© Janice Regan, CMPT 300, May CMPT 300 Introduction to Operating Systems Mutual Exclusion Mutexes, Semaphores
© Janice Regan, CMPT 300, General form, mutual exclusion No matter how we implement mutual exclusion, conceptually the following happens in each process using the resource protected my mutal exclusion NonCriticalRegion() StartCriticalRegion() CriticalRegion() EndCriticalRegion() NonCritical Regtion()
© Janice Regan, CMPT 300, Implementation Now we have the basic ideas we need How do we actually implement mutual exclusion? There are several approaches Interrupt disabling Lock variables Strict alternation Special instructions Peterson’s solution Message passing Semaphores and Mutexes Monitors
© Janice Regan, CMPT 300, More about implementation We have looked at the first five approaches (both hardware and software solutions). All these solutions Are based on indirect sharing Processes do not directly communicate Processes may be competing or indirectly collaborating Busy waiting (or interrupt disabling) is used to prevent processes from entering critical zones when the resource is busy. Priority inversion is a possible problem How does our solution change when we find methods that will avoid busy waiting
© Janice Regan, CMPT 300, No busy waiting: sleep/wakeup How do we avoid busy waiting? For cooperating processes can use sleep/wakeup (based on signaling) Need some method to make a process wait for another process to finish its critical region Put process to ‘sleep’, suspend the process and stop execution Process does not use CPU while it is ‘asleep’ and waiting its turn When the process’s turn arrives then ‘wakeup’ the process and allow it to enter and execute its critical region
© Janice Regan, CMPT 300, How to How to we put a process to ‘sleep’, or ‘wakeup’ a process? Use signaling to a mutual exclusion structure (variable) called a mutex (a binary semaphore) or semaphore (counting semaphore) The Semaphore (mutex) is the structure including the shared variable that is shared between processes. The execution of a semaphore is an atomic action. Use system calls (or thread library) to suspend or restart the process Two signaling functions are needed (to make system calls) one to put a process to sleep one to wake it up
© Janice Regan, CMPT 300, Mutex vs Semaphore When using a mutex (binary semaphore) Only a single resource can be managed (for example one DMA) Only useful for mutual exclusion A mutex is a special case of a semaphore When using a semaphore May manage more than one device of the same type with a counting semaphore Can be used for queuing (sharing or multiple similar resources)
© Janice Regan, CMPT 300, Counting semaphore signals Struct semaphore{ int countblocked; queueType queueUpOrDown; }; void semWait( semaphore s) { s.countblocked--; if(s.countblocked < 0) { /*put process in blocked.queue block process */ } void semSignal( semaphore s) { s.countblocked++; if(s.countblocked <= 0) { /* remove a process from blocked.queue put process in ready queue*/ }
© Janice Regan, CMPT 300, Semaphore wait operation: go to sleep The semWait operation Decrements the semaphore value If the value is >=0, the process is allowed to run its critical region If the value is negative then the process is blocked (put to sleep) and placed in the blocked queue
© Janice Regan, CMPT 300, Semaphore signal operation: wakeup The semSignal operation Increments the semaphore value If the semaphore value is not positive (<=0) the first process in the blocked queue is woken up and placed in the ready queue
© Janice Regan, CMPT 300, Example: counting semaphore Assume 4 processes A, B, C, D Processes A B C and D share a single resource semWait(A) // A claims resource or queues for it A uses resource semSignal(A) // A gives back resource Before beginning process A has run and is presently using the resource (may be waiting for interrupt, or ready to continue) Process A reaches the end of its time slice and is replaced by D Begin with D running. D executes a semWait( ) while preparing to use the shared resource. The semWait( ) decrements the semaphore. Because the semaphore is now -1(<0) process D is blocked and placed in the blocked queue. (D has not yet accessed the resource)
© Janice Regan, CMPT 300, Counting semaphore operation C D processor A Semaphore 1 Blocked queue Ready queue B C D processor A Semaphore 0 Blocked queue Ready queue SemWait for A: Step 1 Decrement semaphore B
© Janice Regan, CMPT 300, Counting semaphore operation B C processor D Semaphore 0 Blocked queue Ready queue D A B processor C Semaphore Blocked queue Ready queue After SemWait for D A Proc A ready to use resource but swapped at end of time slice
© Janice Regan, CMPT 300, Example: counting semaphore This allows Process C to be loaded into CPU C executes a semWait( ) while preparing to access the shared resource The semWait( ) decrements the semaphore. Because the semaphore is now -2(<0) the process is blocked and placed in the blocked queue. This allows Process B to be loaded into the CPU B executes a semWait( ) while preparing to access the shared resource The semWait( ) decrements the semaphore. Because the semaphore is now -3(<0) the process is blocked and placed in the blocked queue.
© Janice Regan, CMPT 300, Counting semaphore operation C D A processor B semaphore -2 Blocked queue Ready queue C B D processor A semaphore -3 Blocked queue Ready queue After semWait for C After semWait for B
© Janice Regan, CMPT 300, Example: counting semaphore This allows Process A to be loaded into the CPU. Process A has already completed its semWait() and is ready to complete use the resource. A uses the resource and then executes a semSignal( ) to indicate that it no longer needs the resource The semSignal( ) increments the semaphore. Because the semaphore is now -2(<=0) the first process in the blocked queue, D, is woken up and placed at the end of the ready queue. Process A continues until it is removed by the scheduler an replaced with process D (from the ready queue).
© Janice Regan, CMPT 300, Counting Semaphore operation B C D processor A Semaphore -2 Blocked queue Ready queue B C A processor D Semaphore -2 Blocked queue Ready queue After semSignal for A After A completes its time slice
© Janice Regan, CMPT 300, Example: counting semaphore This allows Process D to be loaded into the CPU. Process D has already completed its semWait() and is ready to use the resource. D uses the resource and then executes a semSignal( ) to indicate that it no longer needs the resource The semSignal( ) increments the semaphore. Because the semaphore is now -1(<=0) the first process in the blocked queue, C, is woken up and placed at the end of the ready queue. Process D continues until it is removed by the scheduler an replaced with process A (from the ready queue). D is placed at the end of the ready queue.
© Janice Regan, CMPT 300, Counting Semaphore operation B C A processor D Semaphore Blocked queue Ready queue B D C processor A Semaphore Blocked queue Ready queue After semSignal for D After D completes its time slice
© Janice Regan, CMPT 300, Example: counting semaphore This allows Process A to be loaded into the CPU. Process A continues until it is removed by the scheduler an replaced with process C (from the ready queue). A goes to the end of the ready queue Process C has already completed its semWait() and is ready to use the resource. C uses the resource and then executes a semSignal( ) to indicate that it no longer needs the resource The semSignal( ) increments the semaphore. Because the semaphore is now 0(<=0) the first process in the blocked queue, B, is woken up and placed at the end of the ready queue.
© Janice Regan, CMPT 300, Counting Semaphore operation B A D processor C Semaphore Blocked queue Ready queue A B D processor C Semaphore 0 Blocked queue Ready queue After A completes its time slice After C’s semSignal
© Janice Regan, CMPT 300, Example: counting semaphore Process C continues until it is removed by the scheduler and replaced with process D (from the ready queue). Process C will be placed at the end of the ready queue Process D continues until it is removed by the scheduler an replaced with process A (from the ready queue). Process D will be placed at the end of the ready queue Process A continues until it is removed by the scheduler an replaced with process B (from the ready queue). Process A will be placed at the end of the ready queue Process B has already completed its semWait() and is ready to use the resource. After using the resource process C executes a semSignal(). The semSignal( ) increments the semaphore. Because the semaphore is now 1 (not <=0) execution of process B continues
© Janice Regan, CMPT 300, Counting semaphore operation B C A processor D Semaphore 0 Blocked queue Ready queue C D B processor A Semaphore 1 Blocked queue Ready queue After C completes its time slice After D completes its time slice
© Janice Regan, CMPT 300, Counting semaphore operation D A C processor B Semaphore 0 Blocked queue Ready queue D A C processor B Semaphore 1 Blocked queue Ready queue semSignal for B After A completes its time slice
Using Semaphores In the previous example we started with the semaphore value being 1. If we were sharing 5 DMAs, we could have set the initial value of the semaphore to 5. Then each time a process asked for a DMA it would be given one and the number of available DMAs would be decremented. When the number of available DMAs reached 0 subsequent processes would be blocked until one of the DMAs completed and signaled the semaphore © Janice Regan, CMPT 300,
© Janice Regan, CMPT 300, Mutex signals Struct mutex{ enum[zero, one] runBlock; queueType queueRunOrBlock; }; void mutexWait( mutex s) { if(s.runBlock == 1) { s.runBlock = 0; } else { //put process in sleep.queue //block process } void mutexSignal( mutex s) { if(sleepQueueEmpty() ) { s.runBlock= 1; } else { // remove a process from sleep.queue //put process in ready queue }
© Janice Regan, CMPT 300, Mutex wait operation: go to sleep The mutexWait operation Checks the semaphore value If the value is 1, the value is changed to 0 and the process is allowed to run its critical region If the value is 0 then the process is blocked (put to sleep) and placed in the blocked queue
© Janice Regan, CMPT 300, Mutex signal operation: wakeup The mutexSignal operation Checks if there are any processes that are presently blocked (in the blocked queue) If there are processes in the blocked queue,unblock the first process in the queue If there are no processes in the blocked queue set the semaphore value to 1
© Janice Regan, CMPT 300, Mutex operation C D processor idle Mutex 1 Blocked queue Ready queue B C processor D Mutex 1 Blocked queue Ready queue I nitial State D begins to run A B A
© Janice Regan, CMPT 300, Mutex operation B C processor D Mutex 0 Blocked queue Ready queue A A B processor C Mutex 0 Blocked queue Ready queue MutexWait for D: Step 1 Check and Set Mutex to 0 D Proc D ready to use resource but swapped at end of time slice Check mutex value then set to 0
© Janice Regan, CMPT 300, Mutex operation A B processor C Mutex 0 Blocked queue Ready queue D C D A processor B Mutex 0 Blocked queue Ready queue MutexWait for C: Step 1 Check Mutex is 0 Mutex wait for C: step 2 Add C to blocked queue Check mutex value
© Janice Regan, CMPT 300, Mutex operation C D A processor B Mutex 0 Blocked queue Ready queue B C D processor A Mutex 0 Blocked queue Ready queue MutexWait for B: Step 1 Check Mutex is 0 Mutex wait for B step 2 Add B to blocked queue Check mutex value
© Janice Regan, CMPT 300, Mutex operation B C D processor A Mutex 0 Blocked queue Ready queue B C processor D Mutex 0 Blocked queue Ready queue MutexWait for A: Step 1 Check Mutex is 0 A Mutex wait for A step 2 Add A to blocked queue Check mutex value
© Janice Regan, CMPT 300, Mutex operation B A C processor D Mutex 0 Blocked queue Ready queue A B C processor D Mutex 0 Blocked queue Ready queue D uses resource: MutexSignal D: step1 MutexSignal for D step 2 move process to ready queue Check for processes in blocked queue
© Janice Regan, CMPT 300, Mutex operation A B D processor C Mutex 0 Blocked queue Ready queue Time slice for D complete
© Janice Regan, CMPT 300, Mutex operation A B D processor C Mutex 0 Blocked queue Ready queue A B D processor C Mutex 0 Blocked queue Ready queue C uses resource: MutexSignal C: step1 MutexSignal for C step 2 move to ready queue Check for processes in blocked queue
© Janice Regan, CMPT 300, Mutex operation A C B processor D Mutex 0 Blocked queue Ready queue Time slice for C complete A D C processor B Mutex 0 Blocked queue Ready queue Time slice for D complete
Check for processes in blocked queue © Janice Regan, CMPT 300, Mutex operation A D C processor B Mutex 0 Blocked queue Ready queue D A C processor B Mutex 0 Blocked queue Ready queue B uses resource: MutexSignal B: step1 MutexSignal for B step 2 move process to ready queue
© Janice Regan, CMPT 300, Mutex operation A B D processor C Mutex 0 Blocked queue Ready queue Time slice for B complete B C A processor D Mutex 0 Blocked queue Ready queue Time slice for C complete
Check for processes in blocked queue © Janice Regan, CMPT 300, Mutex operation C D B processor A Mutex 0 Blocked queue Ready queue C D B processor A Mutex 1 Blocked queue Ready queue Auses resource: MutexSignalA: step1 MutexSignal for A step 2 set mutex value to 1