Synchronization 2: semaphores and more…
description
Transcript of Synchronization 2: semaphores and more…
1
Synchronization 2: semaphoresand more…
1 Operating Systems, 2011, Danny Hendler & Amnon Meisels
2
What’s wrong with busy waiting?
Doesn‘t make sense for Uni-processor
Wastes CPU time
May cause priority inversion and deadlock
The mutual exclusion algorithms we saw used busy-waiting. What’s wrong with that?
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 resultOperating 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
Operating Systems, 2011, Danny Hendler & Amnon Meisels
5
Synchronization Constructs – Semaphores (Dijkstra ‘68)
Two operations define a semaphore S:DOWN(S) p(s)
while(s <= 0);s = s - 1;
UP(S) v(s)s = s + 1;
Operations on the counter are performed indivisiblyS is non-negative
but this description busy-waits…Operating Systems, 2011, Danny Hendler & Amnon Meisels
6
Semaphores (Dijkstra ‘68)
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 when awakened by an up(S) operation
S--
Two atomic operations are supported by a semaphore S:
S is non-negative
What exactly does “atomic” mean ??
Operating Systems, 2011, Danny Hendler & Amnon Meisels
7
Wrong non negative Semaphore
Lines of code are executed asynchronously S=0 and process A performs down(S) – A is blocked Process B performs up(S) – S=1 A is ready Process C performs down(S) – S=0 & C proceeds Process A gets a time-slice and proceeds – S=0
A single up() operation for 2 down()s
Operating Systems, 2011, Danny Hendler & Amnon Meisels
8
Semaphores (Dijkstra ‘68)
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 when awakened by an up(S) operation
else S--
Two atomic operations are supported by a semaphore S:
S is non-negative
Supported by Windows, Unix, …Operating Systems, 2011, Danny Hendler & Amnon Meisels
9
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…
Operating Systems, 2011, Danny Hendler & Amnon Meisels
10
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
Operating Systems, 2011, Danny Hendler & Amnon Meisels
11
Synchronization with semaphoresThree processes p1; p2; p3
semaphores s1 = 1, s2 = 0;p1 p2 p3down(s1); down(s2); down(s2);A B Cup(s2); up(s2); up(s1);
Which execution orderings of A, B, C, are possible?
(A B* C)*Operating Systems, 2011, Danny Hendler & Amnon Meisels
12
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
Does this work?Deadlock!
Operating Systems, 2011, Danny Hendler & Amnon Meisels
13
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
Operating Systems, 2011, Danny Hendler & Amnon Meisels
14
type semaphore = recordvalue: integer; L: list of process;
end;
Negative semaphore Implementation
-3
down(S):S.value--;if (S.value < 0) { add this process to S.L;
sleep; }
up(S): S.value++;if (S.value <= 0) {
remove a process P from S.L; wakeup(P); }
Operating Systems, 2011, Danny Hendler & Amnon Meisels
15
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
buff
er
in
out
Operating Systems, 2011, Danny Hendler & Amnon Meisels
16
2
6
Out
In
item1
item4
item3
item2
consumer
0buffer
producer
Bounded Buffer
1
2
3
4
5
7
Operating Systems, 2011, Danny Hendler & Amnon Meisels
17
Implementation using semaphores
Two processes or more use a shared buffer in memory
The buffer is finite (e.g., bounded)
The producer writes to the buffer and the consumer reads from it
A full buffer stops the producer
An empty buffer stops the consumer
Operating Systems, 2011, Danny Hendler & Amnon Meisels
18
Producer-Consumer implementation with semaphores#define N 100 /* Buffer size */typedef int semaphore;semaphore mutex = 1; /* access control to critical section */semaphore empty = N; /* counts empty buffer slots */semaphore full = 0; /* counts full slots */
void producer(void) {int item;while(TRUE) {
produce_item(&item); /* generate something... */down(&empty); /* decrement count of empty */down(&mutex); /* enter critical section */enter_item(item); /* insert into buffer */up(&mutex); /* leave critical section */up(&full); /* increment count of full slots */
} }Operating Systems, 2011, Danny Hendler & Amnon Meisels
19
void consumer(void){
int item;
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... */
}}
Comment: up() and down() are atomic operations
Operating Systems, 2011, Danny Hendler & Amnon Meisels
Producer-Consumer implementation with semaphores
20
Implementing a binary semaphore with TSL
In user space, one can use TSL (test-set-lock)mutex_lock:
TSL REG, mutexCMP REG, #0JZE ok | the equivalent of enter_regionCALL thread_yield
JMP mutex_lockok:
RET
mutex_unlock:MOV mutex, #0RET
also called a Spin-lockOperating Systems, 2011, Danny Hendler & Amnon Meisels
21
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 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
Operating Systems, 2011, Danny Hendler & Amnon Meisels
22
More on semaphore implementation TSL implementation can work 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
Operating Systems, 2011, Danny Hendler & Amnon Meisels
23
Outline
Semaphores and the producer/consumer problem Counting semaphores from binary semaphores Event counters and message passing synchronization
Operating Systems, 2011, Danny Hendler & Amnon Meisels
2424 Operating Systems, 2011, Danny Hendler & Amnon Meisels
Assumes only values 0 or 1
Wait blocks if semaphore=0
Signal either wakes up a waiting thread, if there is one, or sets value to 1
How can wakeup signals be accumulated (for the bounded buffer, for example)
Binary Semaphore
25
Implementing a counting semaphore with binary semaphores: take 1
down(S):down(S1);S.value--;if(S.value < 0){
up(S1); // L1
down(S2); } //L2else up(S1);
binary-semaphore S1, S2 initially 1; S.value initially 1
up(S):down(S1);S.value++;if(S.value ≤ 0)
up(S2); up(S1)
This code does not work
25 Operating Systems, 2011, Danny Hendler & Amnon Meisels
26
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.
There is a discrepancy between the value of S and the number of
processes waiting on it
26 Operating Systems, 2011, Danny Hendler & Amnon Meisels
27
Implementing a counting semaphore with binary semaphores: take 2
down(S):down(S1);S.value--;if(S.value < 0){
up(S1); //L1
down(S2); } //L2up(S1);
binary-semaphore S1=1, S2=0; S.value initially 1
up(S):down(S1);S.value++;if(S.value ≤ 0)
up(S2); else up(S1)
Does this code work?
27 Operating Systems, 2011, Danny Hendler & Amnon Meisels
28
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
The critical section that protects the counter is entered
alternately by a producer or a consumer
The effect of the added ‘else’
28 Operating Systems, 2011, Danny Hendler & Amnon Meisels
29
Recall the bounded-buffer algorithm#define N 100typedef int semaphore;semaphore mutex = 1;semaphore empty = N;semaphore full = 0;void producer(void) {
int item;while(TRUE) {
produce_item(&item);down(&empty);down(&mutex);enter_item(item);up(&mutex);up(&full);
} }
void consumer(void){
intitem;
while(TRUE) { down(&full); down(&mutex); remove_item(&item); up(&mutex); up(&empty); consume_item(item);
}}
29 Operating Systems, 2011, Danny Hendler & Amnon Meisels
30
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
30 Operating Systems, 2011, Danny Hendler & Amnon Meisels
31
A Problematic Scheduling Scenario
1. five slots are filled by the first producer
Empty.Value = 021
3 4
5 6
31 Operating Systems, 2011, Danny Hendler & Amnon Meisels
32
A Problematic Scheduling Scenario1. The second producer is blocked
Empty.Value = -121
3 4
5 6
32 Operating Systems, 2011, Danny Hendler & Amnon Meisels
33
A Problematic Scheduling Scenario
1. The third producer is blocked
Empty.Value = -221
3 4
5 6
33 Operating Systems, 2011, Danny Hendler & Amnon Meisels
34
A Problematic Scheduling Scenario
1. The fourth producer is blocked
Empty.Value = -321
3 4
5 6
34 Operating Systems, 2011, Danny Hendler & Amnon Meisels
35
A Problematic Scheduling Scenario
1. The fifth producer is blocked
Empty.Value = -421
3 4
5 6
35 Operating Systems, 2011, Danny Hendler & Amnon Meisels
36
A Problematic Scheduling Scenario
2. All blocked producers are waiting on S2
Empty.Value = -521
3 4
5 6
36 Operating Systems, 2011, Danny Hendler & Amnon Meisels
37
A Problematic Scheduling Scenario
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
37 Operating Systems, 2011, Danny Hendler & Amnon Meisels
38
A Problematic Scheduling Scenario
3. The consumer consumes an item and is blocked on S1 , one producer adds an item.
Empty.Value = -421
3 4
5 6
38 Operating Systems, 2011, Danny Hendler & Amnon Meisels
39
A Problematic Scheduling Scenario
4. Consumer must consume, only then another producer wakes up and produces an item
Empty.Value = -321
3 4
5 6
39 Operating Systems, 2011, Danny Hendler & Amnon Meisels
40
A Problematic Scheduling Scenario
4. Same as in step 3.
Empty.Value = -221
3 4
5 6
40 Operating Systems, 2011, Danny Hendler & Amnon Meisels
41
A Problematic Scheduling Scenario
5. And again…
Empty.Value = -121
3 4
5 6
41 Operating Systems, 2011, Danny Hendler & Amnon Meisels
42
Implementing a counting semaphore with binary semaphores: take 3 (P.A. Kearns, 1988)
down(S)down(S1);S.value--;if(S.value < 0){
up(S1); //L1down(S2); //L2down(S1);S.wake--; //L3 if(S.wake > 0) then up(S2);} //L3
up(S1);
up(S):down(S1);S.value++;if(S.value <= 0) {
S.wake++; up(S2); }up(S1);
binary-semaphore S1=1, S2=0, value initially 1, integer wake=0
Does THIS work?
42 Operating Systems, 2011, Danny Hendler & Amnon Meisels
43
Correctness arguments (Kearns)…
The counter S.wake is used when processes performing down(S) are preempted between lines L1 and L2
In such a case, up(S2) performed by processes during up(S) have no effect
However, these processes accumulate their waking signals on the (protected) counter 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
43 Operating Systems, 2011, Danny Hendler & Amnon Meisels
44
Kearns' algorithm is wrong
Processes P0..P8 perform down(S), P1..P8 are preempted just before line L2 of
the operation
Processes P9..P12 perform up(S) and their up(S2) lines release, say, P1..P4
4 processes are waiting on S2 and S.wake = 4
Processes P1..P4 are ready, just before lines L3
Each of P1..P4 will decrement S.wake in its turn, check that it's positive and
signal one of P5..P8
Four up(S) have released 8 down(S)
44 Operating Systems, 2011, Danny Hendler & Amnon Meisels
45
Implementing a counting semaphore with binary semaphores: take 4 (Hemmendinger, 1989)
down(S)down(S1);S.value--;if(S.value < 0){
up(S1);down(S2);down(S1);S.wake--; if(S.wake > 0) then up(S2);} // L3
up(S1);
up(S):down(S1);S.value++;if(S.value <= 0) {
S.wake++; if (S.wake == 1) up(S2); }up(S1);
binary-semaphore S1=1, S2=0, integer value =1, integer wake=0
This works
45 Operating Systems, 2011, Danny Hendler & Amnon Meisels
46
Implementing a counting semaphore with 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)? 46 Operating Systems, 2011, Danny Hendler & Amnon Meisels
47
Correctness arguments… 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.value is never negative, because any process performing
down(S) is blocked at S2Signals cannot be 'wasted'
47 Operating Systems, 2011, Danny Hendler & Amnon Meisels
48
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
48 Operating Systems, 2011, Danny Hendler & Amnon Meisels
49
Counting and Binary semaphores (open contest)
down(S):down(S1);while(S.value == 0){
S.wait++; up(S1); down(S2); down(S1);
S.wait--; S.wake--; }
if(S.wake > 0) then up(S2);
S.value--;up(S1);
binary-semaphore S1 =1, S2=0; int S.value=k, S.wait=0, S.wake=0
up(S):down(S1);if (S.wait > 0 && S.wake < S.wait)
{ S.wake++; if (S.wake==1) up(S2); } S.value++ up(S1)
49 Operating Systems, 2011, Danny Hendler & Amnon Meisels
50
Outline
Semaphores and the producer/consumer problem Counting semaphores from binary semaphores Event counters and message passing synchronization
50 Operating Systems, 2011, Danny Hendler & Amnon Meisels
51
Event 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 < vo Read(E): return the current value of E
Counter value is ever increasing
The Read() operation is not required for the bounded-buffer implementation in the next slide
51 Operating Systems, 2011, Danny Hendler & Amnon Meisels
52
producer-consumer with Event Counters#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 */
}}
52 Operating Systems, 2011, Danny Hendler & Amnon Meisels
53
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);
}}
53 Operating Systems, 2011, Danny Hendler & Amnon Meisels
54
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 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...
54 Operating Systems, 2011, Danny Hendler & Amnon Meisels
55
Producer-consumer with Message 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 */
}}
55 Operating Systems, 2011, Danny Hendler & Amnon Meisels
56
Message passing (cont.)
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); }
}
56 Operating Systems, 2011, Danny Hendler & Amnon Meisels
57
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
57 Operating Systems, 2011, Danny Hendler & Amnon Meisels