semaphores and other wait and signal mechanisms
play

Semaphores and other Wait-and-Signal mechanisms Carsten Griwodz - PDF document

Semaphores and other Wait-and-Signal mechanisms Carsten Griwodz University of Oslo (including slides by Otto Anshus and Kai Li) Critical Regions Four conditions to provide mutual exclusion No two threads simultaneously in critical region 1.


  1. Semaphores and other Wait-and-Signal mechanisms Carsten Griwodz University of Oslo (including slides by Otto Anshus and Kai Li) Critical Regions Four conditions to provide mutual exclusion No two threads simultaneously in critical region 1. No assumptions made about speeds or numbers of CPUs 2. No thread running outside its critical region may block another thread 3. No thread must wait forever to enter its critical region 4.

  2. Critical Regions Mutual exclusion using critical regions Recall Processes and Threads • Process • Thread – Address space – Program counter – Program text and data – Registers – Open files – Stack – Child process IDs – Alarms – Signal handlers – Accounting information • Implemented in kernel or in user space • Threads are the scheduled • Implemented in kernel entities

  3. Producer-Consumer Problem • Main problem description – Two threads – Different actions in the critical region – The consumer can not enter the CR more often than the producer • Two sub-problems – Unbounded PCP: the producer can enter the CR as often as it wants – Bounded PCP: the producer can enter the CR only N times more often than the consumer Unbounded PCP Q PUT (msg) GET (buf) Rules for the queue Q: •No Get when empty Consumer •Q shared, so must have Producer mutex between Put and Get

  4. Recall Mutexes • Can be acquired and released – Only one thread can hold one mutex at a time – A second thread trying to acquire must wait • Mutexes – Can be implemented using busy waiting – Simpler with advanced atomic operations • Disable interrupts, TSL, XCHG, … – Still many approaches using busy waiting – Better implemented using system calls block & unblock Bounded PCP out B in Rules for the buffer B: Capacity: N •No Get when empty •No Put when full GET (buf) PUT (msg) •B shared, so must have mutex between Put and Get Consumer Producer

  5. Mutex Solution Put(msg) { Get(msg) { acquire(mutex); acquire(mutex); <put> while(empty) { release(mutex); release(mutex); Unbounded PCP } acquire(mutex); } <get> release(mutex); Busy waiting } Put(msg) { Get(msg) { acquire(mutex); acquire(mutex); while(full) { while(empty) { release(mutex); release(mutex); Bounded PCP acquire(mutex); acquire(mutex); } } <put> <get> release(mutex); release(mutex); } } Two Kinds of Synchronization LOCK is initially OPEN Acquire (id); Acquire (id); MUTEX <CR> <CR> Release (id); Release (id); Acquire will let first caller through, and then block next until Release LOCK is initially CLOSED CONDITION SYNCHRONIZATION Release (id); Acquire (id); Acquire will block first caller SIGNAL until Release

  6. Sleep and Wakeup / Signal and Wait • Wait (cond) • Signal (cond) – Insert(caller, – Unblock first in cond_queue) cond_queue, or just return if empty – Block this thread No counting, unused signals are ignored Wait is atomic Unbounded PCP using Signal and Wait Q Rules for the queue Q: •No Get when empty GET (buf): •Q shared, so must have mutex PUT (msg): between Put and Get Consumer Producer while(1) { while(1) { if(empty) <process> wait(cond); acquire(mutex); acquire(mutex); <insert> <remove> release(mutex); release(mutex); signal(cond); <process> } }

  7. Unbounded PCP using Signal and Wait Q GET (buf): PUT (msg): Consumer Producer while(1) { while(1) { if(empty) <process> wait(cond); acquire(mutex); acquire(mutex); <insert> <remove> release(mutex); release(mutex); signal(cond); <process> } } Lost signal Unbounded PCP using Signal and Wait Q GET (buf): PUT (msg): Consumer Producer while(1) { while(1) { acquire(mutex); <process> while(empty) { acquire(mutex); wait(cond); <insert> release(mutex); signal(cond); acquire(mutex); release(mutex); Producer can’t enter } } <remove> release(mutex); <process> }

  8. Unbounded PCP using Signal and Wait Q GET (buf): PUT (msg): Consumer Producer while(1) { while(1) { acquire(mutex); <process> while(empty) { acquire(mutex); release(mutex); <insert> wait(cond); signal(cond); acquire(mutex); release(mutex); } } <remove> Lost signal release(mutex); <process> } Threads wait for … • Access to a critical region – Mutex – Semaphore • A condition to be fulfilled – Condition variable – Barrier – Semaphore

  9. Semaphores Semaphores (Dijkstra, 1965) prolaag verhoog • Down or Wait or “P” • Up or Signal or “V” – Atomic – Atomic – Decrement semaphore – Increment semaphore by 1 value by 1 – Wake up a waiting thread if – Block if not positive any P(s) { V(s) { if (--s < 0) if (++s <= 0) Block(s); Unblock(s); } } Can get negative s: counts number of waiting threads s is NOT accessible through other means than calling P and V

  10. Semaphores w/Busy Wait P(s): V(s): while (s <= 0) {}; s++; s--; ATOMIC • Starvation possible? • Does it matter in practice? The Structure of a Semaphore s Threads waiting to get return after calling P (s) when s was <=0 integer sem_wait_queue V (s) P (s) Unblock Block (FIFO is fair) +1 -1 •Atomic: Disable interrupts •Atomic: P() and V() as System calls •Atomic: Entry-Exit protocols

  11. Using Semaphores “The Mutex” “The Signal” s := 0; s := 1; A B P (s); P (s); P (s); V (s); <CR> <CR> V(s); V(s); One thread gets in, next A blocks until B says V blocks until V is executed s := 11 ; “The Team” NB: remember to set the P(s); P(s); <max 11> <max 11> initial semaphore value! V(s); V(s); Up to 11 threads can pass P, the ninth will block until V is said by one of the eight already in there Simple to debug? A x := 0; B y := 0; P (x); P (y); ….. ….. V (x); V (y); What will happen? THEY ARE FOREVER WAITING FOR EACH OTHERS SIGNAL (“No milk”)

  12. Examples Unbounded PCP using Semaphores Q One semaphore for each Rules for the queue Q: condition we must wait •No Get when empty for to become TRUE: GET (buf): •Q shared, so must have PUT (msg): •Q empty: nonempty:=0; mutex between Put and •Q mutex: mutex:=1; Consumer Producer Get PUT (msg): GET (buf): •Is Mutex needed when only 1 P and 1 C? P(mutex); P(nonempty); •PUT at one end, GET at other end <insert> P(mutex); V(mutex); <remove> V(nonempty); V(mutex);

  13. Bounded PCP using Semaphores One semaphore for each Rules for the buffer B: out condition we must wait •No Get when empty for to become TRUE: B •No Put when full •B empty: nonempty:=0; in •B shared, so must have •B full: nonfull:=N Capacity: N mutex between Put and •B mutex: mutex:=1; Get GET (buf): PUT (msg): Consumer Producer PUT (msg): GET (buf): •PUT at one end, GET at other end P(nonfull); P(nonempty); P(mutex); P(mutex); <insert> <remove> V(mutex); V(mutex); V(nonempty); V(nonfull); Dining Philosophers Problem • Five philosopher • Five dishes • Five forks • But a philosopher needs two forks for eating • Usually the philosophers think, when they are hungry the try to eat • How to prevent all philosophers from starving

  14. Dining Philosophers s state •Each: 2 forks to eat • Free •5 philosophers: 10 forks to let all eat concurrently i+1 •5 forks: 2 can eat concurrently i i+1 i Mutex on whole table: P(mutex); T i eat; •1 can eat at a time V(mutex); Get L; Get R; T i P(s(i)); •Deadlock possible P(s(i+1)); eat; V(s(i+1)); S(i) = 1 initially V(s(i)); T i Get L; Get R if free else Put L; •Starvation possible Dining Philosophers To avoid starvation they could look after each other: s state •Thinking • Entry : If L and R is not eating we can •Eating • Exit : If L (R) wants to eat and L.L (R.R) is not i+1 •Want eating we start him eating i i+1 S() = 0 initially i P(mutex); state(i):=Want; if (state(i-1) !=Eating AND state(i+1) != Eating) T i {/*Safe to eat*/ state(i):=Eating; While (1) { V(s(i)); /*Because */ } <think> V(mutex); ENTRY; P(s(i)); /* Init was 0!! <eat> We or neighbor must say V(i) to us!*/ EXIT; } P(mutex); state(i):=Thinking; if (state(i-1)=Want AND state(i-2) !=Eating) { state(i-1):=Eating; V(s(i-1)); /*Start Left neighbor*/ } /*Analogue for Right neighbor*/ V(mutex);

  15. Dining Philosophers s S(i) = 1 initially i+1 T 1 , T 2 , T 3 , T 4 : i i+1 P(s(i)): •Remove the danger of P(s(i+1)); i circular waiting (deadlock) <eat> V(s(i+1)); Can we in a simple way do better •T1-T4: Get L; Get R; V(s(i)); than this one? •T5: Get R; Get L; Get L; Get R; P(s(i)); T 5 •Deadlock possible P(s(i+1)); P(s(1)); eat; P(s(5)); V(s(i+1)); <eat> V(s(i)); V(s(5)); V(s((1)); •Non-symmetric solution. Still quite elegant Readers and Writers Problem • Several threads • Shared data in a critical region • Sometimes a thread wants to read the data • Sometimes a thread wants to change the data • Readers can enter a critical region together • Writers can not enter a critical region together

Recommend


More recommend