Synchronization Semaphores Operating Systems Spring 2020 I Dinur

  • Slides: 73
Download presentation
Synchronization: Semaphores Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 1

Synchronization: Semaphores Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 1

Semaphores: outline q Semaphores and producer-consumer problem q Counting semaphores from binary semaphores q

Semaphores: outline q Semaphores and producer-consumer problem q Counting semaphores from binary semaphores q Event counters and message passing synchronization Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 2

The mutual exclusion algorithms we saw use busy-waiting. What’s wrong with that? q Waste

The mutual exclusion algorithms we saw use busy-waiting. What’s wrong with that? q Waste of CPU time o but may be efficient if waiting-time is short Windows OS example with two processes: q Doesn't make sense for single processor o may cause (theoretical) deadlock – when lowdeadlock priority process holds lock but is not scheduled (due to its low priority), and high-priority process gets all CPU time to execute busy-waiting (but cannot progress) Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 3

The mutual exclusion algorithms we saw use busy-waiting. What’s wrong with that? q Waste

The mutual exclusion algorithms we saw use busy-waiting. What’s wrong with that? q Waste of CPU time o but may be efficient if waiting-time is short Why theoretical? Does such a deadlock may really happen ? q Doesn't make sense for single processor o may cause (theoretical) deadlock – when lowdeadlock priority process holds lock but is not scheduled (due to its low priority), and high-priority process gets all CPU time to execute busy-waiting (but cannot progress) NO. Since OS increases NO priority of waiting processes, at some point low-priority process would be schedules and frees the lock. Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 4

Semaphore is primitive mutex with no busy-wait Operating Systems, Spring 2020, I. Dinur, D.

Semaphore is primitive mutex with no busy-wait Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 5

Semaphores - definition n is number of permissions up(S) returns “entry permit” for waked-up

Semaphores - definition n is number of permissions up(S) returns “entry permit” for waked-up process down(S) – get “entry permit” if exists, or wait for it down(S) q q up(S) If S=0 the process is blocked. It will resume execution only after it is woken-up Else S-- q If there are blocked processes, wake-up one of them q Else S++ process statement is changed from “Blocked” to “Ready” Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 6

Semaphores - definition when process is blocked, some other process is allowed to execute

Semaphores - definition when process is blocked, some other process is allowed to execute down(S) q q up(S) If S=0 the process is blocked. It will resume execution only after it is woken-up Else S-- q If there are blocked processes, wake-up one of them q Else S++ Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 7

Semaphores: is the following correct ? down(S) q q up(S) If S≤ 0 the

Semaphores: is the following correct ? down(S) q q up(S) If S≤ 0 the process is blocked. It will resume execution only after it is woken-up S-- q S++ q If there are blocked processes, wake-up one of them NO. NO Mutual exclusion might be violated. Let’s demonstrate this by the following scenario. Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 8

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants to enter CS P 1 P 2 P 3 P 1 down (S) 1. If S≤ 0 2. sleep on S 3. S-- CS P 2 … up (S) 1. S++ 2. If there are sleeping processes 3. wake-up one of them Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 9

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants to enter CS P 1 P 2 P 3 down(S) P 3 P 1 down (S) 1. If S≤ 0 2. sleep on S 3. S-- CS P 2 … up (S) 1. S++ 2. If there are sleeping processes 3. wake-up one of them Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 10

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants to enter CS P 1 P 2 P 3 down(S) P 3 down (S) 1. If S≤ 0 2. sleep on S 3. S-- P 1 CS P 2 … up (S) 1. S++ 2. If there are sleeping processes 3. wake-up one of them Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 11

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants to enter CS P 1 P 2 P 3 down(S) BLOCKED: sleeps on S P 3 down (S) 1. If S≤ 0 2. sleep on S 3. S-- P 1 CS P 2 … up (S) 1. S++ 2. If there are sleeping processes 3. wake-up one of them Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 12

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants to enter CS P 1 P 2 P 3 down(S) BLOCKED: sleeps on S P 3 down (S) 1. If S≤ 0 2. sleep on S 3. S-- P 1 CS P 2 … up (S) 1. S++ 2. If there are sleeping processes 3. wake-up one of them Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 13

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants to enter CS P 1 P 2 P 3 down(S) BLOCKED: sleeps on S exits CS up(S) P 3 down (S) 1. If S≤ 0 2. sleep on S 3. S-- P 1 CS P 2 … up (S) 1. S++ 2. If there are sleeping processes 3. wake-up one of them Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 14

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants to enter CS P 1 P 2 P 3 down(S) BLOCKED: sleeps on S exits CS up(S) P 3 down (S) 1. If S≤ 0 2. sleep on S 3. S-- P 1 CS … up (S) P 2 1. S++ 2. If there are sleeping processes 3. wake-up one of them Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 15

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants to enter CS P 1 P 2 P 3 down(S) BLOCKED: sleeps on S exits CS P 3 up(S) wakes-up P 1 down (S) 1. If S≤ 0 2. sleep on S 3. S-- P 1 CS … up (S) P 2 1. S++ 2. If there are sleeping processes 3. wake-up one of them Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 16

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants to enter CS P 1 P 2 P 3 down(S) BLOCKED: sleeps on S P 1 exits CS P 3 up(S) wakes-up P 1 down (S) 1. If S≤ 0 2. sleep on S 3. S-- CS … up (S) 1. S++ 2. If there are sleeping processes 3. wake-up one of them Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 17

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants to enter CS P 1 P 2 P 3 down(S) BLOCKED: sleeps on S P 1 exits CS P 3 up(S) wakes-up P 1 BLOCKED: waits for S lock down (S) 1. If S≤ 0 2. sleep on S 3. S-- CS … up (S) 1. S++ 2. If there are sleeping processes 3. wake-up one of them Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 18

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants to enter CS P 1 P 2 P 3 down(S) BLOCKED: sleeps on S P 1 exits CS P 3 up(S) down (S) 1. If S≤ 0 2. sleep on S 3. S-- CS wakes-up P 1 BLOCKED: waits for S lock … down(S) up (S) 1. S++ 2. If there are sleeping processes 3. wake-up one of them Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 19

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants to enter CS P 1 P 2 P 3 down(S) BLOCKED: sleeps on S P 1 exits CS up(S) down (S) 1. If S≤ 0 2. sleep on S 3. S-- P 3 CS wakes-up P 1 BLOCKED: waits for S lock … down(S) up (S) 1. S++ 2. If there are sleeping processes 3. wake-up one of them Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 20

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants to enter CS P 1 P 2 P 3 down(S) BLOCKED: sleeps on S P 1 exits CS up(S) down (S) 1. If S≤ 0 2. sleep on S 3. S-- P 3 CS wakes-up P 1 BLOCKED: waits for S lock … down(S) enters CS up (S) 1. S++ 2. If there are sleeping processes 3. wake-up one of them Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 21

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants to enter CS P 1 P 2 P 3 down(S) BLOCKED: sleeps on S P 1 exits CS up(S) down (S) 1. If S≤ 0 2. sleep on S 3. S-- CS wakes-up P 1 BLOCKED: waits for S lock P 3 down(S) enters CS … up (S) 1. S++ 2. If there are sleeping processes 3. wake-up one of them Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 22

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants to enter CS P 1 P 2 P 3 down(S) BLOCKED: sleeps on S P 1 exits CS up(S) down (S) 1. If S≤ 0 2. sleep on S 3. S-- CS wakes-up P 1 BLOCKED: waits for S lock P 3 down(S) enters CS gets S lock continues executing down(S) … up (S) 1. S++ 2. If there are sleeping processes 3. wake-up one of them Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 23

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants to enter CS P 1 P 2 P 3 down(S) down (S) 1. If S≤ 0 2. sleep on S 3. S-- BLOCKED: sleeps on S exits CS up(S) P 1 CS wakes-up P 1 BLOCKED: waits for S lock P 3 down(S) enters CS gets S lock continues executing down(S) … up (S) 1. S++ 2. If there are sleeping processes 3. wake-up one of them Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 24

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants to enter CS P 1 P 2 P 3 down(S) down (S) 1. If S≤ 0 2. sleep on S 3. S-- BLOCKED: sleeps on S exits CS up(S) P 1 CS wakes-up P 1 BLOCKED: waits for S lock P 3 down(S) enters CS gets S lock continues executing down(S) … up (S) 1. S++ 2. If there are sleeping processes 3. wake-up one of them Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 25

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants

Semaphore S Suppose: S=0, P 2 in CS, P 1 and P 3 wants to enter CS P 1 P 2 P 3 down(S) down (S) 1. If S≤ 0 2. sleep on S 3. S-- BLOCKED: sleeps on S exits CS up(S) P 1 CS wakes-up P 1 BLOCKED: waits for S lock P 3 down(S) enters CS gets S lock continues executing down(S) single up() freed 2 down()s … up (S) 1. S++ 2. If there are sleeping processes 3. wake-up one of them Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 26

Semaphore as synchronizing tool: example 1 Processes: P Processes 1, P 2 Semaphore: s

Semaphore as synchronizing tool: example 1 Processes: P Processes 1, P 2 Semaphore: s Semaphore Task: execute code A before code B Task time P 1 … A How to use s in order to guarantee such an order ? P 2 … B Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 27

Semaphore as synchronizing tool: example 1 Processes: P Processes 1, P 2 Semaphore: s

Semaphore as synchronizing tool: example 1 Processes: P Processes 1, P 2 Semaphore: s = 0 Semaphore Task: execute code A before code B Task time P 1 … A up(s) P 2 … down(s) B Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 28

Semaphore as synchronizing tool: example 2 Processes: P 1, P 2, P 3 Processes

Semaphore as synchronizing tool: example 2 Processes: P 1, P 2, P 3 Processes Semaphore: s 1 = 1, s 2 =0 Semaphore P 1 while (true) { down(s 1); s 1 A up(s 2); s 2 } P 2 while (true) { down(s 2); s 2 B up(s 2); s 2 } P 3 while (true) { down(s 2); s 2 C up(s 1); s 1 } Which execution orders of A, B, C, are possible? Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky (A B* C)* 29

When multiple semaphores are used – no synch guarantee P 0 P 1 down(S);

When multiple semaphores are used – no synch guarantee P 0 P 1 down(S); down(Q); … up(S); up(Q) down(Q); down(S); … up(Q); up(S); Does this work? NO – this is Deadlock ! Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 30

Negative Semaphore down(S) q q S-If S<0 the process is blocked. It will resume

Negative Semaphore down(S) q q S-If S<0 the process is blocked. It will resume execution only when S is non-negative q If S is negative, then there are |S| blocked processes. Answer: if there is a single waiting process, then it would not be waked-up. • • Assume S=1 P 1 down(S), S=0 P 1 enters CS P 2 down(S), S=-1 P 2 goes sleep on S P 1 exits CS and up(S), S=0 P 1 would Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky not wake-up P 2 since if(S<0) does not hold 31

Negative Semaphore Implementation int value L is a list of sleeping processes int flag

Negative Semaphore Implementation int value L is a list of sleeping processes int flag = 0 down(S): while (Test-And-Set(S. flag)==1); S. value-if (S. value < 0) { add current process P to S. L sleep (P) S. flag=0 } else S. flag=0 Semaphore struct: -3 L Test-And-Set(flag): • prev <- flag • flag <- 1 • return prev up(S): while (Test-And-Set(S. flag)==1); S. value++ if (S. value <= 0) { remove some process P from S. L wakeup (P) } S. flag=0 This implementation uses busy-wait spinlock, since while(Test. And-Set(S. flag)) is busy -wait loop. Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 32

Negative Semaphore Implementation int value L is a list of sleeping processes int flag

Negative Semaphore Implementation int value L is a list of sleeping processes int flag = 0 down(S): while (Test-And-Set(S. flag)==1); S. value-if (S. value < 0) { add current process P to S. L sleep (P) S. flag=0 } else S. flag=0 Semaphore struct: -3 L up(S): while (Test-And-Set(S. flag)==1); S. value++ if (S. value <= 0) { remove some process P from S. L wakeup (P) } S. flag=0 Is the code of down(S) and up(S) may be executed by the process itself ? NO. NO Suppose P 1 executes down(S), and P 1 must go sleep since P 2 is in CS now. If P 1 gets asleep first, P 1 could not set flag to be 0. Now, nobody can execute nor down(S) neither up(S). Deadlock. Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 33

Negative Semaphore Implementation int value L is a list of sleeping processes int flag

