Multiple active devices needed to cooperate with the CPU to provide services (e.g. read a disk block)
multiple active "sequential execution" streams, in the CPU and the controller
communications with I/O devices is inherently asyncronous
I/O controllers had varying response times and the CPU can not simply wait
If something has to happen event
To print the checksum
xxxxxxxxxx151void computeChecksumAndPrint (char* buf, int blockNum, int numBytes) {2 int xsum = 0;3 for (int i = 0); i < numBytes; i++)4 xsum ^= buf [i];5 printf ("0x%1x\n", xsum);6 free (buf);7}89void checksum (blockNum, numBytes, whenComplete) {10 char* buf = malloc (numBytes);11 12 diskRead (buf, blockNum, numBytes, whenComplete);13}1415void checksum (1234, 4096, computeAndPrintChecksum)Huge problem
An abstraction for execution
Creating and starting a htread
Stopping and re-starting a thread
Joining with a thead
xxxxxxxxxx81void uthread_init (int num_processors);2uthread_t uthread_create (void* (*proc)(void*), void* arg);3void uthread_detach (uthread_t t);4void uthread_join (uthread_t t, void **vp);5uthread_t uthread_self ();6void uthread_yield ();7void uthread_block ();8void uthread_unblock (uthread_t thread);Explained
uthread_t thread id data type
uthread_init is called once to initialize the thread systemuthread_create create and start a thread to run a specified procedureuthread_yieldtemporarily stop current thread if other threads waitinguthread_join join calling thread with specified other thread and get return valueuthread_detach indicate thread no thread will join specified threaduthread_self a pointer to the TCB of the current threaduthread_block block current threaduthread_unblock unblock specified thread and make it runnableGive up CPU if there's another thread that can run (i.e., pong())'
xxxxxxxxxx81void* ping (void* v) {2 int i;3 for (i = 0; i < 100; i++) {4 printf("I");5 uthread_yield();6 }7 return 0;8}Give up CPU if there's another thread that can run (i.e., ping())
xxxxxxxxxx81void* pong (void* v) {2 int i;3 for (i = 0; i < 100; i++) {4 printf("O");5 uthread_yield();6 }7 return 0;8}Give up CPU to wait for ping() to return and thus its thread to finish
xxxxxxxxxx81void ping_pong () {2 uthread_t t0, t1;3 uthread_init(1);4 t0 = uthread_create(ping, 0);5 t1 = uthread_create(pong, 0);6 uthread_join(t0, 0);7 uthread_join(t1, 0);8}A program that reads a block from disk
xxxxxxxxxx21read (buf, siz, blkNo); // read siz bytes at blkNo into buf2nowHaveBlock (buf, siz); // now do something with the block xxxxxxxxxx21asyncRead (buf, siz, blkNo, nowHaveBlock);2doSomethingElse ();As a timeline
Create two threads that CPU runs, one at a time
Illusion of synchrony
xxxxxxxxxx31asyncRead (buf, siz, blkNo);2blockToWaitForInterrupt ();3nowHowBlock (buf, siz); xxxxxxxxxx31interruptHandler() {2 unblockWaitingThread();3}We wanted to do this, but couldn't because risk reads are asyncronous...
We implemented it this way in event-driven programming style...
Now we can do this...
We implemented it this way using threads to hide asynchrony...
The key new thing is blocking and unblocking
Thread State
Thread-Control Block (TCB)
Ready Queue
One or more Block Queues
Thread Scheduling is:
Thread Scheduling Policy
Things you might consider when setting scheduling policy
Priority
When choosing the next thread to run
Implementing Thread Mechanism
organize Ready Queue as a priority queue
priority queue: first-in-first-out among equal-priority threads
Preemption occurs when
Priority-based preemption
Quantum-based preemption
How long should quantum be?
The Problem
Timer Devices
Timer Interrupt Handler
Thread
Threads hide asyncrongy
Thread state
Round-robin, preemptive, priority thread scheduling