0% found this document useful (0 votes)
322 views

COS 318: Operating Systems Semaphores, Monitors and Condition Variables

This document summarizes semaphores, monitors, and condition variables for operating systems. It discusses how semaphores can be used to implement bounded buffers and the motivation for using monitors and condition variables instead. It then explains how monitors hide mutual exclusion and how condition variables can be used within monitors. Finally, it compares Mesa-style monitors, which allow signaling threads to continue execution, to Hoare-style monitors.

Uploaded by

xxnations
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
322 views

COS 318: Operating Systems Semaphores, Monitors and Condition Variables

This document summarizes semaphores, monitors, and condition variables for operating systems. It discusses how semaphores can be used to implement bounded buffers and the motivation for using monitors and condition variables instead. It then explains how monitors hide mutual exclusion and how condition variables can be used within monitors. Finally, it compares Mesa-style monitors, which allow signaling threads to continue execution, to Hoare-style monitors.

Uploaded by

xxnations
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

Today’s Topics

‹ Semaphores
COS 318: Operating Systems ‹ Monitors
‹ Mesa-style monitors
Semaphores, Monitors and ‹ Programming idiom
Condition Variables

Kai Li
Computer Science Department
Princeton University

(http://www.cs.princeton.edu/courses/cos318/)

Semaphores (Dijkstra, 1965) Bounded Buffer with Semaphores


‹ Initialization producer() { consumer() {
z Initialize a value atomically while (1) { while (1) {
‹ P (or Down or Wait) definition produce an item P(fullCount);
P(emptyCount);
z Atomic operation
P(mutex);
z Wait for semaphore to become positive and then decrement P(mutex); take an item from buffer
P(s){ put the item in buffer V(mutex);
while (s <= 0) V(mutex);
; V(emptyCount);
s--; V(fullCount); consume the item
} } }
‹ V (or Up or Signal) definition } }
z Atomic operation
z Increment semaphore by 1
‹ Initialization: emptyCount = N; fullCount = 0
V(s){ ‹ Are P(mutex)and V(mutex) necessary?
s++;
}

3
Implementation Motivation

P(sem) { V(sem) { ‹ A shared queue has Enqueue and Dequeue:


while (!TAS(sem.guard)) while (!TAS(sem.guard))
; ; Enqueue(q, item) Dequeue(q)
sem.value--; sem.value++; { {
if (sem.value < 0) { if (sem.value <= 0) Acquire(mutex); Acquire(mutex);
enqueue self to sem.q; dequeue sem.q; put item into q; take an item from q;
schedule & sem.guard = 0; make thread ready; Release(mutex); Release(mutex);
}; }; } return item;
sem.guard = 0; sem.guard = 0; }
} }

‹ It is a consumer and producer problem


z Dequeue(q) blocks until q is not empty
‹ Would this work?
‹ Semaphores are difficult to use: orders are important

Monitor: Hide Mutual Exclusion Condition Variables in A Monitor


Queues
‹ Brinch-Hansen (73), Hoare (74) ‹ Wait( condition )
associated
‹ Procedures are mutual exclusive z Block on “condition” with x, y
‹ Signal( condition ) conditions
Shared z Wakeup a blocked process x
y
data on “condition”
Queue of waiting processes ‹ Conditions are not “sticky” Shared
trying to enter the monitor data
...

procedures ...
Entry queue
procedures
Producer-Consumer with Monitors Options of the Signaler
‹ Run the signaled thread immediately and suspend the
monitor ProdCons
condition full, empty;
current one (Hoare)
procedure Producer
begin
z If the signaler has other work to do, life is complex
procedure Enter;
begin
while true do z It is difficult to make sure there is nothing to do, because the
begin
if (buffer is full)
produce an item
signal implementation is not aware of how it is used
wait(full);
put item into buffer;
ProdCons.Enter(); z It is easy to prove things
end;
if (only one item)
signal(empty);
end; ‹ Exit the monitor (Hansen)
end;
procedure Consumer
z Signal must be the last statement of a monitor procedure
procedure Remove;
begin
while true do
‹ Continues its execution (Mesa)
begin
if (buffer is empty)
begin z Easy to implement
ProdCons.Remove();
wait(empty);
consume an item; z But, the condition may not be true when the awaken process
remove an item;
if (buffer was full)
end; actually gets a chance to run
end;
signal(full);
end;
10

Mesa Style “Monitor” (Birrell’s Paper) Consumer-Producer with Mesa-Style Monitor


