1
CS 333Introduction to Operating Systems
Class 6 – Monitors and Message Passing
Jonathan WalpoleComputer Science
Portland State University
2
Monitors
It is difficult to produce correct programs using semaphores
correct ordering of up and down operations is tricky!
Can we get the compiler to generate the correct semaphore code for us?
what are suitable higher level abstractions for synchronization?
3
Monitors
Collect related shared objects together in a monitor
Characteristics Local data variables are accessible only via the
monitor’s procedures Processes enter the monitor by invoking one of its
procedures Only one process may execute within the monitor at
a given time
Condition variables (cv) Wait(cv) – block on condition Signal(cv) – wake up process waiting on cv
4
Monitor structures
initializationcode
monitor operations
y
x
shared data
condition queuesmonitor entry queue
5
Monitor example for mutual exclusion
process Producerbegin loop <produce char “c”> BoundedBuffer.deposit(c) end loopend Producer
process Consumerbegin loop BoundedBuffer.remove(c) <consume char “c”> end loopend Consumer
monitor: BoundedBuffervar buffer : ...; nextIn, nextOut :... ;
entry deposit(c: char) begin ... end
entry remove(var c: char) begin ... end
end BoundedBuffer
6
Condition variables
Condition variables allow processes to synchronize based on some state of the monitor variables
For example: Buffer_full in the producer/consumer
Operations wait(cv) and signal(cv) allow synchronization within a monitor
Only one processor active at one time what happens on a signal from A to B?
• A waits for B to leave monitor, or waits for another condition
• B waits for A to leave monitor, or waits for another condition
… and what happens on wait?
7
Monitor example
monitor : BoundedBuffervar buffer : array[0..n-1] of char nextIn,nextOut : 0..n-1 := 0 fullCount : 0..n := 0 notEmpty, notFull : condition
entry deposit(c:char) entry remove(var c: char) begin begin if (fullCount = n) then if (fullCount = n) then wait(notFull) wait(notEmpty) end if end if
buffer[nextIn] := c c := buffer[nextOut] nextIn := nextIn+1 mod n nextOut := nextOut+1 mod n fullCount := fullCount+1 fullCount := fullCount-1 signal(notEmpty) signal(notFull) end deposit end removeend BoundedBuffer
8
Condition synchronization semantics
Signaling and signaled processes can not both run
What if signaling process continues to run and signals other condition variable?
What if signaled process continues to run and signals other condition variables?
What order should processes run? How do you avoid deadlock?
9
Condition synchronization semantics
Hoare Semantics On signal, allow signalled process to run; upon
its exit from the monitor, signaller process continues
• Stonger guarantees• Easier to prove correctness
Mesa Semantics (Xerox PARC) Signal is merely a “hint”
• Requires process to check that condition is ok to continue upon receipt of signal
10
Producer consumer with message passing
11
Barriers
Use of a barrier processes approaching a barrier all processes but one blocked at barrier last process arrives, all are let through
12
Summary
Process synchronization topics Semaphores IPC problems Monitors
Reading 2.3-2.4
13
Monitors
It is difficult to produce correct programs using semaphores
correct ordering of up and down is tricky! avoiding deadlock is tricky! boundary conditions are tricky!
Can we get the compiler to generate the correct semaphore code for us?
what are suitable higher level abstractions for synchronization?
14
Monitors
Collect related shared objects together in a monitor
Encapsulation and mutual exclusion Local data variables are accessible only via the
monitor’s procedures Processes enter the monitor by invoking one of its
procedures Only one process may execute within the monitor at a
given time
Condition variables (cv) Wait(cv) – process blocked (queued) until condition
holds Signal(cv) – signals the condition and unblocks
(dequeues) a process
15
Monitor structures
initializationcode
monitor operations
y
x
shared data
condition queuesmonitor entry queue
16
Monitor example for mutual exclusion
process Producerbegin loop <produce char “c”> BoundedBuffer.deposit(c) end loopend Producer
process Consumerbegin loop BoundedBuffer.remove(c) <consume char “c”> end loopend Consumer
monitor: BoundedBuffervar buffer : ...; nextIn, nextOut :... ;
entry deposit(c: char) begin ... end
entry remove(var c: char) begin ... end
end BoundedBuffer
17
Monitor example with condition variables
monitor : BoundedBuffervar buffer : array[0..n-1] of char nextIn,nextOut : 0..n-1 := 0 fullCount : 0..n := 0 notEmpty, notFull : condition
entry deposit(c:char) entry remove(var c: char) begin begin if (fullCount = n) then if (fullCount = n) then wait(notFull) wait(notEmpty) end if end if
buffer[nextIn] := c c := buffer[nextOut] nextIn := nextIn+1 mod n nextOut := nextOut+1 mod n fullCount := fullCount+1 fullCount := fullCount-1 signal(notEmpty) signal(notFull) end deposit end removeend BoundedBuffer
18
Monitor design choices
Condition variables introduce a problem for mutual exclusion
only one process active in the monitor at a time, so what to do when a process is unblocked on signal?
must not block holding the mutex, so what to do when a process blocks on wait?
Should signals be stored/remembered? signals are not stored if signal occurs before wait, signal is lost!
Should condition variables count?
19
Monitor design choices
Choices when A signals a condition that unblocks B A waits for B to exit the monitor or blocks again B waits for A to exit the monitor or block Signal causes A to immediately exit the monitor or block
(on what condition?)
Choices when A signals a condition that unblocks B & C
B is unblocked, but C remains blocked C is unblocked, but B remains blocked
Choices when A calls wait and blocks a new external process is allowed to enter but which one?
20
Common monitor semantics
Hoare semantics On signal, allow signaled process to run; upon
its exit from the monitor, signaler process continues
Brinch Hansen semantics signaler must immediately exit following signal
21
Message Passing
Interprocess communication via shared memory across machine boundaries
Message passing can be used locally or remotely for synchronization or general communication
processes use send and receive primitives receive can block like wait send unblocks a process blocked on receive (like
signal unblocking a waiting process)
22
Producer consumer with message passing
23
Design Choices for Message Passing
Mailboxes system maintains a buffer of sent, but not yet
received, messages Rendezvous
sender and receiver must be active at the same time
receive must be blocked before send occurs kernel does no buffering when does the send return?
24
Barriers
Use of a barrier processes approaching a barrier all processes but one blocked at barrier last process arrives, all are let through
25
Monitors (1)
Example of a monitor
26
Monitors (2)
Outline of producer-consumer problem with monitors only one monitor procedure active at one time buffer has N slots
27
Monitors (3)
Solution to producer-consumer problem in Java (part 1)
28
Monitors (4)
Solution to producer-consumer problem in Java (part 2)
29
Semantics of monitors
What is the strongest statement we can make about the state of the monitor after a waiter wakes up?
entry deposit(c:char) entry remove(var c: char) begin begin if (fullCount = n) then : : wait(notFull) c := buffer[nextOut] fullCount := fullCount-1 end if signal(notFull) : : end deposit end remove
30
Synchronization problems with Mesa P1 P2 P3
/* fullCount=n */
if (fullCount==n)
wait(notFull);
remove()
...
fullCount--;
signal(notFull);
...
/* exit monitor */
/* fullCount=n-1*/
deposit()
...
fullCount++;
...
/* exit monitor */
...
fullCount++;
31
Mesa semantics
monitor : BoundedBuffervar buffer : array[0..n-1] of char nextIn,nextOut : 0..n-1 := 0 fullCount : 0..n := 0 notEmpty, notFull : condition
entry deposit(c:char) entry remove(var c: char) begin begin while (fullCount = n) then while (fullCount = n) then wait(notFull) wait(notEmpty) end while end while
buffer[nextIn] := c c := buffer[nextOut] nextIn := nextIn+1 mod n nextOut := nextOut+1 mod n fullCount := fullCount+1 fullCount := fullCount-1 signal(notEmpty) signal(notFull) end deposit end removeend BoundedBuffer
32
Introduction to Operating Systems
Chapter 2 (partial)
Monitors, Reentrant Code,
Message Passing, and Barriers
33
Introduction
It is difficult to produce correct programs
using locks and semaphores!!!
Correct ordering of Up and Down operations is tricky!
Desirable: Language / compiler support for IPC
What are suitable high-level abstractions for synchronization?
34
Monitors
Collect related, shared objects together in a “monitor”
Characteristics: • Local data variables are accessible only via
the monitor’s procedures/methods • Threads enter the monitor by invoking one of
its procedures/methods • Only one thread may execute within the
monitor at a given time
“Condition Variables” (cv) Wait(cv) – block on condition Signal(cv) – wake up one thread waiting on cv
35
Monitor structures
initializationcode
“entry” methods
y
x
shared data
condition variablesmonitor entry queue
local methods
36
Monitor structures
initializationcode
“entry” methods
y
x
shared data
condition variablesmonitor entry queue
List of threadswaiting to
enter the monitor
Can be called fromoutside the monitor.Only one active at
any moment.
Local to monitor(Each has an associatedlist of waiting threads)
local methods
37
Example: The “Bounded-Buffer” Monitor
Producer Thread: while true -- Produce char “c” BoundedBuffer.deposit(c) endWhile
Consumer Thread: while true c = BoundedBuffer.remove() -- Consume char “c” endWhile
monitor BoundedBuffer var buffer: ... nextIn, nextOut :...
entry deposit(c: char) begin ... end
entry remove() begin ... return c end
endMonitor
38
The “BoundedBuffer” Monitor
monitor BoundedBuffer var buffer: array[n] of char nextIn, nextOut: int = 0 cntFull: int = 0 notEmpty: Condition notFull: Condition
entry deposit(c: char) ...
entry remove() ...
endMonitor
AN-10
B C D
cntFull=4
nextInnextOut
39
Code for the “deposit” entry routine
monitor BoundedBuffer var buffer: array[n] of char nextIn, nextOut: int = 0 cntFull: int = 0 notEmpty: Condition notFull: Condition
entry deposit(c: char) if cntFull == N notFull.Wait() endIf buffer[nextIn] = c nextIn = (nextIn+1) mod N cntFull = cntFull + 1 notEmpty.Signal() endEntry
entry remove() ...
endMonitor
AN-10
B C D
cntFull=4
nextInnextOut
40
Code for the “remove” entry routine
monitor BoundedBuffer var buffer: array[n] of char nextIn, nextOut: int = 0 cntFull: int = 0 notEmpty: Condition notFull: Condition
entry deposit(c: char) ...
entry remove() if cntFull == 0 notEmpty.Wait() endIf c = buffer[nextOut] nextOut = (nextOut+1) mod N cntFull = cntFull - 1 notFull.Signal() endEntry
endMonitor
AN-10
B C D
nextInnextOut
cntFull=4
41
Condition Variables
“Condition variables allow processes to synchronize based on some state of the monitor variables.”
Examples from producer/consumer: “Buffer-Full” condition “Buffer-Empty” condition
Operations Wait(cv) and Signal(cv) allow synchronization within the monitor
When a producer thread adds an element...
A consumer may be sleeping Need to wake the consumer... Signal
42
Condition synchronization semantics
“Only one thread can be executing in the monitor
at any one time.”
Scenario: Thread A is executing in the monitor. Thread A does a Signal, waking up
thread B. What happens now?• Signaling and signaled threads can not
both run!
43
Condition synchronization semantics
• Option 1: Hoare Semantics
• What happens when a Signal is performed?• The signaling thread (A) is suspended.• The signaled thread (B) wakes up and
runs immediately.• B can assume the condition is now
true/satisfied•
• • Stronger guarantees• • Easier to prove correctness
• When B leaves monitor, then A can run.• After B leaves monitor...• A might resume execution
immediately• ... or maybe another thread (C) will
slip in!
44
Condition synchronization semantics
• Option 2: MESA Semantics (Xerox PARC)
• What happens when a Signal is performed?• • The signaling thread (A) continues.• • The signaled thread (B) waits.• When A leaves monitor, then B runs.• Issue: What happens when B waits?• When A leaves the monitor,• can some other thread (C) slip in
first?• (Can some other thread (C) run• after A signals, but before B runs?)• • A signal is more like a hint.• • Requires B to recheck the state of the
monitor variables• to see if it can proceed or must wait some
more.
45
Code for the “deposit” entry routine
monitor BoundedBuffer var buffer: array[n] of char nextIn, nextOut: int = 0 cntFull: int = 0 notEmpty: Condition notFull: Condition
entry deposit(c: char) if cntFull == N notFull.Wait() endIf buffer[nextIn] = c nextIn = (nextIn+1) mod N cntFull = cntFull + 1 notEmpty.Signal() endEntry
entry remove() ...
endMonitor
Hoare Semantics
46
Code for the “deposit” entry routine
monitor BoundedBuffer var buffer: array[n] of char nextIn, nextOut: int = 0 cntFull: int = 0 notEmpty: Condition notFull: Condition
entry deposit(c: char) while cntFull == N notFull.Wait() endWhile buffer[nextIn] = c nextIn = (nextIn+1) mod N cntFull = cntFull + 1 notEmpty.Signal() endEntry
entry remove() ...
endMonitor
MESA Semantics
47
Code for the “remove” entry routine
monitor BoundedBuffer var buffer: array[n] of char nextIn, nextOut: int = 0 cntFull: int = 0 notEmpty: Condition notFull: Condition
entry deposit(c: char) ...
entry remove() if cntFull == 0 notEmpty.Wait() endIf c = buffer[nextOut] nextOut = (nextOut+1) mod N cntFull = cntFull - 1 notFull.Signal() endEntry
endMonitor
Hoare Semantics
48
Code for the “remove” entry routine
monitor BoundedBuffer var buffer: array[n] of char nextIn, nextOut: int = 0 cntFull: int = 0 notEmpty: Condition notFull: Condition
entry deposit(c: char) ...
entry remove() while cntFull == 0 notEmpty.Wait() endWhile c = buffer[nextOut] nextOut = (nextOut+1) mod N cntFull = cntFull - 1 notFull.Signal() endEntry
endMonitor
MESA Semantics
49
“Hoare Semantics”
• What happens when a Signal is performed?• The signaling thread (A) is suspended.• The signaled thread (B) wakes up and runs
immediately.• B can assume the condition is now
true/satisfied• From the original Hoare Paper:• “No other thread can intervene [and enter the
monitor] between the signal and the continuation of exactly one waiting thread.”
• “If more than one thread is waiting on a condition, we postulate that the signal operation will reactivate the longest waiting thread. This gives a simple neutral queuing discipline which ensures that every waiting thread will eventually get its turn.”
50
Implementing Hoare Semantics
Implementation? Thread A holds the monitor lock. Thread A issues a Signal. Thread B will be moved back to the ready
queue. Thread A must be suspended... Possession of the monitor lock must be passed from A to B. When B finishes and gets ready to return... The lock can be released. Thread A must re-aquire the lock. Perhaps A is blocked, waiting to re-aquire
the lock.
51
Implementing Hoare Semantics
Problem: “Possession of the monitor lock must be
passed from A to B.” Each mutex remembers which thread holds
it. My version of Mutex: Any attempt by thread B to release the
monitor lock will cause an error message.
Your Solution: Modify Mutex to eliminate the check?
52
Implementing Hoare Semantics
Recommendation: Do not modify the methods that I
am supplying. (Future code I release will use
them) Create new classes: MonitorLock -- similar to Mutex HoareCondition -- similar to
Condition
53
Implementing Hoare Semantics
Scenario: Thread B does a Wait. Thread A executes a Signal. Thread B wakes up, executes, and returns. Last thing B does: Unlock the monitor lock.
Problem: What happens next? Thread A is waiting for B to finish. It is trying to reaquire the monitor lock. What about thread C? Also trying to acquire lock, and waiting
longer? Hoare: “A must get the lock after B.” C must continue to wait.
54
Implementing Hoare Semantics
Things are getting complex. Simply ending monitor entry methods with monLock.Unlock() will no longer work.
Implementation Ideas: Need a special thing called a “MonitorLock”. Consider a thread like A to be “urgent”. Thread C is not “urgent”. Consider 2 wait lists associated with each MonitorLock • UrgentlyWaitingThreads • NonurgentlyWaitingThreads Want to wake up urgent threads first, if any.
55
Brinch-Hansen Semantics
Hoare Semantics On signal, allow signaled process to run. Upon its exit from the monitor, signaler process
continues.
Brinch-Hansen Semantics Signaler must immediately exit following any invocation of signal. (Implementation of is easier.)
56
Reentrant Code
A function/method is said to be “reentrant” if...
“A function that has been invoked may be invoked again
before the first invocation has returned, and will still work correctly.”
Recursive routines are reentrant.
In the context of multi-programming... A reentrant function can be executed
simultaneously by more than one thread, with no ill effects.
57
Reentrant Code
Consider this function...
var count: int = 0
function GetUnique () returns int count = count + 1 return count endFunction
What if it is executed by different threads?
58
Reentrant Code
Consider this function...
var count: int = 0
function GetUnique () returns int count = count + 1 return count endFunction
What if it is executed by different threads? The results may be incorrect! This routine is not reentrant!
59
Reentrant Code
When is code “reentrant”?
Assumption: A multi-threaded program Some variables are “local” -- to the function/method/routine “global” -- sometimes called “static”
Access to local variables? A new stack frame is created for each invocation.
Access to global variables? Must use synchronization!
60
Making this Function Reentrant
var count: int = 0 myLock: Mutex
function GetUnique () returns int var i: int myLock.Lock() count = count + 1 i = count myLock.Unlock() return i endFunction
61
Message Passing
Interprocess Communication • via shared memory • across machine boundaries
Message passing can be used locally or remotely Can be used for... synchronization, or general communication
Processes use Send and Receive primitives • Receive can block (like Waiting on a Semaphore) • Send unblocks a process blocked on Receive (Just as a Signal unblocks a Waiting process)
62
Producer-Consumer with Message Passing
Idea: After producing, the producer sends the data to consumer in a message. The system buffers messages. The producer can out-run the
consumer. The messages will be kept in order. After consuming the data, the consumer sends back an “empty”
message. A fixed number of messages (N=100) The messages circulate back and forth.
63
Producer-Consumer with Message Passing
thread consumer var c, em: char while true Receive(producer, &c) -- Wait for a char Send(producer, &em) -- Send empty message back // Consume char... endWhileend
const N = 100 -- Size of message buffervar em: charfor i = 1 to N -- Get things started by Send (producer, &em) -- sending N empty messagesendFor
64
Producer-Consumer with Message Passing
thread producer var c, em: char while true // Produce char c... Receive(consumer, &em) -- Wait for an empty msg Send(consumer, &c) -- Send c to consumer endWhileend
65
Design Choices for Message Passing Option 1: “Mailboxes”
System maintains a buffer of sent, but not yet received, messages.
Must specify the size of the mailbox ahead of time.
Sender will be blocked if buffer is full. Receiver will be blocked if the buffer is empty.
66
Design Choices for Message Passing Option 1: “Mailboxes”
System maintains a buffer of sent, but not yet received, messages.
Must specify the size of the mailbox ahead of time. Sender will be blocked if buffer is full. Receiver will be blocked if the buffer is empty.
Option 2: The kernel does no buffering If Send happens first, the sending thread
blocks. If Receiver happens first, the receiving
thread blocks. “Rendezvous” Both threads are ready for the transfer. The data is copied / transmitted
• Both threads are then allowed to proceed.
67
Barriers
• Processes approaching a barrier • All processes but one blocked at barrier • Last process arrives; all are let through
68
Monitors: An Operating System Structuring Concept
Paper by: C. A. R. Hoare
Presented by: Sabrina Brick
69
Why monitors?
Concurrency has always been an OS issue Resource allocation is necessary among
competing processes Timer interrupts
Existing synchronization mechanisms (semaphores, locks) are subject to hard-to-find, subtle bugs.
70
What is a monitor?
A collection of data and procedures Mutual exclusion
allows controlled acquisition and release of critical resources
single anonymous lock automatically acquired and released at entry and exit
Data encapsulation monitor procedures are “entry points” for
accessing data
71
Monitors: a language construct
Monitors are a programming language construct
anonymous lock issues handled by compiler and OS
detection of invalid accesses to critical sections happens at compile time
process of detection can be automated by compiler by scanning the text of the program
72
An Abstract Monitor
name: monitor …local declarations …initialize local data proc1 (…parameters)
…statement list proc2 (…parameters)
…statement list proc3 (…parameters) …statement list
73
Rules to Follow with Monitors
Any process can call a monitor procedure at any time
But only one process can be inside a monitor at any time (mutual exclusion)
No process can directly access a monitor’s local variables (data encapsulation)
A monitor may only access its local variables
Why? Race conditions could occur! “Chaos will ensue”!
74
Enforcing the Rules
“wait” operation current process is put to sleep
“signal” operation wakes up a sleeping process
condition variables May have different reasons for “waiting” or
“signaling” Processes waiting on a particular condition enter
its queue
75
Sabrina’s Car: a running example
car: monitor occupied: Boolean; occupied := false; nonOccupied: condition;
procedure enterCar()if occupied then nonOccupied.wait;
occupied = true;
procedure exitCar() occupied = false; nonOccupied.signal;
What possible problem exists?
monitor declaration
local variables / initializations
procedure
procedure
76
The Possible Problem
As discussed in Birrell’s paper (last class): First process:
• Completes it’s work with critical section• Signals a process waiting on “nonOccupied”• Starts to release the monitor when…
Second process:• Is awakened by first process• Tries an “entry point” into the monitor• First process isn’t finished releasing it so it blocks
again! This can’t happen with Hoare’s approach:
Signal must be the last operation in a monitor. Signal and monitor exit are a combined operation.
77
Multiple Conditions
Sometimes it is necessary to be able to wait on multiple things
Can be implemented with multiple conditions
Example: 2 reasons to enter car drive (empties tank) fill up car
Two reasons to wait: Going to gas station but tank is already full Going to drive but tank is (almost) empty
78
Sabrina’s Car: a running example
car: monitor emptyTank, fullTank: condition; tank: stack; tank := stack of 10 gallons; //10 gallon tank //filled in increments of a gallon procedure driveCar()
if tank.isAlmostEmpty then fullTank.wait; tank.pop(); //consume gas in increments of a
gallonemptyTank.signal;
procedure fillCar() if tank.isFull then emptyTank.wait; tank.push(gallons.pop); //assume gas station “stack” has
infinite supply fullTank.signal;
79
Condition Queue
Might want to check if any process is waiting on a condition The “condition queue” returns true if a process is
waiting on a condition Example: filling the tank only if someone
is waiting to drive the car.
80
Sabrina’s Car: a running example
car: monitor emtpyTank, fullTank: condition; tank: stack; tank := stack of 10 gallons; //10 gallon tank //filled in increments of a gallon procedure driveCar()
if tank.isAlmostEmpty then fullTank.wait; tank.pop(); //consume gas in increments of a
gallonemptyTank.signal;
procedure fillCar() if tank.isFull then emptyTank.wait; if fullTank.queue //returns true if a process is waiting on
fullTank tank.push(gallons.pop); //assume gas station “stack” has
infinite supply fullTank.signal;
81
Priority: Scheduled Waits
A waiting process is given a number The process with the lowest number gets
woken up first Example: People who want to drive my
car are prioritized: Highest: Me! Medium: Family Lowest: Friends/Others
82
Sabrina’s Car: a running example
car: monitor emtpyTank, fullTank: condition; tank: stack; tank := stack of 10 gallons; //10 gallon tank //filled in increments of a gallon procedure driveCar(p: person)
if tank.isAlmostEmpty then if p.isSabrina then fullTank.wait(1); if p.isFamily then fullTank.wait(2); if p.isFriendorOther then fullTank.wait(3);
tank.pop(); //consume gas in increments of a gallonemptyTank.signal;
procedure fillCar() if tank.isFull then emptyTank.wait; if fullTank.queue tank.push(gallons.pop); //assume gas station has infinite
supply fullTank.signal;
83
Other issues
Power of Monitors Monitor->semaphore and vice versa
Proof rules I {b.wait} I&B I&B {b.signal} I
I : the invariantB : the condition that a process waiting on b wants
to be true before its woken upb : the condition variable
84
Lots of Great Examples
OS Examples: Bounded Buffer Alarm clock Disk head scheduler Reader/writer Buffer Allocation
85
Monitors and Granularity
Monitors are designed for course-grained locking Example: locking an entire data structure rather
than its individual components. Is this an appropriate solution for all
cases? Why or why not? What problems arise when the
granularity is too coarse? What about the opposite case?
86
Monitors: implementation issues
Disabling Interrupts
car: monitor occupied: Boolean; occupied := false; nonOccupied: condition;
procedure enterCar()//disableInterrupts();if occupied then nonOccupied.wait;
occupied = true;//enableInterrupts();
procedure exitCar()//disableInterrupts();
occupied = false; nonOccupied.signal;
//enableInterrupts();
“Yellow code” inserted into binary by compiler
Which is the better approach? Why?
Using a lock
car: monitor occupied: Boolean; occupied := false; nonOccupied: condition; //lock1: lock;
procedure enterCar()//lock1.acquire();if occupied then nonOccupied.wait;
occupied = true;//lock1.release();
procedure exitCar()//lock1.acquire();
occupied = false; nonOccupied.signal;
//lock1.release();
//lock1.acquire()//disableInterrupts();//lockVar = 1;//enableInterrupts();
87
What problems do monitors solve?
Mutual exclusion Encapsulation of data Compiler can automatically scan program text for
some types of synchronization bugs Synchronization of shared data access simplified
vs. semaphores and locks Good for problems that require course granularity Invariants are guaranteed after waits
Theoretically, a process that waits on a condition doesn’t have to retest the condition when it is awakened.
88
What remains problematic?
No way to check dynamically allocated shared data
Signals are as error prone as with other synchronization mechanisms
Deadlock can still happen in monitor code Programmer can still screw up Monitors are available in very few
languages
89
Conclusions
Monitors are a synchronization mechanism
A higher level, easier to use abstraction, better encapsulation than semaphores, etc.
Monitors still suffer from various problems
Let’s take a look at working model that addresses some of those issues! (Suzanne’s presentation)
90
References
Jon Walpole “Monitors: An Operating Systems
Structuring Concept” Hoare. Modern Operating Systems, Second
Edition. Tannenbaum, pp. 115-119. Emerson Murphy-Hill presentation from
CS533, Winter 2005 http://en.wikipedia.org/wiki/
C._A._R._Hoare
91
Experience with Processes and Monitors in Mesa
B. W. LampsonXerox Palo Alto Research Center
D. D. RedellXerox Business Systems
Communications of the ACM v.23, n.2, Feb.1980, pp. 105-117
92
Design Goals
Local concurrent programming
Global resource sharing Replacing interrupts
93
Concurrent Programming using
Monitors in Mesa
Interactions with process creation and destruction
How to define WAIT Priority scheduling Semantics of nested monitor calls Handling timeouts, aborts, and other
exceptions Monitoring large numbers of small
objects
94
Signaling in MonitorsJ. H. Howard2nd Intl. Conf. of Software Engr, Oct.1976
SU signal & urgent wait Hoare’74 signaler to “urgent” queue & resumes after signaled process runs
SR signal & return Brinch Hansen’75 return from monitor immediately after signaling Concurrent PASCAL
SW signal & wait Howard’76 signaled immediate access signaler to monitor’s entry queue
SC signal & continue signaler’s view of monitor state not corrupted requires explicit recording of signals pending
Problems SU & SW: signalers might wait & restart unnecessarily
SR simplest but may be inadequate & SC complex
95
Excerpt of Tanenbaum’s Example of Hoare Semantic
Monitor ProducerConsumer condition full, empty; integer count; procedure insert (item; integer);
begin Modification for Mesa Semantic if count = N then wait (full); while not count = N do wait (full) insert_item (item); count := count + 1; if count = 1 then signal (empty); end;
Signaling thread suspends on urgent
Signaled thread wakes & runs immediately
First thread regains possession of monitor when second completes
Signaling thread continues
Signaled thread rechecks condition because order not guaranteed
Avoid context switch
Hoare semantic Mesa semantic
96
StorageAllocator: MONITOR = BEGIN availableStorage: INTEGER: moreAvailable: CONDITION:
Allocate: ENTRY PROCEDURE [size: INTEGER RETURNS [p: POINTER] = BEGIN UNTIL availableStorage >= size DO WAIT moreAvailable ENDLOOP; p <- <remove chunk of size words & update availableStorage> END;
Free: ENTRY PROCEDURE [p: POINTER, Size: INTEGER] = BEGIN <put back chunk of size words & update availableStorage>; NOTIFY moreAvailable END;
Expand:PUBLIC PROCEDURE [pOld: POINTER, size: INTEGER] RETURNS [pNew: POINTER] = BEGIN pNew <- Allocate[size]; <copy contents from old block to new block>; Free[pOld] END;END.
97
Mutual exclusion
Asynchronous processes must not Allocate and Free simultaneously → use entry procedures
Monitor lock not needed during copy in Expand → use external procedure
Structure the monitor computations only when lock is already held → use internal procedure
98
Define WAIT
If caller waits in entry procedure, it releases the lock
If wait in internal procedure, the lock is released
If monitor calls procedure outside the monitor, the lock is not released
99
Invariant
Always true, except when process is executing in the monitor
On entry, invariant assumed to hold Invariant established before control leaves
monitor Monitor procedure must establish invariant
before WAIT Consider exception handler called from
entry procedure
100
Causes ofPair-wise Deadlock
2 processes WAIT in a single monitor
Cyclic calling between 2 monitors → impose a partial order
Two level data abstraction
101
Two level data abstractionExample: Monitor M calls N and waits for C requires process to enter N through M to set C → DEADLOCKDivide M into monitor M’ and interface O to call N
102
Monitored Objects
Collection of shared data objects Multiple instances of monitor Duplication of program linking and
code swapping Monitored record To access a file, pass as parameter
to effectively create a separate monitor for each object (read-only, no aliasing)
103
Abandon computation
UNWIND exception to allow clean-up by any active procedure
If procedure to be abandoned is an entry procedure, must restore invariant and release lock
Programmer provides handler or experiences deadlock
Compare to Java exception handling
104
Condition variables Process establishes a condition for which
another process waits NOTIFY is a hint that waiting process will
resume and reacquire the monitor lock No guarantee about another process
interceding Waiter must reevaluate when it resumes
Mesa WHILE NOT <OK to proceed> DO WAIT c ENDLOOPHoare IF NOT <OK to proceed> THEN WAIT c
105
Verification rules
Simpler and more localized Invariant established before return from
entry procedure or a WAIT Invariant assumed at start of entry
procedure and just after a WAIT Waiter explicitly tests Notify condition may be more general
(low cost to wake a process)
106
NOTIFY alternatives
Timeout with interval Abort Broadcast I/O device communication
device cannot wait on monitor lock notify condition variable to wake
interrupt handler
107
Priorities
Ordering implied by assignment of priorities can be subverted by monitors
Associate with each monitor the priority of the highest priority process that ever enters the monitor (Modula disables interrupts, but this fails with page fault.)
108
Example of subverted priority
Process P1 enters monitor M, P2 preempts, P3 preemptsP3 tries to enter monitor and waits for lock
P1
P2
P3
M
enter
preempt P1
preempt P2
P2 runs again, effectively keeps P3 from running, undermining the priorities.
109
Processor
Process states (pcbs) in queues sorted by priority Ready queue
Monitor lock queue Condition variable queue
Fault queue
Queue cell
process state process state process state
head tail
----
110
Implementation
Compiler – flags errors WAIT in external procedure direct call from external to internal
procedure Runtime – process creation and
destruction Machine – process scheduling
and monitor entry/exit
111
Performance
112
Validation of Mesa Semantic
Operating system Interrupt handling lack of mutual exclusion Interaction of concurrency and exception
Database Single monitor and single condition variable Array of representative states
Network communication Router monitor Network driver monitor
113
Closing comparison
114
Implementation
115
Questions
Monitor – low level mechanism Starvation addressed by high level scheduling Simpler & localized verification rules Signaled process checks specific condition More general condition for notify
• Should signal be the last operation of aShould signal be the last operation of a monitor procedure?monitor procedure?• How is exception handling addressed?How is exception handling addressed?