200 likes | 215 Views
Learn about synchronization techniques, deadlocks, pseudo-monitors, hardware & software solutions, semaphores vs. monitors, and implement monitors with semaphores.
E N D
CS444/CS544Operating Systems Deadlock 3/7/2007 Prof. Searleman jets@clarkson.edu
Outline • Summary: Synchronization • Handling Deadlock NOTE: • Next topic: Memory Management, Chapters 8–9 • Makeup class on Friday 3/09/07: • section §10: lab@1:00 in ITL; lecture@2:00 in SC356 • section §20: lecture@1:00 in SC342; lab@2:00 in ITL • Exam#2 – Tues. 3/13, 7:00 pm, SC160
can a newly arriving reader enter the queue for OKtoRead? could this starve a waiting writer? Recap: Reader/Writer Monitor void startRead(){ if ( busy || (waitingWriters > 0) ) { waitingReader++; OKtoRead.wait(); waitingReaders--; } readercount = readercount + 1; OKtoRead.signal(); } void endRead(){ readercount = readercount - 1; if (readercount == 0) OKtoWrite.signal(); }
// Monitor procedures for writers: void startWrite(){ if ( (readercount != 0) || busy ) { waitingWriters++; OKtoWrite.wait(); waitingWriters--; } busy = true; } void endWrite(){ busy = false; if (waitingReaders > 0) OKtoRead.signal(); else OKtoWrite.signal(); }
Remember • Game is obtaining highest possible degree of concurrency and greatest ease of programming • Tension • Simple high granularity locks easy to program • Simple high granularity locks often means low concurrency • Getting more concurrency means • Finer granularity locks, more locks • More complicated rules for concurrent access
Pseudo-Monitors • Monitor = a lock (implied/added by compiler) for mutual exclusion PLUS zero or more condition variables to express ordering constraints • What if we wanted to have monitor without programming language support? • Declare locks and then associate condition variables with a lock • If wait on the condition variable, then release the lock • Java – “synchronized” methods
Example: Pseudo-monitors pthread_mutex_t monitorLock; pthread_cond_t conditionVar; void pseudoMonitorProc(void) { pthread_mutex_lock(&mutexLock); ….. pthread_cond_wait(&conditionVar, &monitorLock); …. pthread_mutex_unlock(&mutexLock); }
Synchronization Mechanisms (blocks other threads from running) • Hardware Solutions • disable/enable interrupts • uninterruptible machine instruction (e.g. test-and-set, swap) • Software Solutions • Peterson’s solution and variations • semaphores: • counting & binary semaphores • spinlock semaphores • monitors • condition variables • Thread packages: mutex (lock), condition variables, reader-writer locks • Events, Message Passing, Timers, Regions, and others… (busy waiting) (busy waiting) (blocking) (busy waiting) (blocking) (blocking)
Software Synchronization Primitives Summary • Locks • Simple semantics, often close to HW primitives • Can be inefficient if implemented as a spin lock • Semaphores • Internal queue – more efficient if integrated with scheduler • Monitors • Language constructs that automate the locking • Easy to program with where supported and where model fits the task • Once add in condition variables much of complexity is back • Events/Messages • Simple model of synchronization via data sent over a channel
Semaphores vs Monitors • If have one you can implement the other…
Converting a monitor solution to a semaphore solution Basic concept: • Each condition c; simulated with semaphore cSem = 0; • For mutual exclusion, introduce a new semaphore: semaphore mutex = 1; • A wait on a condition variable c: c.wait() becomes: signal(mutex); // release exclusion wait(cSem); // block wait(mutex); // regain exclusion before accessing // shared variables • What about a signal on a condition variable?
Implementing Monitors with Semaphores conditionVariable_t { int count; semaphore_t sem; } condWait (conditionVariable_t *x) { //one more waiting on this cond x->count = x_count++; if (nextCount > 0){ signal(next); //wake up someone } else { signal (mutex); } wait(x->sem); x->count = x->count--; } condSignal(conditionVariable_t *x){ //if no one waiting do nothing! if (x->count > 0){ next_count = nextCount++; signal(x->sem); wait (next); nextCount--; } } semaphore_t mutex, next; int nextCount = 1; Initialization code: mutex.value = 1; next.value = 0; For each procedure P in Monitor, implement P as Wait (mutex); unsynchronizedBodyOfP(); if (nextCount >0){ signal(next); }else { signal(mutex); }
Implementing Semaphores With Monitors Monitor semaphore { int value; condition waitQueue; void setValue(int value){ value = newValue; } int getValue(){ return value; } void wait(){ value--; while (value < 0){ //Notice Mesa semantics condWait(&waitQueue); } } void signal(){ value++; condSignal(&waitQueue); } } //end monitor semaphore
Need for Synchronization Have a number of cooperating, sequential processes/threads running asynchronously. When must they synchronize? • When timing or ordering of execution is required • e.g. one process/thread must wait for another • When sharing a resource • Each process/thread does the following request/acquire the resource; use the resource; release the resource; resources: shared variables/files, buffers, devices (such as printers), databases, etc.
Criteria for a “good” solution • Mutual exclusion is preserved • The progress requirement is satisfied • The bounded-waiting requirement is met. In other words, you want the solution to be • correct (under any circumstances) without any assumptions about relative running times (no race conditions possible) • fair • not subject to starvation (indefinite postponement) or deadlock
Synchronization Mechanisms It is common for Operating Systems to have a variety of synchronization mechanisms. • Solaris • adaptive mutexes, condition variables, semaphores, reader-writer locks, turnstiles • Windows XP • dispatcher objects: mutexes, semaphores, events, timers • Linux • spinlocks, semaphores, reader-writer locks, Pthread API (mutex locks, condition variables, read-write locks) Why??
Summary: Synchronization • Synchronization primitives all boil down to controlling access to a shared state (or resource) with a small amount of additional shared state • All need to be built on top of HW support • Once have one kind, can implement the others • Which one you use is a matter of matching the primitive to the problem • short-term locking: spinlocks, mutexes • longer-term locking: counting semaphores, condition variables • read-only access with occasional writes: reader-writer locks
Deadlock (aka “Deadly Embrace”) Compliments of Oleg Dulin, CS major, Clarkson alumni
Methods for Handling Deadlock • Allow deadlock to occur, but… • Ignore it (ostrich algorithm) • Detection and recovery • Ensure that deadlock never occurs, by… • Prevention (negate at least 1 of the 4 necessary conditions for deadlock to occur) • Dynamic avoidance (be careful) What are the consequences? May be expensive Constrains how requests for resources can be made Processes must give maximum requests in advance