Synchronization semaphores and some more stuff Operating Systems

  • Slides: 55
Download presentation
Synchronization: semaphores and some more stuff Operating Systems, 2015, Meni Adler, Danny Hendler &

Synchronization: semaphores and some more stuff Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 1

What's wrong with busy waiting? The mutual exclusion algorithms we saw used busy-waiting. What’s

What's wrong with busy waiting? The mutual exclusion algorithms we saw used busy-waiting. What’s wrong with that? q Doesn't make sense for uni-processor o May cause deadlock q Wastes CPU time o But may be efficient if waiting-time is short Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 2

What's wrong with busy waiting? Busy waiting may cause deadlock q Process A's priority

What's wrong with busy waiting? Busy waiting may cause deadlock q Process A's priority is higher than process B's q Process B enters the CS q Process A needs to enter the CS, busy-waits for B to exit the CS q Process B cannot execute as long as the higher-priority process A is executing/ready Deadlock results Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 3

Outline q Semaphores and the producer/consumer problem q Counting semaphores from binary semaphores q

Outline q Semaphores and the producer/consumer problem q Counting semaphores from binary semaphores q Event counters and message passing synchronization Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 4

Semaphores Two atomic operations are supported by a semaphore S: down(S) [the 'p' operation]

Semaphores Two atomic operations are supported by a semaphore S: down(S) [the 'p' operation] q q If S≤ 0 the process is blocked. It will resume execution only after it is woken-up Else S-- up(S) [the 'v' operation] q If there are blocked processes, wake-up one of them q Else S++ q S is non-negative q Supported by Windows, Unix, … Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 5

Semaphores: is the following correct? Two atomic operations are supported by a semaphore S:

Semaphores: is the following correct? Two atomic operations are supported by a semaphore S: down(S) [the 'p' operation] q q If S≤ 0 the process is blocked. It will resume execution only after it is woken-up S-- up(S) [the 'v' operation] q S++ q If there are blocked processes, wake-up one of them Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 6

Pseudo-code in previous slide is wrong Consider the following bad scneario: q S=0 and

Pseudo-code in previous slide is wrong Consider the following bad scneario: q S=0 and process A performs down(S) – A is blocked q Process B performs up(S) – S=1 A is ready q Process C performs down(S) – S=0 & C proceeds q Process A gets a time-slice and proceeds – S=-1 A single up() freed 2 down()s Operating Systems, 2011, Danny Hendler & Amnon Meisels 7

Implementing mutex with semaphores Shared data: semaphore lock; /* initially lock = 1 */

Implementing mutex with semaphores Shared data: semaphore lock; /* initially lock = 1 */ down(lock) Critical section up(lock) Yes Does it satisfy deadlock-freedom? Yes Does it satisfy starvation-freedom? Depends… Does the algorithm satisfy mutex? Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 8

Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 9

Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 9

More on synchronization using semaphores Three processes p 1; p 2; p 3 semaphores

More on synchronization using semaphores Three processes p 1; p 2; p 3 semaphores p 1 down(s 1); s 1 A up(s 2); s 2 s 1 = 1, s 2 = 0; p 2 down(s 2); s 2 B up(s 2); s 2 p 3 down(s 2); s 2 C up(s 1); s 1 Which execution orders of A, B, C, are possible? (A B* C)* Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 10

No guarantee for correct synchronization (when multiple semaphores/locks are used) P 0 P 1

No guarantee for correct synchronization (when multiple semaphores/locks are used) P 0 P 1 down(S); down(Q); move 1 up(S); up(Q) down(Q); down(S); move 2 up(Q); up(S); 1 1 q Example: move money between two accounts which are protected by semaphores S and Q Does this work? Deadlock! Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 11

Negative-valued semaphores Two atomic operations are supported by a semaphore S: down(S) q q

