Presentation is loading. Please wait.

Presentation is loading. Please wait.

Semaphores and Condition Variables

Similar presentations


Presentation on theme: "Semaphores and Condition Variables"— Presentation transcript:

1 Semaphores and Condition Variables

2 Locks Locks can be used to ensure mutual exclusion in conflicting critical sections. A lock is an object, a data item in memory. Methods: Lock::Acquire and Lock::Release. Threads pair calls to Acquire and Release. Acquire before entering a critical section. Release after leaving a critical section. Between Acquire/Release, the lock is held. Acquire does not return until any previous holder releases. Waiting locks can spin (a spinlock) or block (a mutex). A A R R

3 Nachos Thread States and Transitions
running Thread::Yield (voluntary or involuntary) Thread::Sleep (voluntary) Scheduler::Run blocked ready Scheduler::ReadyToRun currentThread->Yield(); currentThread->Sleep();

4 Example: Per-Thread Counts and Total
/* shared by all threads */ int counters[N]; int total; /* * Increment a counter by a specified value, and keep a running sum. * This is called repeatedly by each of N threads. * tid is a thread identifier unique across all threads. * value is just some arbitrary number. */ void TouchCount(int tid, int value) { counters[tid] += value; total += value; }

5 Reading Between the Lines of C
/* counters[tid] += value; total += value; */ load counters, R1 ; load counters base load 8(SP), R2 ; load tid index shl R2, #2, R2 ; index = index * sizeof(int) add R1, R2, R1 ; compute index to array load 4(SP), R3 ; load value load (R1), R2 ; load counters[tid] add R2, R3, R2 ; counters[tid] += value store R2, (R1) ; store back to counters[tid] load total, R2 ; load total add R2, R3, R2 ; total += value store R2, total ; store total load add store load add store vulnerable between load and store of counters[tid]...but it’s non-shared. vulnerable between load and store of total, which is shared.

6 Using a Lock for the Counter/Sum Example
int counters[N]; int total; Lock *lock; /* * Increment a counter by a specified value, and keep a running sum. */ void TouchCount(int tid, int value) { lock->Acquire(); counters[tid] += value; /* critical section code is atomic...*/ total += value; /* …as long as the lock is held */ lock->Release(); }

7 Portrait of a Lock in Motion

8 Example: A Bounded Resource
int AllocateEntry() { int i; while (!FindFreeItem(&i)) block and wait for a free slot slot[i] = 1; /* grab free slot */ return(i); } void ReleaseEntry(int i) { slot[i] = 0; wakeup waiter, if any boolean FindFreeItem(int* index) { for (i = 0; i < TableSize; i++) if (slot[i] == 0) return it; return (FALSE);

9 Semaphores Mutexes are designed for mutual exclusion; they are not sufficient for higher-level synchronization needs. waiting for an event managing a resource with more than one instance Semaphores handle all of your synchronization needs with one elegant but confusing abstraction. an integer variable with special operations and properties “souped up” increment (Up or V) and decrement (Down or P) current value is the number of resource instances free to allocate atomic/implicit sleep when decrementing a zero semaphore atomic/implicit wakeup when incrementing

10 A Bounded Resource with a Counting Semaphore
A semaphore for an N-way resource is called a counting semaphore. semaphore->Init(N); int AllocateEntry() { int i; semaphore->Down(); ASSERT(FindFreeItem(&i)); slot[i] = 1; return(i); } void ReleaseEntry(int i) { slot[i] = 0; semaphore->Up(); Passing a Down guarantees that a resource instance is reserved for the caller. Problems?

11 Semaphores as Mutexes Mutexes are often called binary semaphores.
Semaphores must be initialized with a value representing the number of free resources: mutexes are a single-use resource. semapohore->Init(1); void Lock::Acquire() { semaphore->Down(); } void Lock::Release() semaphore->Up(); Down() to acquire a resource; blocks if no resource is available. Up() to release a resource; wakes up waiter if any. Up and Down are atomic. Mutexes are often called binary semaphores. However, “real” mutexes have additional constraints on their use.

12 Condition Variables Condition variables allow explicit event notification. much like a souped-up sleep/wakeup associated with a mutex to avoid sleep/wakeup races managing events using semaphores often demands more synchronization, which is “built in” condition variables alternative to counting semaphores for resource allocation “generally safer and more flexible than semaphores” Condition::Wait(Lock*) Condition:: Signal(Lock*) Condition::Broadcast(Lock*)

13 Using Condition Variables
Condition *cv; Lock* cvMx; int waiter = 0; void await() { cvMx->Lock(); waiter = waiter + 1; /* “I’m sleeping” */ cv->Wait(cvMx); /* sleep */ cvMx->Unlock(); } void wakeup() { if (waiter) { cv->Signal(cvMx); waiter = waiter - 1; CvMx->Unlock(); Must hold lock when calling Wait. Wait atomically releases lock and sleeps until next Signal. Wait atomically reacquires lock before returning. Association with mutex allows threads to safely manage state related to the sleep/wakeup coordination (e.g., waiters count).

14 Bounded Resource with a Condition Variable
Mutex* mx; Condition *cv; int AllocateEntry() { int i; mx->Acquire(); while(!FindFreeItem(&i)) cv.Wait(mx); slot[i] = 1; mx->Release(); return(i); } void ReleaseEntry(int i) { slot[i] = 0; cv->Signal(); “Loop before you leap.” Why is this Acquire needed?

15 Semaphores with Condition Variables
void Down() { mutex->Acquire(); ASSERT(count >= 0); while(count == 0) condition->Wait(mutex); count = count - 1; mutex->Release(); } void Up() { count = count + 1; condition->Signal(mutex);

16 Semaphores vs. Condition Variables
1. Up differs from Signal in that: Signal has no effect if no thread is waiting on the condition. Condition variables are not variables! They have no value! Up has the same effect whether or not a thread is waiting. Semaphores retain a memory of all calls to Up. 2. Down differs from Wait in that: Down checks the condition and blocks only if necessary. no need to recheck the condition after returning from Down wait condition is defined internally, but is limited to a counter Wait is explicit: it does not check the condition, ever. condition is defined externally and protected by integrated mutex


Download ppt "Semaphores and Condition Variables"

Similar presentations


Ads by Google