readers writers readers writers
play

Readers-Writers Readers-Writers Shared: Reader: semaphore mutex, - PDF document

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


  1. 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

  2. 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

  3. 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

  4. 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

  5. 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

  6. 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

  7. 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

  8. 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

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend