Presentation is loading. Please wait.

Presentation is loading. Please wait.

More Synchronization, Semaphores Vivek Pai / Kai Li Princeton University.

Similar presentations


Presentation on theme: "More Synchronization, Semaphores Vivek Pai / Kai Li Princeton University."— Presentation transcript:

1 More Synchronization, Semaphores Vivek Pai / Kai Li Princeton University

2 2 Continuing on Synchronization So far, we’ve seen “Spinning” on lock during entire critical section Disabling interrupts for critical section (bad) Queue associated with each lock & blocking System calls for locking – possibly blocking Since system calls exist, is everything solved? Assume shared variable “count” Lock(&mutex); count++; Unlock(&mutex);

3 3 Cost of Protecting a Shared Variable Making lock system call Pushing parameter, sys call # onto stack Generating trap/interrupt to enter kernel System call in kernel Jump to appropriate function in kernel Verify process passed in valid pointer to mutex Do locking operation, block process if needed Actually change count – load/modify/store System call again to release mutex

4 4 What is Lock Contention? Competition for a lock Uncontended = rarely in use by someone else Contended = often used by someone else Held = currently in use by someone Question: what do these combinations do? Spinning on low-contention lock Spinning on high-contention lock Blocking on low-contention lock Blocking on high-contention lock

5 5 Things to Ponder If critical section is just “count++;”, what is the overhead of the synchronization Is there some other way of doing this? What if you don’t know how long the critical section will be?

6 6 What If You Have the Following Test-and-set – works at either user or kernel System calls for block/unblock Block takes some token and goes to sleep Unblock “wakes up” a waiter on token

7 7 User-Level Acquire/Release using Block and Unblock In what scenarios is this scheme appropriate? Where should it not be used? Acquire(lock) { while (!TAS(lock)) Block( lock ); } Release(lock) { lock = 0; Unblock( lock ); }

8 8 Semaphores (Dijkstra, 1965) Down or “P” Atomic Wait for semaphore to become positive and then decrement by 1 P(s) { if (--s < 0) Block(s); } V(s) { if (++s <= 0) Unblock(s); } Up or “V” –Atomic –Increment semaphore by 1 wake up a waiting P if any

9 9 Bounded Buffer (Consumer-Producer) Example: grep vivek access.log | more ProducerConsumer

10 10 Bounded Buffer w/ Semaphores mutex = 1 emptyCount = N; fullCount = 0; producer() { while (1) { produce an item P(emptyCount); P(mutex); put the item in buffer V(mutex); V(fullCount); } consumer() { while (1) { P(fullCount); P(mutex); take an item from buffer V(mutex); V(emptyCount); consume the item }

11 11 Implementing General Semaphores Need a mutex for each semaphore Block and Unblock need to release mutex after entering their critical section P(s) { Acquire(s.mutex); if (--s.value < 0) Block(s); else Release(s.mutex) } V(s) { Acquire(s.mutex); if (++s.value <= 0) Unblock(s); else Release(s.mutex) }

12 12 Implement General Semaphores with Acquire/Release Kotulski (1988) Two processes call P(s) (when s.value is 0) and preempted after Release(s.mutex) Two other processes call V(s) P(s) { Acquire(s.mutex); if (--s.value < 0) { Release(s.mutex); Acquire(s.delay); } else Release(s.mutex); } V(s) { Acquire(s.mutex); if (++s.value <= 0) Release(s.delay); Release(s.mutex); }

13 13 Hemmendinger’s Solution (1988) The idea is not to release s.mutex and turn it over individually to the waiting process P and V are executing in lockstep P(s) { Acquire(s.mutex); if (--s.value < 0) { Release(s.mutex); Acquire(s.delay); } Release(s.mutex); } V(s) { Acquire(s.mutex); if (++s.value <= 0) Release(s.delay); else Release(s.mutex); }

14 14 Kearns’s Solution (1988) P(s) { Acquire(s.mutex); if (--s.value < 0) { Release(s.mutex); Acquire(s.delay); Acquire(s.mutex); if (--s.wakecount > 0) Release(s.delay); } Release(s.mutex); } V(s) { Acquire(s.mutex); if (++s.value <= 0) { s.wakecount++; Release(s.delay); } Release(s.mutex); } Two Release( s.delay) calls are also possible

15 15 Hemmendinger’s Correction (1989) P(s) { Acquire(s.mutex); if (--s.value < 0) { Release(s.mutex); Acquire(s.delay); Acquire(s.mutex); if (--s.wakecount > 0) Release(s.delay); } Release(s.mutex); } V(s) { Acquire(s.mutex); if (++s.value <= 0) { s.wakecount++; if (s.wakecount == 1) Release(s.delay); } Release(s.mutex); } Correct but a complex solution

16 16 Hsieh’s Solution (1989) Use Acquire(s.delay) to block processes Correct but still a constrained implementation P(s) { Acquire(s.delay); Acquire(s.mutex); if (--s.value > 0) Release(s.delay); Release(s.mutex); } V(s) { Acquire(s.mutex); if (++s.value == 1) Release(s.delay); Release(s.mutex); }


Download ppt "More Synchronization, Semaphores Vivek Pai / Kai Li Princeton University."

Similar presentations


Ads by Google