Too Much Pizza Person A Person B 3:00 Look in fridge. Pizza! 3:05 Leave for store. Look in fridge. Pizza! 3:10 Arrive at store. Leave for store. Operating Systems 3:15 Buy pizza. Arrive at store. 3:20 Arrive home. Buy pizza. 3:25 Put away pizza. Arrive home. Process Synchronization 3:30 Put pizza away. Oh no! Producer Consumer Cooperating Processes • Consider: print spooler • Model for cooperating processes – Enter file name in spooler queue • Producer “produces” and item that – Printer daemon checks queue and prints consumer “consumes” • Bounded buffer (shared memory) A B free 9 item buffer[MAX]; /* queue */ int counter; /* num items */ letter hw1 lab1.c (empty) ... ... 6 7 8 9 � “Race conditions” (ugh!) � (Hey, you! Show demo!) Producer Consumer item i; /* item produced */ item i; /* item consumed */ int in; /* put next item */ int out; /* take next item */ while (1) { while (1) { while (counter == 0) {/*no-op*/} produce an item while (counter == MAX){/*no-op*/} item = buffer[out]; buffer[in] = item; out = (out + 1) % MAX; in = (in + 1) % MAX; counter = counter - 1; counter = counter + 1; consume the item } } 1
Trouble! Critical Section R1 = counter {R1 = 5} • Mutual Exclusion P: P: R1 = R1 + 1 {R1 = 6} – Only one process inside critical region • Progress R2 = counter {R2 = 5} C: – No process outside critical region may block other C: R2 = R2 -1 {R2 = 4} processes wanting in • Bounded Waiting counter = R2 {counter = 4} C: – No process should have to wait forever (starvation) P: counter = R1 {counter = 6} • Note, no assumptions about speed! First Try: Strict Alternation Questions • How does Windows NT avoid process int turn; /* shared, id of turn */ starvation? • What is a “race condition”? while(1) { while (turn <> my_pid) { /* no-op */} • What are 3 properties necessary for a /* critical section */ correct “critical region” solution? turn = your_pid /* remainder section */ } Second Try Third Try: Peterson’s Solution int flag[1]; /* boolean */ int flag[1]; /* boolean */ int turn; while(1) { while(1) { flag[my_pid] = true; flag[my_pid] = true; turn = your_pid; while (flag[your_pid]) { /* no-op */} while (flag[your_pid] && /* critical section */ turn==your_pid){ /* noop */} flag[my_pid] = false; /* critical section */ /* remainder section */ flag[my_pid] = false; } /* remainder section */ } 2
Multiple-Processes Multiple-Processes choosing[my_pid] = true; num[my_pid] = max(num[0],num[1] …)+1 • “Bakery Algorithm” choosing[my_pid] = false; • Common data structures for (j=0; j<n; j++) { boolean choosing[n]; while(choosing[j]) { } int num[n]; while(num[j]!=0 && • Ordering of processes (num[j],j)<(num[my_pid],my_pid)){} } – If same number, can decide “winner” /* critical section */ num[my_pid] = 0; Synchronization Hardware Using Test_and_Set • Test-and-Set: returns and modifies atomically while(1) { while (Test_and_Set(lock)) { } int Test_and_Set(int target) { /* critical section */ int temp; lock = false; temp = target; /* remainder section */ target = true; } return temp; • All the solutions so far have required } “Busy Waiting” … what is that? Critical Section w/Semaphores Semaphores semaphore mutex; /* shared */ • Do not require “busy waiting” • Semaphore S (shared, often initially =1) while(1) { – integer variable wait(mutex); – accessed via two (indivisible) atomic operations /* critical section */ wait(S): S = S - 1 signal(mutex); if S<0 then block(S) signal(S): S = S + 1 /* remainder section */ if S<=0 then wakeup(S) } (Hey, you! Show demo!) 3
Review Semaphore Implementation • What is Peterson’s Solution? • How do you make sure the signal and the • What does Test_and_Set do? wait operations are atomic? • What is one major advantage of semaphores over the above two? Design Technique: Reducing a Semaphore Implementation Problem to a Special Case • Simple solution not adequate • Disable interrupts – Why is this not evil? – ex: disabling interrupts • Problem solution requires special case – Multi-processors? solution • Use correct software solution – ex: protecting S for semaphores • Use special hardware, i.e.- Test-and-Set • Simple solution adequate for special case • Other examples: – name servers, on-line help Classical Synchronization Trouble! Problems signal(S) wait(S) • Bounded Buffer /* cr */ /* cr */ • Readers Writers wait(S) wait(S) • Dining Philosophers /* cr */ Process A Process B wait(S) wait(Q) wait(Q) wait(S) … … 4
Dining Philosophers Dining Philosophers Philosopher i: while (1) { • Philosophers – Think /* think… */ – Sit wait(chopstick[i]); – Eat wait(chopstick[i+1 % 5]); – Think • Need 2 chopsticks to /* eat */ eat signal(chopstick[i]); signal(chopstick[i+1 % 5]); } Other Solutions • Allow at most N-1 to sit at a time • Allow to pick up chopsticks only if both are Other Solutions? available • Asymmetric solution (odd L-R, even R-L) Outline Readers-Writers • Need for synchronization • Readers only read the content of object – why? • Writers read and write the object • Solutions that require busy waiting • Critical region: – what? • Semaphores – No processes – what are they? – One or more readers (no writers) • Classical problems – One writer (nothing else) – dining philosophers • Solutions favor Reader or Writer – reader/writers (today) 5
Readers-Writers Readers-Writers Shared: Reader: semaphore mutex, wrt; wait(mutex); int readcount; readcount = readcount + 1; if (readcount==1) wait(wrt); Writer: signal(mutex); wait(wrt) /* read stuff */ /* write stuff */ wait(mutex); signal(wrt); readcount = readcount - 1; if (readcount==0) signal(wrt); signal(mutex); Monitors Monitor Producer-Consumer • High-level construct monitor ProducerConsumer { • Collection of: condition full, empty; – variables integer count; – data structures /* function prototypes */ – functions void enter(item i); – Like C++ class item remove(); • One process active inside } • “Condition” variable void producer(); – not counters like semaphores void consumer(); Monitor Producer-Consumer Monitor Producer-Consumer void producer() { void enter (item i) { item i; if (count == N) wait(full); while (1) { /* add item i */ /* produce item i */ count = count + 1; ProducerConsumer.enter(i); if (count == 1) then signal(empty); } } } item remove () { void consumer() { if (count == 0) then wait(empty); item i; /* remove item into i */ while (1) { count = count - 1; i = ProducerConsumer.remove(); if (count == N-1) then signal(full); /* consume item i */ return i; } } } 6
Ex: Cond. Crit. Region w/Sem Other IPC Synchronization region X when B do S { wait(x-mutex); • Critical Regions if (!B) { • Conditional Critical Regions x-count = x-count + 1; • Sequencers signal(x-mutex); • Path Expressions wait(x-delay); • Serializers /* wakeup loop */ • ... • All essentially equivalent in terms of semantics. x-count = x-count -1 Can build each other! } /* remainder */ Ex: Wakeup Loop Ex: Remainder while (!B) { x-temp = x-temp + 1; S; if (x-temp < x-count) if (x-count > 0) { signal(x-delay); x-temp = 0; else signal(x-delay); signal(x-mutex); } else wait(x-delay); signal(x-mutex); } Trouble? Message Passing • Monitors and Regions attractive, but ... • Communicate information from one process – Not supported by C, C++, Pascal ... to another via primitives: � semaphores easy to add send(dest, &message) • Monitors, Semaphores, Regions ... receive(source, &message) – require shared memory • Receiver can specify ANY – break on multiple CPU (w/own mem) • Receiver can block (or not) – break distributed systems • Message Passing! 7
Producer-Consumer Consumer Mailbox void Producer() { while (TRUE) { /* produce item */ void Consumer { build_message(&m, item); for (i=0; i<N; i++) send(consumer, &m); send(producer, &m); /* N empties */ receive(consumer, &m); /* wait for ack */ while(1) { }} receive(producer, &m); void Consumer { extract_item(&m, &item); while(1) { send(producer, &m); /* ack */ receive(producer, &m); /* consume item */ “Rendezvous” extract_item(&m, &item); } send(producer, &m); /* ack */ } /* consume item */ }} New Troubles • Scrambled messages ( checksum ) • Lost messages ( acknowledgements ) • Lost acknowledgements ( sequence no .) New Troubles with Messages? • Process unreachable (down, terminates) • Naming • Authentication • Performance (from copying, message building) • (Take cs4514!) 8
Recommend
More recommend