View
214
Download
0
Tags:
Embed Size (px)
Citation preview
OS Fall’02
Concurrency
Operating Systems Fall 2002
OS Fall’02
Concurrency pros and cons Concurrency is good for users
One of the reasons for multiprogramming Working on the same problem, simultaneous
execution of programs, background execution
Concurrency is a “pain in the neck” for the system
Access to shared data structuresDeadlock due to resource contentionEnabling process interaction
OS Fall’02
Mutual Exclusion OS is an instance of concurrent
programmingMultiple activities may take place in the same time
Concurrent execution of operations involving multiple steps is problematic
Example: updating linked list Concurrent access to a shared data
structure must be mutually exclusive
OS Fall’02
new->next=current.next
current
new
current
new
current.next=new
insert_after(current,new):
OS Fall’02
tmp=current.next;current.next=current.next.next;free(tmp);
current
current
remove_next(current):
OS Fall’02
current
new
current
new
current
new
OS Fall’02
Atomic operations A generic solution is to execute an
operation atomicallyAll the steps are perceived as executed in a single point of time
insert_after(current,new) remove_next(current), or
remove_next(current) insert_after(current,new)
OS Fall’02
The Critical Section Model A code within a
critical section must be executed exclusively by a single process
do {
critical section
remainder section
} while(1)
entry section
exit section
OS Fall’02
Linked list exampledo {
remainder section
} while(1)
entry section
exit section
do {
remainder section
} while(1)
entry section
exit section
new->next=current.next
current.next=new
tmp=current.next;current.next=current.next.next;free(tmp);
OS Fall’02
The Critical Section Problem n processes P0,…,Pn-1
Processes are communicating through shared atomic read/write variables
x is a shared variable, l is a local variableRead: takes the current value:
Write: assigns a provided value:){...}6(
;
xif
xl
;5x
OS Fall’02
Requirements Mutual Exclusion: If process Pi is
executing its C.S., then no other process is in its C.S.
Progress: If Pi is in its entry section and no process is in C.S., then some process eventually enters C.S.
Fairness: If no process remains in C.S. forever, then each process requesting entry to C.S. will be eventually let into C.S.
OS Fall’02
Solving the CS problem (n=2)
while(1)}
sectionremainder
section critical
);!( while
;
{ do
: Process
nothingdo
iturn
iturn
Pi
;:Shared turn {0,1} enum
OS Fall’02
Solving the CS problem (n=2)
while(1)}
sectionremainder
;1
section critical
);( while
{ do
; Process
iturn
iturn !
Pi
;:Shared turn {0,1} enum
OS Fall’02
Solving the CS problem (n=2)
while(1)}
sectionremainder
;][
section critical
]);1[(
;][
{ do
: Process
falseiflag
iflagwhile
trueiflag
Pi
]2[ :Shared flagboolean
OS Fall’02
Peterson’s algorithm for n=2
while(1)}
sectionremainder
;][
section critical
);1&&][(
;1
;][
{ do
: Process
falseiflag
iturnjflagwhile
iturn
trueiflag
Pi
; {0,1}];2[ :Shared turn enumflagboolean
OS Fall’02
Bakery algorithm of Lamport Critical section algorithm for any
n>1 Each time a process is requesting an
entry to CS, assign it a ticket which is
Unique and monotonically increasing
Let the process into CS in the order of their numbers
OS Fall’02
Choosing a ticket;[n]boolean];n[ int:Shared choosing number
;1])1[],1[],0[max(][ nnumbernumbernumberinumber
)],[()],[( iinumberjjnumber Does not guarantee uniqueness! Use process Ids:
;][
;1])1[],1[],0[max(][
;][
falseichoosing
nnumbernumbernumberinumber
trueichoosing
Process need to know that somebody perhaps chose a smaller number:
OS Fall’02
Bakery algorithm for n processes
while(1)}sectionremainder ;0][
section critical}
)));],[()],[&((&)0]![((while]);[(while
{ );;0(for;][
;1])1[],1[],0[max(][;][
{ do Process
inumber
iinumberjjnumberjnumberjchoosing
jnjjfalseichoosing
nnumbernumbernumberinumbertrueichoosing
Pi
OS Fall’02
Correctness
)],[()],[( thensection, critical in the is if ,any For
iinumberjjnumberPij j
Lemma:
Mutual exclusion is immediate from this lemma
It is easy to show that Progress and Fairness holdas well (Exercise 47 in the notes :-)
OS Fall’02
Hardware primitives Elementary building blocks capable of
performing certain steps atomicallyShould be universal to allow for solving versatile synchronization problems
Several such primitives were identified:Test-and-setFetch-and-addCompare-and-swap
OS Fall’02
Test-and-Set
test-and-set(lock)
{temp=lock;lock=1;return temp;
}
Shared int lock, initially 0do {
while(test-and-set(lock));critical section;
lock=0;reminder section;
} while(1);
OS Fall’02
Higher level abstractions Atomic primitives bring convenience Using hardware primitives make
programs non-portable Higher level software abstractions
are represented bySemaphoresMonitors
OS Fall’02
Semaphores Invented by Edsger Dijkstra in 1968 Interface consists of two primitives:
P() and V()
}
;
);0(
{)(
S
Swhile
SP
}
;
{)(
S
SV
OS Fall’02
Notes on the Language Dutch: P: Proberen, V: Verhogen Hebrew: P: חותפ , V: עודו English: P(): wait(), V(): signal()
OS Fall’02
Semaphores: initial value Initial value of a semaphore indicates
how many identical instances of the critical resource exist
A semaphore initialized to 1 is called a mutex (mutual exclusion)
P(mutex);critical sectionV(mutex);
OS Fall’02
Programming with semaphores
Semaphores is a powerful programming abstraction
Define a semaphore for each critical resource
E.g., one for each linked listGranularity?
Concurrent processes access appropriate semaphores when synch. is needed
OS Fall’02
Implementing semaphores All the CS solutions so far imply busy
waiting: Burning CPU cycles while being blocked
Semaphore definition does not necessarily imply busy waiting!
Semaphores can be implemented efficiently by the systemP() is explicitly telling the system: “Hey, I cannot proceed, you can preempt me”
OS Fall’02
Implementing Semaphores Hence, in fact, a semaphore is a record (structure):
type semaphore = record count: integer; queue: list of process end;var S: semaphore;
When a process must wait for a semaphore S, it is blocked and put on the semaphore’s queue
The signal operation removes (acc. to a fair policy like FIFO) one process from the queue and puts it in the list of ready processes
OS Fall’02
Semaphore’s operations (atomic)
P(S): S.count--; if (S.count<0) { place this process in S.queue block this process; }
V(S): S.count++; if (S.count <= 0) { remove a process P from S.queue place this process P on ready list }
S.count must be initialized to a nonnegative value (depending on application)
OS Fall’02
The producer/consumer problem
A producer process produces information that is consumed by a consumer process
We need a buffer to hold items that are produced and eventually consumed
A common paradigm for cooperating processes
OS Fall’02
P/C: unbounded buffer We assume first an unbounded buffer
consisting of a linear array of elements in points to the next item to be produced out points to the next item to be consumed
OS Fall’02
P/C: unbounded buffer (solution) We need a semaphore S to perform
mutual exclusion on the buffer: only 1 process at a time can access the buffer
We need another semaphore N to synchronize producer and consumer on the number N (= in - out) of items in the buffer
an item can be consumed only after it has been created
OS Fall’02
Solution of P/C: unbounded buffer
Producer:repeat produce v; P(S); append(v); V(S); V(N);forever
Consumer:repeat P(N); P(S); w:=take(); V(S); consume(w);forever
Initialization: S.count:=1; N.count:=0; in:=out:=0;
append(v):b[in]:=v;in++;
take():w:=b[out];out++;return w;
OS Fall’02
P/C: finite circular buffer of size k
can consume only when number N of (consumable) items is at least 1 (now: N!=in-out)
can produce only when number E of empty spaces is at least 1
OS Fall’02
P/C: finite circular buffer of size k As before:
we need a semaphore S to have mutual exclusion on buffer accesswe need a semaphore N to synchronize producer and consumer on the number of consumable items
In addition:we need a semaphore E to synchronize producer and consumer on the number of empty spaces
OS Fall’02
Solution of P/C: finite circular buffer of size k
Initialization: S.count:=1; in:=0; N.count:=0; out:=0; E.count:=k;
Producer:repeat produce v; P(E); P(S); append(v); V(S); V(N);forever
Consumer:repeat P(N); P(S); w:=take(); V(S); V(E); consume(w);forever
critical sections
append(v):b[in]:=v;in:=(in+1) mod k;
take():w:=b[out];out:=(out+1) mod k;return w;
OS Fall’02
Monitorsmonitor monitor-name{
shared variable declarations
procedure P1(…) {…
}…
procedure Pn() {…
}}
Only a single process at a time can be active within the monitor
=> other processes calling Pi() are queued
Conditional variables for finer grained synchronization
x.wait() suspend the execution until another process calls x.signal()
OS Fall’02
Monitor Awaiting processes
are either in the entrance queue or in a condition queue
A process puts itself into condition queue cn by issuing cwait(cn)
csignal(cn) brings into the monitor 1 process in condition cn queue
Hence csignal(cn) blocks the calling process and puts it in the urgent queue (unless csignal is the last operation of the monitor procedure)
OS Fall’02
Producer/Consumer problem
Two types of processes:
producersconsumers
Synchronization is now confined within the monitor
append(.) and take(.) are procedures within the monitor: are the only means by which P/C can access the buffer
If these procedures are correct, synchronization will be correct for all participating processes
ProducerI:repeat produce v; Append(v);forever
ConsumerI:repeat Take(v); consume v;forever
OS Fall’02
Monitor for the bounded P/C problem Monitor needs to hold the buffer:
buffer: array[0..k-1] of items; needs two condition variables:
notfull: csignal(notfull) indicates that the buffer is not fullnotemty: csignal(notempty) indicates that the buffer is not empty
needs buffer pointers and counts:nextin: points to next item to be appendednextout: points to next item to be takencount: holds the number of items in buffer
OS Fall’02
Monitor for the bounded P/C problemMonitor boundedbuffer: buffer: array[0..k-1] of items; nextin:=0, nextout:=0, count:=0: integer; notfull, notempty: condition;
Append(v): if (count=k) cwait(notfull); buffer[nextin]:= v; nextin:= nextin+1 mod k; count++; csignal(notempty);
Take(v): if (count=0) cwait(notempty); v:= buffer[nextout]; nextout:= nextout+1 mod k; count--; csignal(notfull);