consumer trouble
play

Consumer Trouble! item i; /* item consumed */ P: R1 = counter - 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. (Ch 4.4-4.6, 7.1-7.7) Oh no! Cooperating Processes Outline • Consider: print spooler • Need for synchronization – Enter file name in spooler queue – why? • Solutions that require busy waiting – Printer daemon checks queue and prints – what? • Semaphores A B free 9 – what are they? • Classical problems ... ... letter hw1 lab1.c (empty) – dining philosophers 6 7 8 9 – reader/writers • “Race conditions” (ugh!) • (Hey, you! Show demo!) Producer Consumer Producer item i; /* item produced */ • Model for cooperating processes int in; /* put next item */ • Producer “produces” and item that while (1) { consumer “consumes” produce an item • Bounded buffer (shared memory) while (counter == MAX){/*no-op*/} item buffer[MAX]; /* queue */ buffer[in] = item; int counter; /* num items */ in = (in + 1) % MAX; counter = counter + 1; } 1

  2. Consumer Trouble! item i; /* item consumed */ P: R1 = counter {R1 = 5} int out; /* take next item */ P: R1 = R1 + 1 {R1 = 6} while (1) { C: R2 = counter {R2 = 5} while (counter == 0) {/*no-op*/} C: R2 = R2 -1 {R2 = 4} item = buffer[out]; C: counter = R2 {counter = 4} out = (out + 1) % MAX; counter = counter - 1; P: counter = R1 {counter = 6} consume the item } Critical Section First Try: Strict Alternation • Mutual Exclusion int turn; /* shared, id of turn */ – Only one process inside critical region • Progress while(1) { – No process outside critical region may block other while (turn <> my_pid) { /* no-op */} processes wanting in /* critical section */ • Bounded Waiting turn = your_pid – No process should have to wait forever (starvation) • Note, no assumptions about speed! /* 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? Outline Semaphores • Need for synchronization • Do not require “busy waiting” (done) • Semaphore S (shared, often initially =1) – why? • Solutions that require busy waiting (done) – integer variable – what? – accessed via two (indivisible) atomic operations • Semaphores wait(S): S = S - 1 – what are they? • Classical problems if S<0 then block(S) signal(S): S = S + 1 – dining philosophers – reader/writers if S<=0 then wakeup(S) 3

  4. Critical Section w/Semaphores Semaphore Implementation semaphore mutex; /* shared */ • Disable interrupts – Why is this not evil? while(1) { – Multi-processors? wait(mutex); • Use correct software solution /* critical section */ • Use special hardware, i.e.- Test-and-Set signal(mutex); /* remainder section */ } (Hey, you! Show demo!) Design Technique: Reducing a Trouble! Problem to a Special Case signal(S) wait(S) • Simple solution not adequate /* cr */ /* cr */ – ex: disabling interrupts wait(S) wait(S) • Problem solution requires special case solution /* cr */ – ex: protecting S for semaphores • Simple solution adequate for special case • Other examples: Process A Process B – name servers, on-line help wait(S) wait(Q) wait(Q) wait(S) … … Classical Synchronization Dining Philosophers Problems • Bounded Buffer • Philosophers • Readers Writers – Think – Sit • Dining Philosophers – Eat – Think • Need 2 chopsticks to eat 4

  5. Dining Philosophers Other Solutions Philosopher i: • Allow at most N-1 to sit at a time while (1) { • Allow to pick up chopsticks only if both are /* think… */ wait(chopstick[i]); available • Asymmetric solution (odd L-R, even R-L) wait(chopstick[i+1 % 5]); /* eat */ signal(chopstick[i]); signal(chopstick[i+1 % 5]); } (Other solutions?) Readers-Writers Readers-Writers Shared: semaphore mutex, wrt; • Readers only read the content of object int readcount; • Writers read and write the object • Critical region: Writer: – No processes wait(wrt) – One or more readers (no writers) /* write stuff */ – One writer (nothing else) • Solutions favor Reader or Writer signal(wrt); Readers-Writers Monitors Reader: • High-level construct wait(mutex); • Collection of: readcount = readcount + 1; – variables if (readcount==1) wait(wrt); – data structures signal(mutex); – functions – Like C++ class /* read stuff */ • One process active inside wait(mutex); • “Condition” variable readcount = readcount - 1; – not counters like semaphores if (readcount==0) signal(wrt); signal(mutex); 5

  6. Monitor Producer-Consumer Monitor Producer-Consumer void producer() { item i; monitor ProducerConsumer { while (1) { condition full, empty; /* produce item i */ integer count; ProducerConsumer.enter(i); } /* function prototypes */ } void enter(item i); void consumer() { item remove(); item i; } while (1) { void producer(); i = ProducerConsumer.remove(); void consumer(); /* consume item i */ } } Other Process Synchronization Monitor Producer-Consumer Methods void enter (item i) { if (count == N) sleep(full); • Sequencers /* add item i */ • Path Expressions count = count + 1; • Serializers if (count == 1) then wakeup(empty); } • ... item remove () { • All essentially equivalent in terms of if (count == 0) then sleep(empty); /* remove item into i */ semantics. Can build each other! count = count - 1; if (count == N-1) then wakeup(full); return i; } Trouble? Inter Process Communication • Monitors and Regions attractive, but ... • How does one process communicate with another process? Some of the ways: – Not supported by C, C++, Pascal ... + semaphores easy to add – shared memory – read/write to shared region • Monitors, Semaphores, Regions ... + shmget(), shmctl() in Unix + Memory mapped files in WinNT/2000 – require shared memory – semaphores - signal notifies waiting process – break on multiple CPU (w/own mem) – software interrupts - process notified – break distributed systems asynchronously • In general, Inter-Process Communication – pipes - unidirectional stream communication (IPC) – message passing - processes send and receive – Move towards Message Passing messages. 6

  7. Pipes The Pipe • One process writes, 2nd process reads % ls | more 1 \0 b l a h . c Shell 2 3 ls more read fd write fd stdout stdin • Shell: • Bounded Buffer 1 create a pipe – shared buffer (Unix 4096K) 2 create a process for ls command, setting – block writes to full pipe stdout to write side of pipe – block reads to empty pipe 3 create a process for more command, setting stdin to read side of pipe (Hey, see sample code!) The Pipe Message Passing • Process inherits file descriptors from parent • Communicate information from one process – file descriptor 0 stdin, 1 stdout, 2 stderr • Process doesn't know (or care!) when reading to another via primitives: from keyboard, file, or process or writing to send(dest, &message) terminal, file, or process receive(source, &message) • System calls: • Receiver can specify ANY – read(fd, buffer, nbytes) ( scanf() built on top) • Receiver can block (or not) – write(fd, buffer, nbytes) ( printf() built on top) – pipe(rgfd) creates a pipe + rgfd array of 2 fd. Read from rgfd[0], write to rgfd[1] • (Hey, show sample code!) 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 */ }} 7

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