Negative-valued semaphores Two atomic operations are supported by a semaphore S: down(S) q q up(S) S-If S<0 the process is blocked. It will resume execution only when S is non-negative q S++ q If there are blocked processes (i. e. S≤ 0), wake-up one of them -3 q If S is negative, then there are –S blocked processes Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 12

Negative semaphore Implementation type semaphore = record value: integer; L: list of process; end;

Negative semaphore Implementation type semaphore = record value: integer; L: list of process; end; -3 L 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); } Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 13

Implementing a spin-lock with TSL (test-set-lock) mutex_lock: TSL CMP JZE CALL JMP ok: RET

Implementing a spin-lock with TSL (test-set-lock) mutex_lock: TSL CMP JZE CALL JMP ok: RET REG, mutex REG, #0 ok thread_yield mutex_lock mutex_unlock: MOV mutex, #0 RET Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 14

Implementing a negative semaphore with TSL type semaphore = record value, flag: integer; L:

Implementing a negative semaphore with TSL type semaphore = record value, flag: integer; L: list of process; end; 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 -3 L 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 Any problem with this code? In down(), resetting flag and sleeping should be atomic. Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 15

More on semaphore implementation q On a uni-processor, disabling interrupts may be used q

More on semaphore implementation q On a uni-processor, disabling interrupts may be used q TSL implementation works for multi-processors q On a multi-processor, we can use spin-lock mutual exclusion to protect semaphore access Why is this better than busy-waiting in the first place? Busy-waiting is now guaranteed to be very short Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 16

Producer-Consumer Problem buffer in out q Paradigm for cooperating processes, • producer process produces

Producer-Consumer Problem buffer in out q Paradigm for cooperating processes, • producer process produces information that is consumed by a consumer process q Two versions • unbounded-buffer places no practical limit on the size of the buffer • bounded-buffer assumes that there is a fixed buffer size Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 17

Bounded Buffer buffer 0 1 2 item 1 3 item 2 producer 2 Out

Bounded Buffer buffer 0 1 2 item 1 3 item 2 producer 2 Out 4 item 3 consumer 5 item 4 6 In 7 Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 18

Implementation using semaphores q Two processes or more use a shared buffer in memory

Implementation using semaphores q Two processes or more use a shared buffer in memory q The buffer has finite size(i. e. , it is bounded) bounded q The producer writes to the buffer and the consumer reads from it q A full buffer stops the producer q An empty buffer stops the consumer Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 19

Producer-Consumer implementation with semaphores #define N typedef int semaphore 100 semaphore; semaphore mutex =

Producer-Consumer implementation with semaphores #define N typedef int semaphore 100 semaphore; semaphore mutex = 1; empty = N; full = 0; /* Buffer size */ /* access control to critical section */ /* counts empty buffer slots */ /* 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 */ down enter_item(item); /* insert into buffer */ up(&mutex); /* leave critical section */ up up(&full); /* increment count of full slots */ up } } Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 20

