Date post: | 17-Jan-2016 |
Category: |
Documents |
Upload: | lynn-mitchell |
View: | 220 times |
Download: | 1 times |
TANNENBAUMSECTION 2.3
INTERPROCESS COMMUNICATION3
OPERATING SYSTEMS
PRODUCER/CONSUMERBOUNDED BUFFER
• Producer puts items into a buffer• Consumer removes items from buffer• Producer issue: attempts to put an item in a full
buffer• Consumer issue: attempts to remove an item
from an empty buffer
PRODUCER/CONSUMER MODEL 1
prod_cons1(){ const int N = const int N = 100;100; int count = 0; int count = 0;
parbeginparbegin
{{
producer();producer();
consumer();consumer();
}}
parendparend
}}
producer()producer()
{{
int item;int item;
while(1)while(1)
{{ item = make_item(); if (count == N) sleep(); add(item); ++count; if (count == 1) wakeup(consumer); }}
consumer()consumer()
{{
int item;int item;
while(1)while(1)
{{ if (count == 0) sleep(); --count; if (count == (N – 1)) wakeup(producer) take(item) }}
ACCESS TO COUNTIS UNCONSTRAINED
1. buffer is empty2. consumer tests count3. context-switch before sleep4. producer puts an item in the buffer5. increments count to 16. tries to wakeup consumer, but consumer is not
asleep7. produces goes on filling the buffer then goes to
sleep8. consumer runs and goes to sleep9. Could be solved with either peterson or tsl
SEMAPHORE
• ADT proposed by Dijkstra• composed of a single member variable and two
uninterruptible operationssemaphore• variable, s, guards mutex gate• down(s) • inspects s• if s== 0, there is a process in CS• decrements s
• up(s)• increments s
SEMAPHORES COME IN TWO FLAVORS
• Spinlocks: implemented with TSL, are either set or unset• Counting Semaphores: use sleep/wakeup
SPINLOCK SEMAPHORE
class spinlock{ private int s; public: spinlock() { s = 1; }
void down() //uninterruptible { while (s== 0); --s;}
void up() { ++s; }
void unset() //used for synchronization { --s;} };
N-PROCESS EXAMPLE
N_Process(){ spinlock spin;
parbeginparbegin
{{
proc0();proc0();
proc1();proc1();
}}
parendparend
}}
//All N processes look //All N processes look like like
//this//this
proc_0proc_0
{{
while(1)while(1)
{{ spin.down(); cs(); spin.up(); }}
• proc0 runs and calls down
• S == 1, so s is decremented to 0
• Enter CS• proc1, calls down,
fails test and sits in loop
• proc2, calls down, fails test and sits in loop
• proc0 runs, finishes CS, calls up to increment s
• proc2 runs, passes while test, decrements s, leaves down, enters CS
SPINLOCK CAN SYNCHRONIZE PROCESSES. PROC0 BEFORE PROC1
synch(){ spinlock spin; spin.unset();
parbeginparbegin
{{
proc0();proc0();
proc1();proc1();
}}
parendparend
}}
proc0proc0
{{ cs(); spin.up(); }
proc1proc1
{{ spin.down() cs()}
PROC0 CAN’T CONSUME Y UNTIL PROC1 PRODUCES ITPROC1 CAN’T CONSUME X UNTIL PROC0 PRODUCES IT
synch(){ spinlock s1, s2; s1.unset(); s2.unset();
parbeginparbegin
{{
proc0();proc0();
proc1();proc1();
}}
parendparend
}}
proc_0proc_0
{{
while(1)while(1)
{{
produce(x);produce(x);
s1.up();s1.up();
s2.down();s2.down();
consume(y);consume(y);
}}
}}
proc_1proc_1
{{
while(1)while(1)
{{ s1.down(); s1.down();
consume(x);consume(x);
produce(y);produce(y);
s2.up();s2.up();
}}
}}
Demonstrate with a table: s1.s s2.s x y
COUNTING SEMAPHORES
• Instead of busy-wait, process goes to sleep• Process executing up operations wakes sleeping
processes• We have to keep track of which processes are
sleeping on a semaphore because they don’t test themselves (as in busy-wait)• Include with our class a pointer to a linked list of
pointers to process control blocks
pc1 p2 p3 pn
P ...
COUNTING SEMAPHORES
Class Semaphore{ private: int s; pcb_list_lst; public: Semaphore(int value) { s = value; lst == NULL; }
down() { s--; if (s < 0) { l.add(this); sleep(); } }
up() { pcbptr* p; s++; if (s <= 0) { p = lst.delete() wakeup(p); }
N PROCESS SEMAPHORE EXAMPLE
cnt_sem(){ Semaphore s(1); parbegin { proc0(); ... procn-1(); } parend
procj(){ while(1) { S.down(); crit_sect(); S.up(); }}
SCENARIO
1. proc0() runs, calls down: value == 0, enters CS
2. proc1() runs, calls down: value == -1, fails test and blocks
3. proc2() runs, calls down: value == -2, fails test and blocks]
4. proc0() runs, finished CS, calls up: value == -1, removes p1 from sleep list, wakes up p1
lst p1
lst p1 p2
p1lst
PRODUCER-CONSUMERWITH SEMAPHORES
• Recall PC required two variables: count, collection of buffer slots item is to put into or extracted from• Both must be protected• Solution with three semaphores• empty: counts empty buffer slots, initially N• full: counts full buffer slots, initially 0• mutex: controls access to buffer, initially 1
PRODUCER-CONSUMER MODEL 2
prod_cons2(){ SemaphoreSemaphore
mutex(1),mutex(1),
empty(100),empty(100),
full(0);full(0);
parbeginparbegin
{{
prod();prod();
cons();cons();
}}
parendparend
}}
producer()producer()
{{
int item;int item;
while(1)while(1)
{{ item = make_item(); empty.down(); mutex.down(); add(item); mutex.up(); full.up(); }}
consumer()consumer()
{{
int item;int item;
while(1)while(1)
{{
full.down();full.down();
mutex.down();mutex.down();
take(&item);take(&item);
mutex.up();mutex.up();
empty.up();empty.up(); }}
SCENARIOS
#1•consumer runs: value == -1, blocks on full•producer runs: dec empty, dec mutex, enters cs, inc mutex, inc full full.s == 0, wakes up consumer
#2•Suppose full.s == 98, empty.s == 2, mutex.s == 1•producer runs: dec empty (so empty.s == 1), dec mutex (so mutex.s == 0), enters cs•consumer runs: dec full (so full.s == 97), dec mutex (so mutex.s == -1) consumer blocks on mutex•producer runs: inc mutex (so mutex.s == 0), wakes up consumer, inc full (so full.s == 98)•consumer runs: enters cs, inc mutex (so mutex.s == 1), inc empty (so empty.s == 2)
Semphore values: full.s == 98, empty.s == 2, mutex.s == 1Both Producer and consumer have run to completion. Semaphore values are as they were in the beginning
A TRAP
• Suppose we wrote producer this way:producer(){ int item; while(1) { item = make_item(); //order of mutex and empty shifted mutex.down(); empty.down(); add(item); mutex.up(); full.up(); }}
SUPPOSE WE WROTE THE PRODUCER LIKE THIS
• Suppose we wrote producer this way:producer(){ int item;
while(1) { item = make_item(); //order of mutex and empty shifted mutex.down(); empty.down(); add(item); mutex.up(); full.up(); }}
• producer runs: 100 times, empty.s == 0
• producer runs: dec mutex (mutex.s == 0)
dec mutex and blocks• consumer runs: dec mutex and blocks
Problem: producer claimed mutex flag before it was needed
CORRECT SOLUTIONS
• Peterson• software• two processes• busy-wait
• TSL• hardware• N processes• busy-wait
• Spinlock Semaphore• Hardware• N processes• busy-wait
• Counting Semaphore• Hardware• N processes• sleep/wakeup
BUILDING A MODEL OF PRODUCER/CONSUMER
Primitives•pipes: direct communication link between two linux processes•semaphore system calls in linux