Post on 18-Dec-2015
Synchronization: semaphoresSynchronization: semaphoresand some more stuffand some more stuff
1Operating Systems, 2011, Danny Hendler & Amnon Meisels
What's wrong with busy waiting?What's wrong with busy waiting?
Doesn‘t make sense for Uni-processoro May cause priority inversion and deadlock
Wastes CPU timeo But is efficient if waiting-time is short
The mutual exclusion algorithms we saw used busy-waiting. What’s wrong with that?
2Operating Systems, 2011, Danny Hendler & Amnon Meisels
What's wrong with busy waiting? What's wrong with busy waiting?
Busy waiting may cause priority-inversion and deadlockBusy 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 resultPriority inversion and deadlock result
3Operating Systems, 2011, Danny Hendler & Amnon Meisels
OutlineOutline
Semaphores and the producer/consumer problem
Counting semaphores from binary semaphores
Event counters and message passing synchronization
4Operating Systems, 2011, Danny Hendler & Amnon Meisels
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, …
5Operating Systems, 2011, Danny Hendler & Amnon Meisels
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:
6Operating Systems, 2011, Danny Hendler & Amnon Meisels
7
Consider the following bad scneario:Consider the following bad scneario: S=0 and process A performs down(S) down(S) – A is blocked Process B performs up(S)up(S) – S=1 S=1 A is ready Process C performs down(S) down(S) – S=0 & C proceedsS=0 & C proceeds Process A gets a time-slice and proceeds – S=0 S=0
A single up() freed 2 down()sA single up() freed 2 down()s
Operating Systems, 2011, Danny Hendler & Amnon Meisels
Pseudo-code in previous slide is wrong
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?
YesYesDepends…
8Operating Systems, 2011, Danny Hendler & Amnon Meisels
Semaphore as a General Synchronization ToolSemaphore as a General Synchronization Tool
Execute B in Pj only after A executed in Pi
Use semaphore flag initialized to 0 Code:
Pi Pj
… …A down(flag)
up(flag) B
Execute B in Pj only after A executed in Pi
Use semaphore flag initialized to 0 Code:
Pi Pj
… …A down(flag)
up(flag) B
0
time
9Operating Systems, 2011, Danny Hendler & Amnon Meisels
More on synchronization using semaphoresMore on synchronization using semaphores
Three processes p1; p2; p3
semaphores s1 = 1, s2 = 0;p1p1 p2p2 p3p3down(s1s1); down(s2s2); down(s2s2);A B Cup(s2s2); up(s2s2); up(s1s1);
Which execution orders of A, B, C, are possible?
(A B* C)*
10Operating Systems, 2011, Danny Hendler & Amnon Meisels
P0 P1
down(S); down(Q); down(Q); down(S);
move1 move2up(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 No guarantee for correct synchronization
Does this work?
Deadlock!
11Operating Systems, 2011, Danny Hendler & Amnon Meisels
Negative-valued semaphoresNegative-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 If S is negative, then there are –S blocked processesprocesses
12Operating Systems, 2011, Danny Hendler & Amnon Meisels
type semaphore = recordvalue: integer; L: list of process;
end;
Negative semaphore ImplementationNegative 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); }
13Operating Systems, 2011, Danny Hendler & Amnon Meisels
L
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
bu
ffer
in
out
14Operating Systems, 2011, Danny Hendler & Amnon Meisels
2
6
Out
In
item1
item4
item3
item2
consumer
0buffer
producer
Bounded Buffer
1
2
3
4
5
7
15Operating Systems, 2011, Danny Hendler & Amnon Meisels
Implementation using semaphoresImplementation using semaphores
Two processes or more use a shared buffer in memory
The buffer has finite size(i.e., it is boundedbounded)
The producer writes to the buffer and the consumer reads from it
A full bufferfull buffer stops the producer
An empty bufferempty buffer stops the consumer
16Operating Systems, 2011, Danny Hendler & Amnon Meisels
Producer-ConsumerProducer-Consumer implementation from semaphores
#define N 100 /* Buffer size */typedef int semaphoresemaphore;semaphoresemaphore mutex = 1; /* access control to critical section */semaphoresemaphore empty = N; /* counts empty buffer slots */semaphoresemaphore full = 0; /* counts full slots */
void producer(void) {int item;while(TRUE) {
produce_item(&item); /* generate something... */downdown(&empty); /* decrement count of empty */downdown(&mutex); /* enter critical section */enter_item(item); /* insert into buffer */upup(&mutex); /* leave critical section */upup(&full); /* increment count of full slots */
} } 17Operating Systems, 2011, Danny Hendler & Amnon Meisels
void consumerconsumer(void){
int item;
while(TRUE) { downdown(&full); /* decrement count of full */ downdown(&mutex); /* enter critical section */ remove_item(&item); /* take item from buffer) */ upup(&mutex); /* leave critical section */ upup(&empty); /* update count of empty */ consume_item(item); /* do something... */
}}
18Operating Systems, 2011, Danny Hendler & Amnon Meisels
Producer-ConsumerProducer-Consumer implementation from semaphores
Implementing a binary semaphore with TSLImplementing a binary semaphore with TSL(a.k.a. a spin-lock)(a.k.a. a spin-lock) In user space, one can use TSL (test-set-lock)mutex_lock:mutex_lock:
TSL REG, mutexCMP REG, #0JZE okokCALL thread_yieldthread_yield
JMP mutex_lockok:ok:
RET
mutex_unlock:mutex_unlock:MOV mutex, #0RET
19Operating Systems, 2011, Danny Hendler & Amnon Meisels
type semaphore = recordvalue, 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 TSLImplementing 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
20Operating Systems, 2011, Danny Hendler & Amnon Meisels
L
Any problem with this code?In down(), resetting flag and sleeping should be atomic.
More on semaphore implementationMore 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 1st
place?Busy-waiting is now guaranteed to be very short
21Operating Systems, 2011, Danny Hendler & Amnon Meisels
Outline
Semaphores and the producer/consumer problem
Counting semaphores from binary semaphores
Event counters and message passing synchronization
22Operating Systems, 2011, Danny Hendler & Amnon Meisels
23Operating 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 SemaphoreBinary Semaphore
Implementing a counting semaphore from binary Implementing a counting semaphore from binary semaphores: semaphores: take 1take 1
down(S):down(S):down(S1);SS.value--;if(SS.value < 0){
up(S1); down(S2); }
else up(S1);
binary-semaphore S1, S2 initially 1; S.value initially 1
up(S):up(S):down(S1);SS.value++;if(SS.value ≤ 0)
up(S2); up(S1)
This code does not work. Why?
24Operating Systems, 2011, Danny Hendler & Amnon Meisels
L1:L2:
Race condition for counting semaphore Race condition for counting semaphore take 1take 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.
25Operating Systems, 2011, Danny Hendler & Amnon Meisels
There is a discrepancy between the value of S and the There is a discrepancy between the value of S and the number of processes waiting on itnumber of processes waiting on it
Implementing a counting semaphore from binary Implementing a counting semaphore from binary semaphores: semaphores: take 2take 2
down(S):down(S):down(S1);SS.value--;if(SS.value < 0){
up(S1); //L1
down(S2); } //L2up(S1);
binary-semaphore S1=1, S2=1; S.value initially 1
up(S):up(S):down(S1);
SS.value++;if(SS.value ≤ 0)
up(S2); else up(S1)
Does this code work?
26Operating Systems, 2011, Danny Hendler & Amnon Meisels
up(S1) is performed by up(S) only if no process waits on S2only 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 The critical section that protects the counter is entered
alternately by a producer or a consumeralternately by a producer or a consumer
The effect of the added ‘else’The effect of the added ‘else’
27Operating Systems, 2011, Danny Hendler & Amnon Meisels
Recall the bounded-buffer algorithmRecall the bounded-buffer algorithm
#define N 100typedef int semaphoresemaphore;semaphoresemaphore mutex = 1;semaphoresemaphore empty = N;semaphoresemaphore full = 0;void producerproducer(void) {
int item;while(TRUE) {
produce_item(&item);downdown(&empty);downdown(&mutex);enter_item(item);upup(&mutex);upup(&full);
} }
void consumerconsumer(void){
intitem;
while(TRUE) { downdown(&full); downdown(&mutex); remove_item(&item); upup(&mutex); upup(&empty); consume_item(item);
}}
28Operating Systems, 2011, Danny Hendler & Amnon Meisels
A Problematic Scheduling Scenario
Consider a Bounded buffer of 5 slots.Assume there are 6 processes each filling five slots in turn.
Empty.Value = 521
3 4
5 6
29Operating Systems, 2011, Danny Hendler & Amnon Meisels
A Problematic Scheduling Scenario
1. 1. five slots are filled by the first producer
Empty.Value = 021
3 4
5 6
30Operating Systems, 2011, Danny Hendler & Amnon Meisels
A Problematic Scheduling Scenario
1. 1. The second producer is blocked
Empty.Value = -121
3 4
5 6
31Operating Systems, 2011, Danny Hendler & Amnon Meisels
A Problematic Scheduling Scenario
1. 1. The third producer is blocked
Empty.Value = -221
3 4
5 6
32Operating Systems, 2011, Danny Hendler & Amnon Meisels
A Problematic Scheduling Scenario
11. The fourth producer is blocked
Empty.Value = -321
3 4
5 6
33Operating Systems, 2011, Danny Hendler & Amnon Meisels
A Problematic Scheduling Scenario
1. 1. The fifth producer is blocked
Empty.Value = -421
3 4
5 6
34Operating Systems, 2011, Danny Hendler & Amnon Meisels
A Problematic Scheduling Scenario
2. 2. All blocked producers are waiting on S2
Empty.Value = -521
3 4
5 6
35Operating Systems, 2011, Danny Hendler & Amnon Meisels
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 = -521
3 4
5 6
36Operating Systems, 2011, Danny Hendler & Amnon Meisels
A Problematic Scheduling Scenario
3. 3. The consumer consumes an item and is blocked on S1 , one producer adds an item.
Empty.Value = -421
3 4
5 6
37Operating Systems, 2011, Danny Hendler & Amnon Meisels
A Problematic Scheduling Scenario
44. Consumer must consume, only then another producer wakes up and produces an item
Empty.Value = -321
3 4
5 6
38Operating Systems, 2011, Danny Hendler & Amnon Meisels
A Problematic Scheduling Scenario
4. 4. Same as in step 3.
Empty.Value = -221
3 4
5 6
39Operating Systems, 2011, Danny Hendler & Amnon Meisels
A Problematic Scheduling Scenario
5. 5. And again…
Empty.Value = -121
3 4
5 6
40Operating Systems, 2011, Danny Hendler & Amnon Meisels
Implementing a counting semaphore from binary Implementing a counting semaphore from binary semaphores: semaphores: take 3 take 3 (P.A. Kearns, 1988)(P.A. Kearns, 1988)
down(S)down(S)down(S1);SS.value--;if(SS.value < 0){
up(S1); //L1down(S2); //L2down(S1);SS.wake--; //L3 if(SS.wake > 0) then up(S2);} //L3
up(S1);
up(S):up(S):down(S1);SS.value++;if(SS.value <= 0) {
SS.wake++; up(S2); }up(S1);
binary-semaphore S1=1, S2=0, value initially 1, integer wake=0
Does THIS work?
41Operating Systems, 2011, Danny Hendler & Amnon Meisels
Correctness arguments (Kearns)…
The counter S.wakeS.wake is used when processes performing down(S)down(S) are preempted between lines L1 and L2
In such a case, up(S2) performed by processes during up(S)up(S) have no effect
However, these processes accumulate their waking signals on the (protected) counter S.wakeS.wake
After preemption is over, any single process that wakes up from its block on down(S2) checks the value of S.wakeS.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 oneEach re-scheduled process wakes up the next one
42Operating Systems, 2011, Danny Hendler & Amnon Meisels
Kearns' algorithm is wrongKearns' algorithm is wrong
Processes P0..P7 perform down(S),down(S), P0 goes through, P1..P7 are preempted
just after line L2 of the operation
Processes P8..P11 perform up(S)up(S) and their up(S2) operations release, say,
P1..P4
Processes P5, P6, P7 are still waiting on S2 and S.wake = 4S.wake = 4
Processes P1..P4 are ready, just before line L3
Each of P1..P3 will decrement S.wakeS.wake in its turn, check that it's positive and
signal one of P5..P7
Four Four upup operations have released 7 operations have released 7 down down operations operations
43Operating Systems, 2011, Danny Hendler & Amnon Meisels
Implementing a counting semaphore from binary Implementing a counting semaphore from binary semaphores: semaphores: take 4 take 4 (Hemmendinger, 1989)(Hemmendinger, 1989)
down(S)down(S)down(S1);SS.value--;if(SS.value < 0){
up(S1);down(S2);down(S1);SS.wake--; if(SS.wake > 0) then up(S2);} //3
up(S1);
up(S):up(S):down(S1);SS.value++;if(SS.value <= 0) {
SS.wake++; if (S.wake == 1) up(S2); }up(S1);
binary-semaphore S1=1, S2=0, integer wait
This works
44Operating Systems, 2011, Danny Hendler & Amnon Meisels
Implementing a counting semaphore from binary Implementing a counting semaphore from binary semaphores: semaphores: take 5take 5 (Barz, 1983)(Barz, 1983)
down(S)down(S)down(S2);down(S1);
S.value--; if (S.value>0) then up(S2); up(S1);
up(S):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)? 45Operating Systems, 2011, Danny Hendler & Amnon Meisels
Correctness arguments…Correctness arguments… The critical section is guarded by S1 and each of the operations
down(SS) and up(SS) uses it to correctly update the value of SS.value After updating (and inside the critical section) both operations
release the S2 semaphore only if value is positive SS.value is never negative, because any process performing
down(SS) is blocked at S2
Signals cannot be 'wasted' Signals cannot be 'wasted'
46Operating Systems, 2011, Danny Hendler & Amnon Meisels
Fairness of semaphores
Order of releasing blocked processes:o Fairo Processes are not allowed multiple entries if others are
waiting Another option:
o Open competition each time the lock is freeo Imitating the Java 'wait' 'notify' mechanismo Starvation is possible
47Operating Systems, 2011, Danny Hendler & Amnon Meisels
Outline
Semaphores and the producer/consumer problem
Counting semaphores from binary semaphores
Event counters and message passing synchronization
48Operating Systems, 2011, Danny Hendler & Amnon Meisels
Event CountersEvent Counters Integer counters with three operations:
o Advance(E): increment E by 1, wake up relevant sleepers
o Await(E,v): wait until E ≥ v. Sleep if E < vSleep if E < v
o Read(E): return the current value of E
Counter value is ever increasingCounter value is ever increasing
The Read() operation is not required for the bounded-buffer
implementation in the next slide
49Operating Systems, 2011, Danny Hendler & Amnon Meisels
producer-consumer with Event Countersproducer-consumer with Event Counters(for a single producer and a single consumer)(for a single producer and a single consumer)
#define N 100typedef int event_counter;event_counter in = 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 */
}}
50Operating Systems, 2011, Danny Hendler & Amnon Meisels
Event countersEvent 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);
}}
51Operating Systems, 2011, Danny Hendler & Amnon Meisels
MessageMessage Passing Passing – no shared memory– 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 duplicationo 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...
52Operating Systems, 2011, Danny Hendler & Amnon Meisels
Producer-consumer with Message PassingMessage Passing
#define N 100#define MSIZE 4 /* message size */
typedef int message(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 */
}}
53Operating Systems, 2011, Danny Hendler & Amnon Meisels
Message passingMessage passing (cont.) (cont.)
void consumer(void){int item, i;message m;
for(i = 0; i < N; i++) send(producer, &m); /* send N emptiesempties */
while(TRUE) {receive(producer, &m); /* get message with item */extract_item(&m, &item);send(producer, &m); /* send an empty reply */consume_item(item); }
}
54Operating Systems, 2011, Danny Hendler & Amnon Meisels
Message passing variationsMessage 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
55Operating Systems, 2011, Danny Hendler & Amnon Meisels