Producer-Consumer implementation with semaphores void consumer(void) consumer { int } item; while(TRUE) { down(&full);

Producer-Consumer implementation with semaphores void consumer(void) consumer { int } item; while(TRUE) { down(&full); down(&mutex); down remove_item(&item); up(&mutex); up up(&empty); up consume_item(item); } /* decrement count of full */ /* enter critical section */ /* take item from buffer) */ /* leave critical section */ /* update count of empty */ /* do something. . . */ Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 21

Outline q Semaphores and the producer/consumer problem q Counting semaphores from binary semaphores q

Outline q Semaphores and the producer/consumer problem q Counting semaphores from binary semaphores q Event counters and message passing synchronization Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 22

Binary Semaphore q Assumes only values 0 or 1 q Wait blocks if semaphore=0

Binary Semaphore q Assumes only values 0 or 1 q Wait blocks if semaphore=0 q Signal (up operation) either wakes up a waiting process, if there is one, or sets value to 1 (if value is already 1, signal is “wasted”) q How can we implement a counting semaphore by using binary semaphores? Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 23

Implementing a counting semaphore with binary semaphores (user space): take 1 binary-semaphore S 1

Implementing a counting semaphore with binary semaphores (user space): take 1 binary-semaphore S 1 initially 1, S 2 initially 0, S. value initially 1 down(S): down(S 1); S. value--; if(S. value < 0){ L 1: up(S 1); L 2: down(S 2); } else up(S 1); up(S): down(S 1); S. value++; if(S. value ≤ 0) up(S 2); up(S 1) This code does not work. Why? Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 24

Race condition for counting semaphore take 1 1. Processes Q 1 – Q 4

Race condition for counting semaphore take 1 1. Processes Q 1 – Q 4 perform down(S), Q 2 – Q 4 are preempted between lines L 1 and L 2: the value of the counting semaphore is now -3 2. Processes Q 5 -Q 7 now perform up(S): the value of the counting semaphore is now 0 3. Now, Q 2 -Q 4 wake-up in turn and perform line L 2 (down S 2) 4. Q 2 runs but Q 3 -Q 4 block. There is a discrepancy between the value of S and the number of processes waiting on it Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 25

Implementing a counting semaphore with binary semaphores (user space): take 2 binary-semaphore S 1

Implementing a counting semaphore with binary semaphores (user space): take 2 binary-semaphore S 1 initially 1, S 2 initially 0, S. value initially 1 down(S): down(S 1); S. value--; if(S. value < 0){ up(S 1); //L 1 down(S 2); } //L 2 up(S 1); up(S): down(S 1); S. value++; if(S. value ≤ 0) up(S 2); else up(S 1) Does this code work? Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 26

The effect of the added ‘else’ q up(S 1) is performed by up(S) only

The effect of the added ‘else’ q up(S 1) is performed by up(S) only if no process waits on S 2 q Q 5 leaves up(S) without releasing S 1 q Q 6 cannot enter the critical section that protects the counter q It can only do so after one of Q 2 -Q 4 releases S 1 q This generates a “lock-step” situation: an up(), a down(), an up()… q The critical section that protects the counter is entered alternately by a producer or a consumer Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 27

Recall the bounded-buffer algorithm #define N 100 typedef int semaphore; semaphore mutex = 1;

Recall the bounded-buffer algorithm #define N 100 typedef int semaphore; semaphore mutex = 1; semaphore empty = N; semaphore full = 0; void producer(void) { producer int item; while(TRUE) { produce_item(&item); down(&empty); down(&mutex); down enter_item(item); up(&mutex); up up(&full); up } } void consumer(void) consumer { int } item; while(TRUE) { down(&full); down(&mutex); down remove_item(&item); up(&mutex); up up(&empty); up consume_item(item); } Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 28

A Problematic Scheduling Scenario Consider a Bounded buffer of 5 slots. Assume there are

A Problematic Scheduling Scenario Consider a Bounded buffer of 5 slots. Assume there are 6 processes each filling five slots in turn. 1 2 3 4 5 6 Empty. Value = 5 Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 29

A Problematic Scheduling Scenario 1. five slots are filled by the first producer 1

A Problematic Scheduling Scenario 1. five slots are filled by the first producer 1 2 3 4 5 6 Empty. Value = 0 Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 30

A Problematic Scheduling Scenario 1. The second producer is blocked 1 2 3 4

A Problematic Scheduling Scenario 1. The second producer is blocked 1 2 3 4 5 6 Empty. Value = -1 Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 31

A Problematic Scheduling Scenario 1. The third producer is blocked 1 2 3 4

A Problematic Scheduling Scenario 1. The third producer is blocked 1 2 3 4 5 6 Empty. Value = -2 Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 32

A Problematic Scheduling Scenario 1. The fourth producer is blocked 1 2 3 4

A Problematic Scheduling Scenario 1. The fourth producer is blocked 1 2 3 4 5 6 Empty. Value = -3 Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 33

A Problematic Scheduling Scenario 1. The fifth producer is blocked 1 2 3 4

A Problematic Scheduling Scenario 1. The fifth producer is blocked 1 2 3 4 5 6 Empty. Value = -4 Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 34

A Problematic Scheduling Scenario 2. All blocked producers are waiting on S 2 1

A Problematic Scheduling Scenario 2. All blocked producers are waiting on S 2 1 2 3 4 5 6 Empty. Value = -5 Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 35

A Problematic Scheduling Scenario 3. The consumer consumes an item and is blocked on

A Problematic Scheduling Scenario 3. The consumer consumes an item and is blocked on Empty. S 1 until a producer adds an item. 1 2 3 4 5 6 Empty. Value = -5 Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 36

A Problematic Scheduling Scenario 3. The consumer consumes an item and is blocked on

A Problematic Scheduling Scenario 3. The consumer consumes an item and is blocked on S 1 , one producer adds an item. 1 2 3 4 5 6 Empty. Value = -4 Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 37

A Problematic Scheduling Scenario 4. Consumer must consume, only then another producer wakes up

A Problematic Scheduling Scenario 4. Consumer must consume, only then another producer wakes up and produces an item 1 2 3 4 5 6 Empty. Value = -3 Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 38

A Problematic Scheduling Scenario 4. Same as in step 3. 1 2 3 4

A Problematic Scheduling Scenario 4. Same as in step 3. 1 2 3 4 5 6 Empty. Value = -2 Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 39

A Problematic Scheduling Scenario 5. And again… 1 2 3 4 5 6 Empty.

A Problematic Scheduling Scenario 5. And again… 1 2 3 4 5 6 Empty. Value = -1 Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 40

Implementing a counting semaphore with binary semaphores (user space): take 3 (P. A. Kearns,

Implementing a counting semaphore with binary semaphores (user space): take 3 (P. A. Kearns, 1988) binary-semaphore S 1=1, S 2=0, value initially 1, integer wake=0 down(S) down(S 1); S. value--; if(S. value < 0){ up(S 1); //L 1 down(S 2); //L 2 down(S 1); S. wake--; if(S. wake > 0) then up(S 2); } //L 3 up(S 1); up(S): down(S 1); S. value++; if(S. value <= 0) { S. wake++; up(S 2); } up(S 1); Does THIS work? Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 41

Correctness arguments (Kearns)… q The counter S. wake is used when processes performing down(S)

Correctness arguments (Kearns)… q The counter S. wake is used when processes performing down(S) are preempted between lines L 1 and L 2 q In such a case, up(S 2) performed by processes during up(S) has no effect q However, these processes accumulate their waking signals on the (protected) counter S. wake q After preemption is over, any single process that wakes up from its block on down(S 2) checks the value of S. wake q The check is again protected q For each count of the wake-up signals, the awakened process performs the up(S 2) (in line L 3) q Each re-scheduled process wakes up the next one Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 42

Kearns' algorithm is wrong q Processes P 0. . P 7 perform down(S), P

Kearns' algorithm is wrong q Processes P 0. . P 7 perform down(S), P 0 goes through, P 1. . P 7 are preempted just after line L 2 of the operation q Processes P 8. . P 11 perform up(S) and their up(S 2) operations release, say, P 1. . P 4 q Processes P 5, P 6, P 7 are still waiting on S 2 and S. wake = 4 q Processes P 1. . P 4 are ready, just before line L 3 q Each of P 1. . P 3 will decrement S. wake in its turn, check that it's positive and signal one of P 5. . P 7 q Four up operations have released 7 down operations Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 43

Implementing a counting semaphore with binary semaphores (user space): take 4 (Hemmendinger, 1989) binary-semaphore

Implementing a counting semaphore with binary semaphores (user space): take 4 (Hemmendinger, 1989) binary-semaphore S 1=1, S 2=0, integer wake=0 down(S) down(S 1); S. value--; if(S. value < 0){ up(S 1); down(S 2); down(S 1); S. wake--; if(S. wake > 0) then up(S 2); } // L 3 up(S 1); up(S): down(S 1); S. value++; if(S. value <= 0) { S. wake++; if (S. wake == 1) up(S 2); } up(S 1); This works Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 44

Implementing a counting semaphore with binary semaphores (user space): take 5 (Barz, 1983) binary-semaphore

Implementing a counting semaphore with binary semaphores (user space): take 5 (Barz, 1983) binary-semaphore S 1=1, S 2=min(1, init_value), value=init_value down(S) down(S 2); down(S 1); S. value--; if (S. value>0) then up(S 2); up(S 1); up(S): down(S 1); S. value++; if(S. value == 1) { up(S 2); } up(S 1); This works, is simpler, and was published earlier(!)… Can we switch the order of downs in down(S)? Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 45

Correctness arguments… q The critical section is guarded by S 1 and each of

Correctness arguments… q The critical section is guarded by S 1 and each of the operations down(S) and up(S) uses it to correctly update the value of S. value q After updating (and inside the critical section) both operations release the S 2 semaphore only if value is positive q S. value is never negative, because any process performing down(S) is blocked at S 2 q. Signals cannot be 'wasted' Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 46

Fairness of semaphores q Order of releasing blocked processes: o Weak – up() performing

Fairness of semaphores q Order of releasing blocked processes: o Weak – up() performing process enters after (one of the) blocked processes o Strong – An upper bound on the number of entries of process that performed up() if others are waiting q Unfair: o No guarantee about the number of times the up() performing process enters before the blocked o Open competition each time the lock is free o Imitating the Java 'wait' 'notify' mechanism o Or the spin-lock of XV 6… Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 47

Outline q Semaphores and the producer/consumer problem q Counting semaphores from binary semaphores q

Outline q Semaphores and the producer/consumer problem q Counting semaphores from binary semaphores q Event counters and message passing synchronization Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 48

Event Counters q Integer counters with three operations: o Advance(E): increment E by 1,

Event Counters q 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 < v o Read(E): return the current value of E q Counter value is ever increasing q The Read() operation is not required for the bounded-buffer implementation in the next slide Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 49

producer-consumer with Event Counters (for a single producer and a single consumer) #define typedef

producer-consumer with Event Counters (for a single producer and a single consumer) #define typedef event_counter N int in = 0; out = 0; 100 event_counter; /* counts inserted items */ /* 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 */ } } Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 50

Event counters (producer-consumer) void consumer(void) { int item, sequence = 0; } while(TRUE) {

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); } Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 51

Message Passing – no shared memory q In a multi-processor system without shared memory,

Message Passing – no shared memory q In a multi-processor system without shared memory, synchronization can be implemented by message passing q 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…) q Two main functions: o send(destination, &message); o receive(source, &message) block while waiting. . . Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 52

Producer-consumer with Message Passing #define N #define MSIZE 100 4 typedef int message(MSIZE); void

Producer-consumer with Message Passing #define N #define MSIZE 100 4 typedef int message(MSIZE); void producer(void) { int item; message m; } while(TRUE) { produce_item(&item); receive(consumer, &m); construct_message(&m, item); send(consumer, &m); } /* message size */ /* message buffer */ /*wait for an empty */ /* send item */ Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 53

Message passing (cont. ) void consumer(void) { int item, i; message m; for(i =

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); extract_item(&m, &item); send(producer, &m); consume_item(item); } } /* get message with item */ /* send an empty reply */ Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 54

Message passing variations q Messages can be addressed to a process address or to

Message passing variations q 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 q Unix pipes - a generalization of messages … no fixed size message (blocking receive) q If no buffer is maintained by the system, then send and receive must run in lock-step. Example: Unix rendezvous Operating Systems, 2015, Meni Adler, Danny Hendler & Roie Zivan 55