synchronicity ii introduction to operating systems: module 6

Post on 19-Jan-2018

218 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Review u Solutions to the critical section problem (CSP)  Software  Petersen’s algorithm (2 processes)  Bakery algorithm (3 or more processes)  Hardware  Disable interrupts  Special instructions (can’t solve the problem alone)  OS primitives (introduced in this module)  Semaphores  Monitors

TRANSCRIPT

Synchronicity II

Introduction to Operating Systems: Module 6

Review Synchronization

The problem of getting processes to work together Poor synchronization can result in a race condition

Two people access the same bank account via ATM The naïve solution to the bounded buffer problem

The critical section problem Is an instance of synchronization Formal criteria for a solution

Traditional: mutual exclusion, progress, bounded wait Last time: 6 equivalent, less difficult criteria

Review Solutions to the critical section problem (CSP)

Software Petersen’s algorithm (2 processes) Bakery algorithm (3 or more processes)

Hardware Disable interrupts Special instructions (can’t solve the problem alone)

OS primitives (introduced in this module) Semaphores Monitors

Software solutions to CSP Some solutions are hard to program, debug

Bakery algorithm Waiting processes are busy

Wastes CPU cycles It would be better to block the process

Like waiting for I/O Incurs overhead of a context switch Not efficient for very short critical sections

Hardware solutions to CSP: disable interrupts

On a uniprocessor: mutual exclusion is preserved but efficiency of execution is degraded: while in CS, we cannot interleave execution with other processes that are in RS

On a multiprocessor: mutual exclusion is not achieved

Generally not an acceptable solution

repeat disable interrupts critical section enable interrupts remainder sectionforever

Hardware solutions to CSP: Special machine instructions

Machine instructions can perform 2 actions atomically (indivisible) on the same memory location (ex: reading and testing)

The execution of such an instruction is mutually exclusive (even with multiple CPUs)

They can be used simply to provide mutual exclusion but need more complex algorithms for satisfying the requirements of the CSP

Synchronization Primitives

SemaphoresMonitors

Semaphores A semaphore is an abstract data

type Semaphores can be implemented

through Busy wait Blocking via system calls

Semaphores have a 2 method interface Wait( ) Signal( )

Wait Signal

Semaphore

Busy waiting semaphores

The simplest way to implement semaphores

Useful when critical sections last for a short time, or we have lots of CPUs

I is initialized to positive value (to allow someone in at the beginning)

S.wait(){ while (I<=1); I--;} S.signal(){ I++;}

I

Semaphore

Integer

Atomicity aspects

The testing and decrementing sequence in wait are atomic, but not the loop

Signal is atomic No two processes can be

allowed to execute atomic sections simultaneously

This can be implemented by other mechanisms, such as test-and-set

S.wait:

I <= 1

I - -

atomic

F

T

Using semaphores for solving critical section problems

For n processes Initialize I to 1 Then only 1 process is

allowed into CS (mutual exclusion)

To allow k processes into CS, we initialize I to k

Process Pi:repeat S.wait(); CS S.signal(); RSforever

Signal to a waiting process

Process Pi:repeat S.wait(); CS S.signal(); RSforever

Process Pj:repeat S.wait(); CS S.signal(); RSforever

Semaphores: the global view

Initialize I to 1

Semaphores synchronize processes

We have 2 processes: P1 and P2

Statement S1 in P1 needs to be performed before statement S2 in P2

Then define a semaphore “synch”

Initialize synch to 0

Proper synchronization is achieved by having in P1: S1; synch.signal();

And having in P2: synch.wait(); S2;

Semaphores: observations

When initial I>=0: the number of processes that can execute S.wait()

without being blocked = I I processes can enter the “limited capacity” section

When I becomes >=0, which waiting process enters the critical section? FCFS? Not specified Implementation dependent

Avoiding busy wait in semaphores To avoid busy waiting: when a process has to wait for a

semaphore to become greater than 0, it will be put in a blocked queue of processes waiting for this to happen

Queues can be FIFO, priority, etc.: OS has control on the order processes enter CS

In practice, wait and signal become system calls to the OS (such as I/O), which contains the semaphore implementation

There is a queue for every semaphore just as there is a queue for each I/O unit

Semaphores without busy waiting

class semaphore { private: int I; ProcessQueue queue; public: void signal(); void wait();} When a process must wait for a

semaphore S, it is blocked and put on the semaphore’s queue

The signal operation removes (by a fair policy like FIFO) one process from the queue and puts it in the list of ready processes

S.wait() { S.I--; if (S.I<0) S. enqueue(p)} S.signal(){ I++; if (s.I<=0) S.dequeue();}

Semaphore