Negative Semaphore Implementation int value L is a list of sleeping processes int flag = 0 down(S): } while (Test-And-Set(S. flag)==1); S. value-if (S. value < 0) { add current process P to S. L S. flag=0 sleep (P) else S. flag=0 And what if P 1 first set flag to be 0, and then goes asleep ? up(S): while (Test-And-Set(S. flag)==1); S. value++ if (S. value <= 0) { remove some process P from S. L wakeup (P) } S. flag=0 So, down(S) and up(S) should not be executed by the process – they should be or system calls, calls and then executed by OS, or be executed by some other thread. STILL NO. NO If P 1 first set flag to be 0, then OS scheduler might stop P 1, and schedule P 2 before P 1 gets asleep. P 2 might finish CS, and execute up(S). P 2 would try to wakeup P 1 since P 2 finds S. value to be negative. BUT P 1 STILL DOES NOT SLEEP !!! So P 2 would not wake up P 1. When P 1 is re-scheduled, P 1 would continue executing down(S), and gets asleep. Now there might be nobody who can wake up P 1. Deadlock. Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 34

Bounded Producer-Consumer Problem Producer produces items that are consumed by consumer. bounded-size buffer q

Bounded Producer-Consumer Problem Producer produces items that are consumed by consumer. bounded-size buffer q full buffer stops producer buffer 0 q empty buffer stops consumer buffer 1 producer 6 In 2 item 3 item 4 item 5 item 2 Out 3 semaphores: - full - empty 6 7 - binary semaphore for consumer mutual exclusion of buffer Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 35

Producer-Consumer implementation with semaphores Producer-Consumer semaphore mutex = 1 semaphore empty = N semaphore

Producer-Consumer implementation with semaphores Producer-Consumer semaphore mutex = 1 semaphore empty = N semaphore full = 0 /* binary semaphore for access control to critical section */ /* empty semaphore - counts empty buffer slots */ /* full semaphore - counts full slots */ producer: while(TRUE) produce_item(&item) down(&empty) down(&mutex) down insert_item(item) up(&mutex) up up(&full) up /* generate item */ /* is there free space in buffer ? */ /* enter CS */ /* insert item into buffer */ /* leave CS */ /* there is an item to consume */ consumer: while(TRUE) down(&full) down(&mutex) down remove_item(&item) up(&mutex) up up(&empty) up consume_item(item) /* is there items to consume ? */ /* enter critical section */ /* take item from buffer */ /* leave critical section */ /* update count of empty */ /* consume item */ We use mutex to synchronize buffer shared resource usage. Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 36

Producer-Consumer implementation with semaphores Producer-Consumer semaphore mutex = 1 semaphore empty = N semaphore

Producer-Consumer implementation with semaphores Producer-Consumer semaphore mutex = 1 semaphore empty = N semaphore full = 0 /* binary semaphore for access control to critical section */ /* empty semaphore - counts empty buffer slots */ /* full semaphore - counts full slots */ producer: while(TRUE) produce_item(&item) down(&empty) down(&mutex) down insert_item(item) up(&mutex) up up(&full) up /* generate item */ /* is there free space in buffer ? */ /* enter CS */ /* insert item into buffer */ /* leave CS */ /* there is an item to consume */ consumer: while(TRUE) down(&full) down(&mutex) down remove_item(&item) up(&mutex) up up(&empty) up consume_item(item) /* is there items to consume ? */ /* enter critical section */ /* take item from buffer */ /* leave critical section */ /* update count of empty */ /* consume item */ If there are only single producer and single consumer, may we not to use mutex ? YES. The reason is that consumer and producer never try to use same index in the buffer concurrently. Suppose buffer with i items, buffer[1] till buffer[i]. Then consumer will use buffer only at these indexes, and then would be BLOCKED on full semaphore. Producer will use only [i+1, n] indexes in the buffer, and then would be BLOCKED on empty semaphore. Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 37

Producer-Consumer implementation with semaphores Producer-Consumer semaphore mutex = 1 semaphore empty = N semaphore

Producer-Consumer implementation with semaphores Producer-Consumer semaphore mutex = 1 semaphore empty = N semaphore full = 0 /* binary semaphore for access control to critical section */ /* empty semaphore - counts empty buffer slots */ /* full semaphore - counts full slots */ We switched two first lines in consumer code. Is the code still right ? producer: while(TRUE) produce_item(&item) down(&empty) down(&mutex) down insert_item(item) up(&mutex) up up(&full) up /* generate item */ /* is there free space in buffer ? */ /* enter CS */ /* insert item into buffer */ /* leave CS */ /* there is an item to consume */ consumer: while(TRUE) down(&mutex) down(&full) down remove_item(&item) up(&mutex) up up(&empty) up consume_item(item) /* enter critical section */ /* is there items to consume ? */ /* take item from buffer */ /* leave critical section */ /* update count of empty */ /* consume item */ NO. Suppose empty buffer. Suppose consumer comes first, down the mutex, and then goes sleep on full semaphore. In this case no producers can put items into buffer since mutex is occupied. Deadlock Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 38

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

Semaphores: outline q Semaphores and the producer/consumer problem q Counting semaphores from binary semaphores q Event counters and message passing synchronization Operating Systems, Spring 2020, Dinur , Hendler and Kogan-Sadetsky 39

Binary Semaphore vs. single entry permission, guarantees mutual exclusion q S may be only

Binary Semaphore vs. single entry permission, guarantees mutual exclusion q S may be only 0 or 1 q down(S) blocks process if S is 0 q up(S) either wakes up some process, or sets S to be 1 use case: critical section semaphore S = 1 down(S) CS up(S) Counting Semaphore n permissions q S = n q down(S) blocks process if S <= 0 q up(S) increments S, and wakes up some process if S is still <= 0 How to implement a counting semaphore, using binary semaphores ? semaphore empty = N semaphore full = 0 Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky use case: Producer. Consumer 40

Counting semaphore by binary semaphores – try #1 S 1 is used for mutual

Counting semaphore by binary semaphores – try #1 S 1 is used for mutual exclusion of S. value S 2 is used to let waiting processes to sleep on it down(S): down(S 1) S. value-if(S. value < 0) up(S 1) down(S 2) else up(S 1) up(S): block current process down(S 1) S. value++ if(S. value ≤ 0) up(S 2) up(S 1) value field simulates a semaphore counter wake-up some blocked process This code does not work. Why? Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 41

Counting semaphore by binary semaphores – try #1 Problematic scenario: Suppose S. value =

Counting semaphore by binary semaphores – try #1 Problematic scenario: Suppose S. value = 0 down(S): up(S): down(S 1) S. value- if(S. value < 0) L 1: up(S 1) L 2: down(S 2) else up(S 1) down(S 1) S. value++ if(S. value ≤ 0) up(S 2) up(S 1) block asking process wake-up some BLOCKED process P 1 down(S), S. value = -1 P 1 is preempted between lines L 1 and L 2 P 2 down(S), S. value = -1 P 2 is preempted between lines L 1 and L 2 P 3 performs up(S) S. value = -1, S 2. value=1 P 4 performs up(S) S. value = -2, S 2. value=1 there is still nobody to wakeup P 1 re-scheduled and perform L 2 P 1 runs P 2 re-scheduled and perform L 2 P 2 is BLOCKED on S 2. Deadlock. Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 42

Counting semaphore by binary semaphores – try #2 Hemmendinger, 1988 down(S): down(S 1) S.

Counting semaphore by binary semaphores – try #2 Hemmendinger, 1988 down(S): down(S 1) S. value-if(S. value < 0) up(S 1) L 1: L 2: down(S 2) up(S 1) we removed ‘else’ up(S): down(S 1) S. value++ if(S. value ≤ 0) up(S 2) else up(S 1) we added ‘else’ Idea: do not up(S 2) twice, give a waked-up process down(S 2) first. If S. value is non-positive, S 1 stays locked, locked and only the process that already downs S 1 can up S 1 when this process is re-scheduled. Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 43

Counting semaphore by binary semaphores – try #2 Hemmendinger, 1988 Problematic scenario of try

Counting semaphore by binary semaphores – try #2 Hemmendinger, 1988 Problematic scenario of try #1: Suppose S. value = 0 down(S): up(S): down(S 1) S. value-if(S. value < 0) up(S 1) L 1: L 2: down(S 2) up(S 1) we removed ‘else’ down(S 1) S. value++ if(S. value ≤ 0) up(S 2) else up(S 1) we added ‘else’ Does this code work? Yes, but… P 1 down(S), S. value = -1 P 1 is preempted between lines L 1 and L 2 P 2 down(S), S. value = -2 P 2 is preempted between lines L 1 and L 2 P 3 performs up(S) S. value = -1, S 2 = 1, S 1 is still 0 P 4 performs up(S) P 4 is BLOCKED on S 1 P 1 is re-scheduled and performs L 2 S 2 = 0 P 1 up(S 1) P 4 wakes-up, S 1 is still 0 P 2 re-scheduled and perform L 2 P 2 is BLOCKED on S 2. P 2 would be later waked-up by P 4. Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 44

Counting semaphore by binary semaphores – try #2 Hemmendinger, 1988 down(S): down(S 1) S.

Counting semaphore by binary semaphores – try #2 Hemmendinger, 1988 down(S): down(S 1) S. value-if(S. value < 0) up(S 1) L 1: L 2: down(S 2) up(S 1) we removed ‘else’ up(S): down(S 1) S. value++ if(S. value ≤ 0) up(S 2) else up(S 1) we added ‘else’ Does this code work? Yes, but… Let’s try to use this counting semaphore for producersconsumers. Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 45

try #2 – for producers-consumers Consider a bounded-buffer of 5 slots. Consider 6 producers

try #2 – for producers-consumers Consider a bounded-buffer of 5 slots. Consider 6 producers each filling five slots in turn. 1 2 bounded-buffer 3 4 producers consumer 5 6 Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 46

try #2 – for producers-consumers 1. five slots are filled by first producer 1.

try #2 – for producers-consumers 1. five slots are filled by first producer 1. 1 2 bounded-buffer 3 4 producers consumer 5 6 Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 47

try #2 – for producers-consumers 2. second producer tries to insert, and is blocked

try #2 – for producers-consumers 2. second producer tries to insert, and is blocked 2. 1 2 bounded-buffer 3 4 producers consumer 5 6 Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 48

try #2 – for producers-consumers 3. third producer tries to insert, and is blocked

try #2 – for producers-consumers 3. third producer tries to insert, and is blocked 3. 1 2 bounded-buffer 3 4 producers consumer 5 6 Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 49

try #2 – for producers-consumers 4. fourth producer tries to insert, and is blocked

try #2 – for producers-consumers 4. fourth producer tries to insert, and is blocked 4. 1 2 bounded-buffer 3 4 producers consumer 5 6 Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 50

try #2 – for producers-consumers 5. fifth producer tries to insert, and is blocked

try #2 – for producers-consumers 5. fifth producer tries to insert, and is blocked 5. 1 2 bounded-buffer 3 4 producers consumer 5 6 Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 51

try #2 – for producers-consumers 6. sixth producer tries to insert, and is blocked

try #2 – for producers-consumers 6. sixth producer tries to insert, and is blocked 6. Five producers are blocked now … 1 2 bounded-buffer 3 4 producers consumer 5 6 Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 52

try #2 – for producers-consumers 7. Consumer removes one item, and wake up one

try #2 – for producers-consumers 7. Consumer removes one item, and wake up one of the blocked 7. producers. Consumer would stay blocked until the waked-up producer adds item. Let’s see why… 1 2 bounded-buffer 3 4 producers consumer 5 6 Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 53

try #2 – for producers-consumers producer: while(TRUE) produce_item(&item) down(&empty) down(&mutex) down insert_item(item) up(&mutex) up

try #2 – for producers-consumers producer: while(TRUE) produce_item(&item) down(&empty) down(&mutex) down insert_item(item) up(&mutex) up up(&full) up consumer : while(TRUE) down(&full) down(&mutex) down remove_item(&item) up(&mutex) up up(&empty) up consume_item(item) Counting semaphore S: down(S): down(S 1) S. value-if(S. value < 0) up(S 1) down(S 2) up(S 1) up(S): down(S 1) S. value++ if(S. value ≤ 0) up(S 2) else up(S 1) empty. value=-5, since 5 producers tried to add items, and were BLOCKED on empty semaphore • consumer wants to remove the first item from buffer • after removing the item, consumer executes up(empty) o since if(empty. value<=0) holds, consumer up(S 2) (this would wake-up one of the producers BLOCKED on empty semaphore), but does not up(S 1) • consumer wants to remove second item from buffer • after removing the item, consumer executes up(empty) o consumer executes down(S 1) and is BLOCKED since S 1 was not up before o only the waked-up producer would up(S 1) after this producer adds item to the buffer • consumer must wait, and cannot consume all five items. We lost concurrency between consumers and producers. 54 Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky

try #2 – for producers-consumers 7. Consumer removes one item, and wake up one

try #2 – for producers-consumers 7. Consumer removes one item, and wake up one of the blocked 7. producers. Consumer would stay blocked until the waked-up producer adds item. 1 2 bounded-buffer 3 4 producers consumer 5 6 Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 55

try #2 – for producers-consumers 8. Consumer must consume, only then another producer wakes

try #2 – for producers-consumers 8. Consumer must consume, only then another producer wakes up and produces an item 1 2 bounded-buffer 3 4 producers consumer 5 6 Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 56

try #2 – for producers-consumers 8. Consumer must consume, only then another producer wakes

try #2 – for producers-consumers 8. Consumer must consume, only then another producer wakes up and produces an item 1 2 bounded-buffer 3 4 producers consumer 5 6 Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 57

try #2 – for producers-consumers Once again… 1 2 bounded-buffer 3 4 producers consumer

try #2 – for producers-consumers Once again… 1 2 bounded-buffer 3 4 producers consumer 5 6 Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 58

try #2 – for producers-consumers Producers and consumers work alternately, and this And again…

try #2 – for producers-consumers Producers and consumers work alternately, and this And again… decreases concurrency 1 2 bounded-buffer 3 4 producers consumer 5 6 Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 59

Counting semaphore by binary semaphores – try #3 P. A. Kearns, 1988 up(S): down(S):

Counting semaphore by binary semaphores – try #3 P. A. Kearns, 1988 up(S): 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) up(S 2) up(S 1) down(S 1) S. value++ if(S. value <= 0) S. wake++ up(S 2) up(S 1) if there are more wakes left, we up(S 2), to let some other BLOCKED process to wakeup and down(S 2) successfully ‘wake’ variable remembers number of wakeups, and thus let them not to get lost Is this code correct ? NO. Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky Note that each up(S) both wake-up somebody, and increments wake. 60

Counting semaphore by binary semaphores – try #3 P. A. Kearns, 1988 up(S): down(S):

Counting semaphore by binary semaphores – try #3 P. A. Kearns, 1988 up(S): 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) up(S 2) up(S 1) down(S 1) S. value++ if(S. value <= 0) S. wake++ up(S 2) up(S 1) Problematic scenario: Assume semaphore state: S. value = 1 P 0, …, P 7 perform down(S) P 0 goes through, P 1, …, P 7 are BLOCKED S. value = -7 P 8, …, P 11 perform up(S) and wakeup P 1, … P 4 S. wake = 4 S. value = -3 P 1 performs: S. wake--, up(S 2) wakeup P 5 P 2 performs: S. wake--, up(S 2) wakeup P 6 P 3 performs: S. wake--, up(S 2) wakeup P 7 4 up(S) operations have released 7 down(S) operations… Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 61

Counting semaphore by binary semaphores – try #4 Hemmendinger, 1989 up(S): down(S): down(S 1)

Counting semaphore by binary semaphores – try #4 Hemmendinger, 1989 up(S): 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) up(S 2) up(S 1) down(S 1) S. value++ if(S. value <= 0) S. wake++ if (S. wake == 1) up(S 2) up(S 1) only if wake==1, we wake-up BLOCKED process Is this code correct ? Yes. Let’s see the previous problematic scenario solved… Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 62

Counting semaphore by binary semaphores – try #4 Hemmendinger, 1989 up(S): down(S): down(S 1)

Counting semaphore by binary semaphores – try #4 Hemmendinger, 1989 up(S): 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) up(S 2) up(S 1) down(S 1) S. value++ if(S. value <= 0) S. wake++ if (S. wake == 1) up(S 2) up(S 1) Previously problematic scenario: P 0. . P 7 perform down(S) P 0 goes through, P 1. . P 7 blocked S. value = -7 P 8. . P 11 perform up(S) P 8 wake-ups P 1 S. wake = 4 S. value = -3 P 1 performs: S. wake— S. wake=0, thus P 1 does not up(S 2) Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 63

Counting semaphore by binary semaphores – try #5 Barz, 1983 down(S): down(S 2) down(S

Counting semaphore by binary semaphores – try #5 Barz, 1983 down(S): down(S 2) down(S 1) S. value- if (S. value>0) up(S 2) up(S 1) when first down(S 2) and then down(S 1), a process cannot miss its wakeup signal up(S): down(S 1) S. value++ if(S. value == 1) up(S 2) up(S 1) wakeup some other BLOCKED process, if there is any wakeup only first BLOCKED process (and this process would wakeup another one, and so on. . . This works, is simpler, and was published earlier(!)… What if we switch order of downs in down(S) ? Deadlock… Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 64

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, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 65

Event Counters Each process may wait for its own specific value, while semaphore has

Event Counters Each process may wait for its own specific value, while semaphore has only a single blocking value. Read(E): Advance(E): Await(E, v): return the current value of E increment E by 1, wakeup relevant BLOCKED processes BLOCKED until E ≥ v Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 66

Single producer-consumer with Event Counters producer apriori increments sequence, and then waits till “out”

Single producer-consumer with Event Counters producer apriori increments sequence, and then waits till “out” has free space for this item Initially: event_counter in=0 event_counter out=0 /* count inserted items */ /* count removed items */ producer: consumer: sequence. P=0 // count items while(True) produce_item(&item) sequence++ await(out, sequence-N) insert_item(item) advance(&in) sequence. C=0 // count items while(True) sequence++ await(in, sequence) remove_item(&item) advance(&out) consume_item(item) inform consumer apriori increments sequence, and then waits till “in” would contain this item waits for item inform producer if sequence-N<=0, there is a free slot in the buffer Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 67

Semaphores and Event Counters require access to common shared memory. In distributed systems this

Semaphores and Event Counters require access to common shared memory. In distributed systems this is inapplicable. For such cases, we may use Message Passing. Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 68

Message Passing – no shared memory send (destination, &message) receive (source, &message) /* block

Message Passing – no shared memory send (destination, &message) receive (source, &message) /* block while waiting*/ Implementation issues: • • we ignore all these by now acknowledgements (messages may be lost) message sequence numbers required to avoid message duplication unique process addresses (domains) authentication (validate sender’s identity) Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 69

Producer-consumer using message passing producer consumer: for (i = 1 to N) send(producer, &m)

Producer-consumer using message passing producer consumer: for (i = 1 to N) send(producer, &m) while(TRUE) receive(producer, &m) extract_item(&m, &item) send(producer, &m) consume_item(item) producer: /* send N empty messages */ /* get message with item */ /* send empty message */ producer may send an item only after getting an empty message m; // message buffer while(TRUE) produce_item(&item) receive(consumer, &m) /*wait for empty message*/ construct_message(&m, item) send(consumer, &m) /* send item */ Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky consumer 70

Should semaphore be fair ? An unfair semaphore does not guarantee that the wakeup

Should semaphore be fair ? An unfair semaphore does not guarantee that the wakeup unfair semaphore order of processes is similar to their falling asleep order. Should we wakeup the process A first ? Because it may conflict with OS scheduler Semaphore struct: value L A B C NOT SURE. Why ? Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 71

Should semaphore be fair ? An unfair semaphore does not guarantee that the wakeup

Should semaphore be fair ? An unfair semaphore does not guarantee that the wakeup unfair semaphore order of processes is similar to their falling asleep order. Semaphore struct: A’s priority=8 B’s priority=12 C’s priority=4 value L A B C According to OS scheduler, process C should run first since its (Unix-style) priority is highest ! Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 72

Fairness of semaphores If we do prefer fair semaphore, there are several levels of

Fairness of semaphores If we do prefer fair semaphore, there are several levels of fairness: • Weak fairness: if process A is running on semaphore S, and when A exits S there are P 1…PN processes BLOCKED on S, at least one of P 1…PN should enter S before A re-enters S • Strong fairness: if process A is blocked on semaphore S, there is upper bound on number of processes that may re-enter S before A • Strongest fairness: FIFO Operating Systems, Spring 2020, I. Dinur, D. Hendler and M. Kogan-Sadetsky 73