Download presentation
Presentation is loading. Please wait.
1
Synchronization: semaphores and some more stuff 1 Operating Systems, 2011, Danny Hendler & Amnon Meisels
2
What's wrong with busy waiting? Doesn‘t make sense for Uni-processor o May cause priority inversion and deadlock Wastes CPU time o But is efficient if waiting-time is short The mutual exclusion algorithms we saw used busy-waiting. What’s wrong with that? 2 Operating Systems, 2011, Danny Hendler & Amnon Meisels
3
What's wrong with busy waiting? Busy waiting may cause priority-inversion and deadlock Process A's priority is higher than process B's Process B enters the CS Process A needs to enter the CS, busy-waits for B to exit the CS Process B cannot execute as long as the higher-priority process A is executing/ready Priority inversion and deadlock result 3 Operating Systems, 2011, Danny Hendler & Amnon Meisels
4
Outline Semaphores and the producer/consumer problem Counting semaphores from binary semaphores Event counters and message passing synchronization 4 Operating Systems, 2011, Danny Hendler & Amnon Meisels
5
Semaphores up(S) [the `v’ operation] If there are blocked processes, wake-up one of them Else S++ down(S) [the ‘p’ operation] If S ≤ 0 the process is blocked. It will resume execution only after it is woken-up Else S-- Two atomic operations are supported by a semaphore S: S is non-negative Supported by Windows, Unix, … 5 Operating Systems, 2011, Danny Hendler & Amnon Meisels
6
Semaphores: is the following correct? up(S) [the `v’ operation] S++ If there are blocked processes, wake-up one of them down(S) [the ‘p’ operation] If S ≤ 0 the process is blocked. It will resume execution only after it is woken-up S-- Two atomic operations are supported by a semaphore S: 6 Operating Systems, 2011, Danny Hendler & Amnon Meisels
7
7 Consider the following bad scneario: down(S) S=0 and process A performs down(S) – A is blocked up(S)S=1 Process B performs up(S) – S=1 A is ready down(S) S=0 & C proceeds Process C performs down(S) – S=0 & C proceeds S=0 Process A gets a time-slice and proceeds – S=0 A single up() freed 2 down()s Operating Systems, 2011, Danny Hendler & Amnon Meisels Pseudo-code in previous slide is wrong
8
Implementing mutex with semaphores Shared data: semaphore lock; /* initially lock = 1 down(lock) Critical section up(lock) Does the algorithm satisfy mutex? Does it satisfy deadlock-freedom? Does it satisfy starvation-freedom? Yes Depends… 8 Operating Systems, 2011, Danny Hendler & Amnon Meisels
9
9
10
More on synchronization using semaphores Three processes p1; p2; p3 semaphoress1 = 1, s2 = 0; p1p2p3 s1s2s2 down(s1);down(s2);down(s2); A B C s2s2s1 up(s2);up(s2);up(s1); Which execution orders of A, B, C, are possible? (A B* C)* 10 Operating Systems, 2011, Danny Hendler & Amnon Meisels
11
P 0 P 1 down(S); down(Q); down(Q); down(S); move1 move2 up(S); up(Q); up(Q) up(S); 1 1 Example: move money between two accounts which are protected by semaphores S and Q No guarantee for correct synchronization Does this work? Deadlock! 11 Operating Systems, 2011, Danny Hendler & Amnon Meisels
12
Negative-valued semaphores up(S) S++ If there are blocked processes (i.e. S ≤ 0), wake-up one of them -3 down(S ) S-- If S<0 the process is blocked. It will resume execution only when S is non-negative Two atomic operations are supported by a semaphore S: If S is negative, then there are –S blocked processes 12 Operating Systems, 2011, Danny Hendler & Amnon Meisels
13
type semaphore = record value: integer; L: list of process; end; Negative semaphore Implementation -3 atomic down(S): S.value--; if (S.value < 0) { add this process to S.L; sleep; } atomic up(S): S.value++; if (S.value <= 0) { remove a process P from S.L; wakeup(P); } 13 Operating Systems, 2011, Danny Hendler & Amnon Meisels L
14
Producer-Consumer Problem Paradigm for cooperating processes, producer process produces information that is consumed by a consumer process Two versions unbounded-buffer places no practical limit on the size of the buffer bounded-buffer assumes that there is a fixed buffer size buffer in out 14 Operating Systems, 2011, Danny Hendler & Amnon Meisels
15
2 6 Out In item1 item4 item3 item2 consumer 0 buffer producer Bounded Buffer 1 2 3 4 5 7 15 Operating Systems, 2011, Danny Hendler & Amnon Meisels
16
Implementation using semaphores Two processes or more use a shared buffer in memory bounded The buffer has finite size(i.e., it is bounded) The producer writes to the buffer and the consumer reads from it full buffer A full buffer stops the producer empty buffer An empty buffer stops the consumer 16 Operating Systems, 2011, Danny Hendler & Amnon Meisels
17
Producer-Consumer Producer-Consumer implementation from semaphores #defineN100/* Buffer size */ semaphore typedefintsemaphore; semaphore semaphoremutex = 1;/* access control to critical section */ semaphore semaphoreempty = N;/* counts empty buffer slots */ semaphore semaphorefull = 0;/* counts full slots */ void producer(void) { intitem; while(TRUE) { produce_item(&item);/* generate something... */ down down(&empty);/* decrement count of empty */ down down(&mutex);/* enter critical section */ enter_item(item);/* insert into buffer */ up up(&mutex);/* leave critical section */ up up(&full);/* increment count of full slots */} 17 Operating Systems, 2011, Danny Hendler & Amnon Meisels
18
consumer down down up up void consumer(void) { intitem; while(TRUE){ down(&full);/* decrement count of full */ down(&mutex); /* enter critical section */ remove_item(&item);/* take item from buffer) */ up(&mutex);/* leave critical section */ up(&empty);/* update count of empty */ consume_item(item);/* do something... */ } } 18 Operating Systems, 2011, Danny Hendler & Amnon Meisels Producer-Consumer Producer-Consumer implementation from semaphores
19
Implementing a binary semaphore with TSL (a.k.a. a spin-lock) In user space, one can use TSL (test-set-lock)mutex_lock: TSLREG, mutex CMPREG, #0 ok JZEok thread_yield CALLthread_yield JMP mutex_lockok: RETmutex_unlock: MOVmutex, #0 RET 19 Operating Systems, 2011, Danny Hendler & Amnon Meisels
20
type semaphore = record value, flag: integer; L: list of process; end; -3 down(S): repeat until test-and-set(S.flag) S.value--; if (S.value < 0) { add this process to S.L; S.flag=0 sleep; } else S.flag=0 Implementing a negative semaphore with TSL up(S): repeat until test-and-set(S.flag) S.value++; if (S.value <= 0) { remove a process P from S.L; wakeup(P); } S.flag=0 20 Operating Systems, 2011, Danny Hendler & Amnon Meisels L Any problem with this code? In down(), resetting flag and sleeping should be atomic.
21
More on semaphore implementation TSL implementation works for multi-processors On a uni-processor, may be implemented by disabling interrupts On a multi-processor, we can use spin-lock mutual exclusion to protect semaphore access Why is this better than busy-waiting in the 1 st place? Busy-waiting is now guaranteed to be very short 21 Operating Systems, 2011, Danny Hendler & Amnon Meisels
22
Outline Semaphores and the producer/consumer problem Counting semaphores from binary semaphores Event counters and message passing synchronization 22 Operating Systems, 2011, Danny Hendler & Amnon Meisels
23
23 Operating Systems, 2011, Danny Hendler & Amnon Meisels Assumes only values 0 or 1 Wait blocks if semaphore=0 Signal (up operation) either wakes up a waiting thread, if there is one, or sets value to 1 (if value is already 1, signal is “wasted”) How can we implement a counting semaphore from binary semaphore? Binary Semaphore
24
Implementing a counting semaphore from binary semaphores: take 1 down(S): down(S1); S S.value--; S if(S.value < 0){ up(S1); down(S2); } else up(S1); binary-semaphore S1, S2 initially 1; S.value initially 1 up(S): down(S1); S S.value++; S if(S.value ≤ 0) up(S2); up(S1) This code does not work. Why? 24 Operating Systems, 2011, Danny Hendler & Amnon Meisels L1: L2:
25
Race condition for counting semaphore take 1 1.Processes Q1 – Q4 perform down(S), Q2 – Q4 are preempted between lines L1 and L2: the value of the counting semaphore is now -3 2.Processes Q5-Q7 now perform up(S): the value of the counting semaphore is now 0 3.Now, Q2-Q4 wake-up in turn and perform line L2 (down S2) 4.Q2 runs but Q3-Q4 block. 25 Operating Systems, 2011, Danny Hendler & Amnon Meisels There is a discrepancy between the value of S and the number of processes waiting on it
26
Implementing a counting semaphore from binary semaphores: take 2 down(S): down(S1); S S.value--; S if(S.value < 0){ up(S1); //L1 down(S2); } //L2 up(S1); binary-semaphore S1=1, S2=1; S.value initially 1 up(S): down(S1); S S.value++; S if(S.value ≤ 0) up(S2); else up(S1) Does this code work? 26 Operating Systems, 2011, Danny Hendler & Amnon Meisels
27
only if no process waits on S2 up(S1) is performed by up(S) only if no process waits on S2 Q5 leaves up(S) without releasing S1 Q6 cannot enter the critical section that protects the counter It can only do so after one of Q2-Q4 releases S1 This generates a “lock-step” situation: an up(), a down(), an up()… The critical section that protects the counter is entered alternately by a producer or a consumer The effect of the added ‘else’ 27 Operating Systems, 2011, Danny Hendler & Amnon Meisels
28
Recall the bounded-buffer algorithm #defineN100 semaphore typedefintsemaphore; semaphore semaphoremutex = 1; semaphore semaphoreempty = N; semaphore semaphorefull = 0; producer void producer(void) { intitem; while(TRUE) { produce_item(&item); down down(&empty); down down(&mutex); enter_item(item); up up(&mutex); up up(&full);} consumer down down up up void consumer(void) { intitem; while(TRUE){ down(&full); down(&mutex); remove_item(&item); up(&mutex); up(&empty); consume_item(item); } } 28 Operating Systems, 2011, Danny Hendler & Amnon Meisels
29
A Problematic Scheduling Scenario Consider a Bounded buffer of 5 slots. Assume there are 6 processes each filling five slots in turn. Empty.Value = 5 21 34 56 29 Operating Systems, 2011, Danny Hendler & Amnon Meisels
30
A Problematic Scheduling Scenario 1. 1. five slots are filled by the first producer Empty.Value = 0 21 34 56 30 Operating Systems, 2011, Danny Hendler & Amnon Meisels
31
A Problematic Scheduling Scenario 1. 1. The second producer is blocked Empty.Value = -1 21 34 56 31 Operating Systems, 2011, Danny Hendler & Amnon Meisels
32
A Problematic Scheduling Scenario 1. 1. The third producer is blocked Empty.Value = -2 21 34 56 32 Operating Systems, 2011, Danny Hendler & Amnon Meisels
33
A Problematic Scheduling Scenario 1 1. The fourth producer is blocked Empty.Value = -3 21 34 56 33 Operating Systems, 2011, Danny Hendler & Amnon Meisels
34
A Problematic Scheduling Scenario 1. 1. The fifth producer is blocked Empty.Value = -4 21 34 56 34 Operating Systems, 2011, Danny Hendler & Amnon Meisels
35
A Problematic Scheduling Scenario 2. 2. All blocked producers are waiting on S2 Empty.Value = -5 21 34 56 35 Operating Systems, 2011, Danny Hendler & Amnon Meisels
36
A Problematic Scheduling Scenario 3. 3. The consumer consumes an item and is blocked on Empty.S1 until a producer adds an item. Empty.Value = -5 21 34 56 36 Operating Systems, 2011, Danny Hendler & Amnon Meisels
37
A Problematic Scheduling Scenario 3. 3. The consumer consumes an item and is blocked on S1, one producer adds an item. Empty.Value = -4 21 34 56 37 Operating Systems, 2011, Danny Hendler & Amnon Meisels
38
A Problematic Scheduling Scenario 4 4. Consumer must consume, only then another producer wakes up and produces an item Empty.Value = -3 21 34 56 38 Operating Systems, 2011, Danny Hendler & Amnon Meisels
39
A Problematic Scheduling Scenario 4. 4. Same as in step 3. Empty.Value = -2 21 34 56 39 Operating Systems, 2011, Danny Hendler & Amnon Meisels
40
A Problematic Scheduling Scenario 5. 5. And again… Empty.Value = -1 21 34 56 40 Operating Systems, 2011, Danny Hendler & Amnon Meisels
41
Implementing a counting semaphore from binary semaphores: take 3 (P.A. Kearns, 1988) down(S) down(S1); S S.value--; S if(S.value < 0){ up(S1); //L1 down(S2); //L2 down(S1); S S.wake--; //L3 S if(S.wake > 0) then up(S2);} //L3 up(S1); up(S): down(S1); S S.value++; S if(S.value <= 0) { S S.wake++; up(S2); } up(S1); binary-semaphore S1=1, S2=0, value initially 1, integer wake=0 Does THIS work? 41 Operating Systems, 2011, Danny Hendler & Amnon Meisels
42
Correctness arguments (Kearns)… S.wakedown(S) The counter S.wake is used when processes performing down(S) are preempted between lines L1 and L2 up(S) In such a case, up(S2) performed by processes during up(S) have no effect S.wake However, these processes accumulate their waking signals on the (protected) counter S.wake S.wake After preemption is over, any single process that wakes up from its block on down(S2) checks the value of S.wake The check is again protected For each count of the wake-up signals, the awakened process performs the up(S2) (in line L3) Each re-scheduled process wakes up the next one 42 Operating Systems, 2011, Danny Hendler & Amnon Meisels
43
Kearns' algorithm is wrong down(S), Processes P0..P7 perform down(S), P0 goes through, P1..P7 are preempted just after line L2 of the operation up(S) Processes P8..P11 perform up(S) and their up(S2) operations release, say, P1..P4 S.wake = 4 Processes P5, P6, P7 are still waiting on S2 and S.wake = 4 Processes P1..P4 are ready, just before line L3 S.wake Each of P1..P3 will decrement S.wake in its turn, check that it's positive and signal one of P5..P7 Four up operations have released 7 down operations 43 Operating Systems, 2011, Danny Hendler & Amnon Meisels
44
Implementing a counting semaphore from binary semaphores: take 4 (Hemmendinger, 1989) down(S) down(S1); S S.value--; S if(S.value < 0){ up(S1); down(S2); down(S1); S S.wake--; S if(S.wake > 0) then up(S2);} //3 up(S1); up(S): down(S1); S S.value++; S if(S.value <= 0) { S S.wake++; if (S.wake == 1) up(S2); } up(S1); binary-semaphore S1=1, S2=0, integer wait This works 44 Operating Systems, 2011, Danny Hendler & Amnon Meisels
45
Implementing a counting semaphore from binary semaphores: take 5 (Barz, 1983) down(S) down(S2); down(S1); S.value--; if (S.value>0) then up(S2); up(S1); up(S): down(S1); S.value++; if(S.value == 1) { up(S2); } up(S1); binary-semaphore S1=1, S2=min(1, init_value), value=init_value This works, is simpler, and was published earlier(!)… Can we switch the order of downs in down(S)? 45 Operating Systems, 2011, Danny Hendler & Amnon Meisels
46
Correctness arguments… SSS The critical section is guarded by S1 and each of the operations down(S) and up(S) uses it to correctly update the value of S.value After updating (and inside the critical section) both operations release the S2 semaphore only if value is positive S S S.value is never negative, because any process performing down(S) is blocked at S2 Signals cannot be 'wasted' 46 Operating Systems, 2011, Danny Hendler & Amnon Meisels
47
Fairness of semaphores Order of releasing blocked processes: o Fair o Processes are not allowed multiple entries if others are waiting Another option: o Open competition each time the lock is free o Imitating the Java 'wait' 'notify' mechanism o Starvation is possible 47 Operating Systems, 2011, Danny Hendler & Amnon Meisels
48
Outline Semaphores and the producer/consumer problem Counting semaphores from binary semaphores Event counters and message passing synchronization 48 Operating Systems, 2011, Danny Hendler & Amnon Meisels
49
Event Counters Integer counters with three operations: o Advance(E): increment E by 1, wake up relevant sleepers Sleep if E < v o Await(E,v): wait until E ≥ v. Sleep if E < v o Read(E): return the current value of E Counter value is ever increasing Counter value is ever increasing The Read() operation is not required for the bounded-buffer implementation in the next slide 49 Operating Systems, 2011, Danny Hendler & Amnon Meisels
50
producer-consumer with Event Counters (for a single producer and a single consumer) #defineN100 typedefintevent_counter; event_counterin = 0;/* counts inserted items */ event_counter out = 0;/* items removed from buffer */ void producer(void) { int item, sequence = 0; while(TRUE) { produce_item(&item); sequence = sequence + 1; /* counts items produced */ await(out, sequence - N); /* wait for room in buffer */ enter_item(item); /* insert into buffer */ advance(&in); /* inform consumer */ } } 50 Operating Systems, 2011, Danny Hendler & Amnon Meisels
51
Event counters Event counters (producer-consumer) void consumer(void) { int item, sequence = 0; while(TRUE) { sequence = sequence + 1; /* count items consumed */ await(in, sequence); /* wait for item */ remove_item(&item); /* take item from buffer */ advance(&out); /* inform producer */ consume_item(item); } } 51 Operating Systems, 2011, Danny Hendler & Amnon Meisels
52
Message Passing – no shared memory In a multi-processor system without shared memory, synchronization can be implemented by message passing Implementation issues: o Acknowledgements may be required (messages may be lost) o Message sequence numbers required to avoid message duplication o Unique process addresses across CPUs (domains..) o Authentication (validate sender’s identity, a multi-machine environment…) Two main functions: o send(destination, &message); o receive(source, &message) block while waiting... 52 Operating Systems, 2011, Danny Hendler & Amnon Meisels
53
Message Passing Producer-consumer with Message Passing #defineN100 #define MSIZE4/* message size */ typedefintmessage(MSIZE); void producer(void) { int item; message m;/* message buffer */ while(TRUE) { produce_item(&item); receive(consumer, &m);/*wait for an empty */ construct_message(&m, item); send(consumer, &m);/* send item */ } 53 Operating Systems, 2011, Danny Hendler & Amnon Meisels
54
Message passing (cont.) empties void consumer(void) { int item, i; message m; for(i = 0; i < N; i++) send(producer, &m); /* send N empties */ while(TRUE) { receive(producer, &m);/* get message with item */ extract_item(&m, &item); send(producer, &m);/* send an empty reply */ consume_item(item); } } 54 Operating Systems, 2011, Danny Hendler & Amnon Meisels
55
Message passing variations Messages can be addressed to a process address or to a mailbox o Mailboxes are generated with some capacity. When sending a message to a full mailbox, a process blocks o Buffer management done by mailbox Unix pipes - a generalization of messages … no fixed size message (blocking receive) If no buffer is maintained by the system, then send and receive must run in lock-step. Example: Unix rendezvous 55 Operating Systems, 2011, Danny Hendler & Amnon Meisels
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.