‹ Associate a condition variable with a mutex static count = 0;
‹ Wait( mutex, condition ) static Cond full, empty;
z Atomically unlock the mutex and enqueued on the condition static Mutex lock;
variable (block the thread)
z Re-lock the lock when it is awaken Enter(Item item) { Remove(Item item) {
Acquire(lock); Acquire(lock);
‹ Signal( condition ) if (count==N) if (!count)
z No-op if there is no thread blocked on the condition variable Wait(lock, full); Wait(lock, empty);
z Wake up at least one if there are threads blocked insert item into buffer remove item from buffer
count++; count--;
‹ Broadcast( condition ) if (count==1) if (count==N-1)
z Wake up all waiting threads Signal(empty); Signal(full);
‹ Original Mesa paper Release(lock); Release(lock);
z B. Lampson and D. Redell. Experience with processes and } }
monitors in Mesa. Comm. ACM 23, 2 (feb 1980), pp 106-117.
Any issues with this?
12
Consumer-Producer with Mesa-Style Monitor The Programming Idiom
‹ Waiting for a resource ‹ Make a resource available
static count = 0;
static Cond full, empty;
Acquire( mutex ); Acquire( mutex );
static Mutex lock;
while ( no resource ) ...
Enter(Item item) { Remove(Item item) { wait( mutex, cond ); (make resource available)
Acquire(lock); Acquire(lock); ... ...
while (count==N) while (!count) (use the resource) Signal( cond );
Wait(lock, full); Wait(lock, empty); ... /* or Broadcast( cond );
insert item into buffer remove item from buffer Release( mutex); Release( mutex);
count++; count--;
if (count==1) if (count==N-1)
Signal(empty); Signal(full);
Release(lock); Release(lock);
} }

13 14

Revisit the Motivation Example Condition Variables Primitives


‹ Wait( mutex, cond ) ‹ Signal( cond )
Enqueue(Queue q, Item GetItem(Queue q) {
Item item) { Item item; z Enter the critical section z Enter the critical section
(min busy wait) (min busy wait)
Acquire(lock); Acquire( lock ); z Release mutex z Wake up a TCB in cond’s
while ( q is empty )
z Put my TCB to cond’s queue
insert an item to q; Wait( lock, Empty);
queue z Exit the critical section
Signal(Empty); remove an item; z Call scheduler
Release(lock);
} Release( lock ); z Exit the critical section
return item; . . . (blocked)
}

z Waking up:
• Acquire mutex
‹ Can this be further improved?
• Resume

16
More on Mesa-Style Monitor Evolution of Monitors
‹ Signaler continues execution ‹ Brinch-Hansen (73) and Hoare Monitor (74)
z Concept, but no implementation
‹ Waiter simply put on ready queue, with no special z Requires Signal to be the last statement (Hansen)
priority z Requires relinquishing CPU to signaler (Hoare)
z Must then spin and reevaluate the condition ‹ Mesa Language (77)
z Monitor in language, but signaler keeps mutex and CPU
‹ No constraints on when the waiting thread/process must z Waiter simply put on ready queue, with no special priority
run after a “signal” ‹ Modula-2+ (84) and Modula-3 (88)
‹ Simple to introduce a broadcast: wake up all z Explicit LOCK primitive
z Mesa-style monitor
‹ No need to make signal sticky ‹ Pthreads (95)
‹ No constrains on signaler z Started standard effort around 1989
z Defined by ANSI/IEEE POSIX 1003.1 Runtime library
z Can execute after signal call (Hansen’s cannot)
‹ Java threads
z Do not need to relinquish control to awaken thread/process z James Gosling in early 1990s without threads
z Use most of the Pthreads primitives

Example: A Simple Barrier Using Semaphores as A Barrier


‹ Thread A and Thread B ‹ Use two semaphores
want to meet at a Thread A Thread B init(s1, 0);
particular point and then init(s2, 0);
go on
Thread A Thread B
‹ How would you program … …
V(s1); V(s2);
this with monitor?
P(s2); P(s1);
… …

19 20
Example: Interrupt Handler Use Semaphore to Signal
‹ A device thread works with an interrupt handler
‹ What to do with shared data? Init(s,0);
‹ What if “m” is held by another thread or by itself?
Device thread Interrupted Thread
while (1) {
Device thread Interrupt handler P(s); …
Acquire(m); Interrupt handler
... ... ... ... Interrupt
Acquire(); Acquire(); deal with interrupt V(s); …
...

Release();
...
? ...

Release();
...
}
...
Release(m);
...

21 22

Equivalence Summary
‹ Semaphores ‹ Semaphores
z Good for signaling ‹ Monitors
z Not good for mutex because it is easy to introduce a bug z Hoare’s
‹ Monitors z Mesa-style and its idiom
z Good for scheduling and mutex ‹ Examples
z Maybe costly for a simple signaling z Use cases for semaphores

23 24

You might also like