Queue

-3 I

Semaphore’s operations (atomic)

S.wait() { S.I--; if (S.I<0) { block this process

place this process in S.queue}}

S.signal(){S.I++; if (S.I<=0) { remove a process from S.queue place it on ready list }}

The value to which S.count is initialized depends on the application

Semaphores: implementation wait and signal themselves contain critical

sections! How to implement them? Note that they are very short critical sections Solutions:

uniprocessor: disable interrupts during these operations (i.e.: for a very short period)

This does not work on a multiprocessor machine multiprocessor: use some busy waiting scheme

Busy waiting shouldn’t last long

Binary semaphores Similar to counting semaphores except that “count”

is Boolean valued Perhaps simpler to implement Can do anything counting semaphores can do Requires writing more code than counting

semaphores: must use additional counting variables protected by binary semaphores

Binary semaphoreswaitB(S){ if (S.value = 1) S.value = 0; else { block(this) S.queue.add(this) }}

signalB(S){ if (S.queue is empty) S.value = 1; else { process = S.queue.next(); readyQueue.add(process); }}

Semaphores Semaphores provide a structured tool for enforcing

mutual exclusion and coordinate processes. Avoid bus wait, but not completely. If used correctly, avoid deadlock and starvation. But if wait(S) and signal(S) are scattered among

several processes it may be difficult to use them correctly

Usage must be correct in all processes One bad (or malicious) process can fail the entire

collection of processes, cause deadlock, starvation

Monitors

Are high-level language constructs that provide equivalent functionality to that of semaphores but are easier to control

Found in many concurrent programming languages

Concurrent Pascal, Modula-3, C++, Java… Very appropriate for OO programming However each language has own ‘dialect’

Monitor Is a software module containing:

one or more procedures an initialization sequence local data variables

Characteristics: local variables accessible only by monitor’s procedures a process enters the monitor by invoking one of its

procedures only one process can be in the monitor at any given time

Monitor

The monitor ensures mutual exclusion: no need to program this constraint explicitly

Shared data within the monitor are protected The monitor locks on process entry Only one process can execute in the monitor at a time

Process synchronization is done by the programmer by using condition variables represent conditions on which a process may wait for

before executing in the monitor

Condition variables are local to the monitor

(accessible only within the monitor) have ADT methods:

cwait(a): blocks execution of the calling process on condition variable a

process can resume execution only if another process executes csignal(a)

csignal(a): resume execution of some process blocked on condition variable a

If several such process exists: choose any one (fifo or priority) If no such process exists: do nothing

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)

Monitors for the bounded buffer

Monitor needs to hold the buffer: buffer: array[0..k-1] of items;

needs two condition variables: notfull: csignal(notFull) when buffer becomes not full notempty: csignal(notEmpty) when the becomes not empty

needs buffer pointers and counts: nextin: points to next slot to be filled nextout: points to next item to be taken count: holds the number of items in buffer

No race condition: monitor ensures mutual exclusion!

Monitor for the bounded P/C problemMonitor boundedbuffer{ items buffer[k]; int nextin=0, nextout=0, count=0; condition notfull, notempty; //buffer statevoid append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ % k; count++; csignal(notempty);}

item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ % k; count--; csignal(notfull); return v;}}

Monitor Monitors result in simpler, easier to read code, and

provide synchronization via condition variables They are not, however, able to do things

semaphores cannot: they can be implemented with semaphores, and vice versa

