OS Fall’02 Concurrency Operating Systems Fall 2002

Preview:

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);

Recommended