Monitor exampleMonitor boundedbuffer{buffer[ | | | ]nextin=0 nextout=0 count=0 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Running process

Monitor exampleMonitor boundedbuffer{buffer[ 1 | | | ];nextin=0 nextout=0 count=0 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | | | ]nextin=1 nextout=0 count=0 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | | | ]nextin=1 nextout=0 count=1 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | | | ]nextin=1 nextout=0 count=1 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | | | ]nextin=1 nextout=0 count=1 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | | ]nextin=1 nextout=0 count=1 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | | ]nextin=2 nextout=0 count=1 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | | ]nextin=2 nextout=0 count=2 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | | ]nextin=2 nextout=0 count=2 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | | ]nextin=2 nextout=0 count=2 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | | ]nextin=2 nextout=0 count=2 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | | ]nextin=2 nextout=1 count=2 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | | ]nextin=2 nextout=1 count=1 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | | ]nextin=2 nextout=1 count=1 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | | ]nextin=2 nextout=1 count=1 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | 3 | ]nextin=2 nextout=1 count=1 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | 3 | ]nextin=3 nextout=1 count=1 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | 3 | ]nextin=3 nextout=1 count=2 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | 3 | ]nextin=3 nextout=1 count=2 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | 3 | ]nextin=3 nextout=1 count=2 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | 3 | 4 ]nextin=3 nextout=1 count=2 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | 3 | 4 ]nextin=0 nextout=1 count=2 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | 3 | 4 ]nextin=0 nextout=1 count=3 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | 3 | 4 ]nextin=0 nextout=1 count=3 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 1 | 2 | 3 | 4 ]nextin=0 nextout=1 count=3 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 2 | 3 | 4 ]nextin=0 nextout=1 count=3 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 2 | 3 | 4 ]nextin=1 nextout=1 count=3 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 2 | 3 | 4 ]nextin=1 nextout=1 count=4 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 2 | 3 | 4 ]nextin=1 nextout=1 count=4 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 2 | 3 | 4 ]nextin=1 nextout=1 count=4 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 2 | 3 | 4 ]nextin=1 nextout=1 count=4 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 2 | 3 | 4 ]nextin=1 nextout=2 count=4 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 2 | 3 | 4 ]nextin=1 nextout=2 count=3 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 2 | 3 | 4 ]nextin=1 nextout=2 count=3 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 2 | 3 | 4 ]nextin=1 nextout=2 count=3 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 6 | 3 | 4 ]nextin=1 nextout=2 count=3 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 6 | 3 | 4 ]nextin=2 nextout=2 count=3 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 6 | 3 | 4 ]nextin=2 nextout=2 count=4 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 6 | 3 | 4 ]nextin=2 nextout=2 count=4 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 6 | 3 | 4 ]nextin=2 nextout=2 count=4 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 6 | 3 | 4 ]nextin=2 nextout=2 count=4 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 6 | 3 | 4 ]nextin=2 nextout=2 count=4 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 6 | 3 | 4 ]nextin=2 nextout=2 count=4 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 6 | 3 | 4 ]nextin=2 nextout=2 count=4 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 6 | 3 | 4 ]nextin=2 nextout=2 count=4 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 6 | 3 | 4 ]nextin=2 nextout=3 count=4 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 6 | 3 | 4 ]nextin=2 nextout=3 count=3 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Monitor exampleMonitor boundedbuffer{buffer[ 5 | 6 | 3 | 4 ]nextin=2 nextout=3 count=3 k=4

void append(item v){ if (count==k) cwait(notfull); buffer[nextin]= v; nextin++ mod k; count++; csignal(notempty);}item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ mod k; count--; csignal(notfull); return v;}}

notfullnotempty

Who goes first?

Who goes first? When a condition variable with a nonempty queue

is signaled, which process executes in the monitor? The signaled process: Hoare semantics The signaling process: Mesa (Brinch-Hansen) semantics

If the signaled process does not immediately execute in the monitor, it is possible that the signaled condition could be come invalid Using Mesa semantics the signaled process must recheck

the condition, waiting on the associated condition variable if it is false

Hoare vs. Mesa semantics: usageMonitor boundedbuffer{ items buffer[k-1]; int nextin=0, nextout=0; int count=0; condition notfull, notempty; void append(item v){ if (count==k)

cwait(notfull); buffer[nextin]= v; nextin++ % k; count++; csignal(notempty);}

item take(){item v; if (count==0) cwait(notempty); v= buffer[nextout]; nextout++ % k; count--; csignal(notfull); return v;}}

Monitor boundedbuffer{ items buffer[k-1]; int nextin=0, nextout=0; int count=0; condition notfull, notempty; void append(item v){ while(count==k) cwait(notfull); buffer[nextin]= v; nextin++ % k; count++; csignal(notempty);}

item take(){item v; while(count==0) cwait(notempty); v= buffer[nextout]; nextout++ % k; count--; csignal(notfull); return v;}}

Message passing Processes (and threads) can communicate without

synchronization Shared memory

A message passing paradigm for communication requires synchronization Send (destination, message)

What if the source has not yet called receive? Receive(source, message)

What if no message was sent?

Blocking vs. non-blocking After calling send, if no matching receive

The sender could block until the message is received The sender could continue

After calling receive, if no matching send The caller could block until a message is sent

Test function (Are there pending messages?) Time out (Wait until message or X seconds have passed)

The caller could continue, with receive returning failure

Direct vs. Indirect If the source/destination arguments are process

identifiers, the system uses direct messaging If the source/destination arguments are mailboxes,

possibly shared by many processes, the system uses indirect messaging Many senders, one receiver (client server) Many receivers, many senders (topic subscription) Who owns the mailbox?

Message passing as synchronization Semaphores or monitors may be used to implement

message passing A message passing system can be used to

implement monitors or semaphores Message passing has the same synchronization

power as semaphores and monitors

top related