Sei sulla pagina 1di 334

Silberschatz, Galvin and Gagne 2009

Operating System Concepts 8


th
Edition,
Process Synchronization
Modified by M.Rebaudengo - 2010
6.2
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Concurrency
! Concurrency is the simultaneous execution of threads
" The system must support concurrent execution of threads
" Scheduling:
! Deals with execution of unrelated threads
" Concurrency:
! Deals with execution of related threads

Why is it necessary?
! Cooperation: One thread may need to wait for the result of some operation
done by another thread
" e.g. Calculate Average must wait until all data reads are completed
! Competition: Several threads may compete for exclusive use of resources
" e.g. two threads trying to increment the value is a memorylocation
6.3
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Competition and Cooperation
! Competition
" Processes compete for resources
" Each process could exist without the other
! Cooperation
" Each process aware of the other
" Processes Synchronization
" Exchange information with one another
! Share memory
! Message passing
6.4
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Resources
! An object, necessary to a task in order to execute
" Hardware resources:
! Co-processor
! I/O system
! printer
! memory
! HDD
! network
" Software resources:
! buffer memory space
! portion of code source.
6.5
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Concurrence
! When several tasks want to obtain a resource, they enter in competition.
The scheduler solves the allocation problem to this resource.
" The scheduling is done by considering:
! the task's priority
! the shared time
6.6
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Mutual Exclusion
! Critical resource: a resource not shareable for which sharing by the threads
must be controlled by the system. Such a mechanism is called mutual
exclusion
! Critical section of a program: a part of a program where access to a critical
resource occurs
! If one thread is going to use a shared resource (critical resource)
" a le
" a variable
" printer
" register, etc
! the other thread must be excluded from using the same resource
6.7
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Process Interaction
! Processes unaware of each other (competition)
" independent processes not working together
" The OS must resolve the competition for resources.
! I/O, memory, printer, tape drive, etc.
" Each process should leave the state of any resource that it uses
unaffected.
" issues involved
! Mutual exclusion
The resource being competed for is called a critical resource
The portion of program in each process that uses the critical
resource is called the critical section or critical region
At any time, only one program is allowed to be in its critical
section.
! Deadlock
! Starvation
6.8
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Process Interaction (cont.)
! Processes indirectly aware of each other (cooperation by sharing)
" shared access to some object
! shared variables, les, or databases
! Processes may use and update the shared data without reference to
other process, but know that other processes may have access to
the same data.
" Issues involved
! maintenance of data integrity
! Since data are stored in resources (devices, memory), the control
problems of mutual exclusion, deadlock, and starvation are still
present.
Mutual exclusion applies only to writing, not reading of data.
! Data coherence
Example: a = b must be enforced in the following two processes:
P1: a := a + 1;
b := b + 1;
P2: b := 2 * b;
a := 2 * a;
(Cont.)
6.9
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Process interaction (cont.)
! If the traces of P1 and P2 are as below, a = b is not enforced.
1. a := a + 1;
2. b := 2 * b;
3. b := b + 1;
4. a := 2 * a;
! The solution is to put the instructions of each process in a critical section.
6.10
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Process interaction (cont.)
! Processes directly aware of each other (cooperation by communication)
" Interprocess communication exists.
" Sending and receiving of messages are involved.
" Issues involved
! no shared object, hence no mutual exclusion
! The problems of deadlock and starvation are still present.
deadlock: two processes may be blocked, waiting for a message
from the other.
starvation: three processes are involved in communication, but
two of them exchange information repeatedly that the third one
waits indenitely for its turn.
6.11
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Race Conditions
! When two or more processes/threads are executing concurrently, the
result can depend on the two instruction streams are interleaved.
! Race conditions may cause:
" undesired computation results.
" bugs which are hard to reproduce!
6.12
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Resource Competition
! When several process may asynchronously access a common data area,
it is necessary to protect the data from simultaneous change by two or
more processes.
! If not, the updated area may be left in an inconsistent state.
6.13
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Background
! Concurrent access to shared data may result in data
inconsistency
! Maintaining data consistency requires mechanisms to ensure the
orderly execution of cooperating processes
! Suppose that we wanted to provide a solution to the consumer-
producer problem that lls all the buffers.
! We can do so by having an integer count that keeps track of the
number of full buffers.
" Initially, count is set to 0.
" It is incremented by the producer after it produces a new buffer
" It is decremented by the consumer after it consumes a buffer.
6.14
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Producer
while (true) {

/* produce an item and put in nextProduced */
while (count == BUFFER_SIZE)
; // do nothing
buffer [in] = nextProduced;
in = (in + 1) % BUFFER_SIZE;
count++;
}
In
out
6.15
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Consumer

while (true) {
while (count == 0)
; // do nothing
nextConsumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
count--;

/* consume the item in nextConsumed


}
In
out
6.16
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Race Condition
! Race condition: The outcome of concurrent thread execution depends
on the particular order in which the access takes place.
! count++ could be implemented as
register1 := count
register1 := register1 + 1
count := register1
! count-- could be implemented as
register2 := count
register2 := register2 - 1
count := register2
! Consider this execution interleaving with count = 5 initially:
T0: producer execute register1 := count {register1 = 5}
T1: producer execute register1 := register1 + 1 {register1 = 6}
T2: consumer execute register2 := count {register2 = 5}
T3: consumer execute register2 := register2 - 1 {register2 = 4}
T4: producer execute count := register1 {count = 6}
T5: consumer execute count := register2 {count = 4}

6.17
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Process synchronization
! To prevent race conditions, concurrent processes must be synchronized.
6.18
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Synchronization Motivation: Too much milk
problem
! Example: two cooperating threads, not cooperating properly
People need to coordinate
Arrive home, put milk away 3:30
Buy milk 3:25
Arrive at store Arrive home, put milk away 3:20
Leave for store Buy milk 3:15
Leave for store 3:05
Look in Fridge. Out of milk 3:00
Look in Fridge. Out of milk Arrive at store 3:10
Person B Person A Time
! Concurrent threads introduce problems when accessing shared data
" Programs must be insensitive to arbitrary interleavings
" Without careful design, shared variables can become completely inconsistent.

6.19
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
More Definitions
! Lock: prevents someone from doing something
" Lock before entering critical section and
before accessing shared data
" Unlock when leaving, after accessing shared data
" Wait if locked
! all synchronization involves waiting
! For example: x the milk problem by putting a key on the refrigerator
" Lock it and take key if you are going to go buy milk
" Fixes too much: roommate angry if only wants orange juice
#
$
@
%
@
#
$
@

6.20
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
20
Solving the Too Much Milk Problem
! First: use atomic loads & stores as building blocks
" Leave a note (lock)
" Remove a note (unlock)
" Dont buy milk if theres a note (wait)
6.21
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Too Much Milk: Solution #1
! Suppose a computer tries this (remember, only memory read/write are
atomic):
if (noMilk) {
if (noNote) {
leave Note;
buy milk;
remove note;
}
}
! Result?
" Thread can get context switched after checking milk and note but before
buying milk!
" Still too much milk but only occasionally!
6.22
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Too Much Milk Solution #2
! How about labeled notes?
" Now we can leave note before checking
! Algorithm looks like this:
Thread A Thread B
leave note A; leave note B;
if (noNote B) { if (noNoteA) {
if (noMilk) { if (noMilk) {
buy Milk; buy Milk;
} }
} }
remove note A; remove note B;
! Does this work?
! Possible for neither thread to buy milk
" Context switches at exactly the wrong times can lead each to think that the other
is going to buy
" Im not getting milk, Youre getting milk
" This kind of lockup is called starvation!
6.23
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Too Much Milk Solution #3
! Here is a possible two-note solution:
Thread A Thread B
leave note A; leave note B;
while (note B) { //X if (noNote A) { //Y
do nothing; if (noMilk) {
} buy milk;
if (noMilk) { }
buy milk; }
} remove note B;
remove note A;
! Does this work? Yes. Both can guarantee that:
" It is safe to buy, or
" Other will buy, ok to quit
! At X:
" if no note B, safe for A to buy,
" otherwise wait to nd out what will happen
! At Y:
" if no note A, safe for B to buy
" Otherwise, A is either buying or waiting for B to quit
6.24
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Solution #3 discussion
! Our solution protects a single Critical-Section piece of code for each thread:
if (noMilk) {
buy milk;
}
! Solution #3 works, but its really unsatisfactory
" Really complex even for this simple example
" As code is different from Bs what if lots of threads?
! Code would have to be slightly different for each thread
" While A is waiting, it is consuming CPU time
! This is called busy-waiting
! Theres a better way
" Have hardware provide better (higher-level) primitives than atomic load and store
" Build even higher-level programming abstractions on this new hardware support

6.25
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Too Much Milk: Solution #4
! Suppose we have some sort of implementation of a lock
" Lock.Acquire() wait until lock is free, then grab
" Lock.Release() Unlock, waking up anyone waiting
" These must be atomic operations if two threads are waiting for the lock
and both see its free, only one succeeds to grab the lock
! Then, our milk problem is easy:
milklock.Acquire();
if (nomilk)
buy milk;
milklock.Release();
! Section of code between Acquire() and Release() is called a Critical
Section
Critical Section
6.26
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Critical Section
! A section of code, common to n cooperating processes, in which the
processes may be accessing common variables, competing to use some
shared data
! Each process has a code segment, called critical section, in which the
shared data is accessed.
! Problem ensure that when one process is executing in its critical
section, no other process is allowed to execute in its critical section
" A code within a critical section must be executed exclusively by a
single process.
6.27
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Critical-Section Problem

! A Critical Section environment contains:
" Entry Section: code requesting entry into the critical section.
" Critical Section: code in which only one process can execute at any one
time.
" Exit Section: the end of the critical section, releasing or allowing others in.
" Remainder Section: rest of the code after the critical section.
do {
entry section
critical section
exit section
remainder section
} while (TRUE);
6.28
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Solution to Critical-Section Problem
! The critical section must enforce all 3 of the
following rules:
1. Mutual Exclusion - If process P
i
is
executing in its critical section, then no
other processes can be executing in their
critical sections
2. Progress - If no process is executing in its
critical section and there exist some
processes that wish to enter their critical
section, then the selection of the processes
that will enter the critical section next
cannot be postponed indenitely
3. Bounded Waiting - A bound must exist on
the number of times that other processes
are allowed to enter their critical sections
after a process has made a request to
enter its critical section and before that
request is granted.
Critical Section
1. only one process
When exiting from CS
2. Pick up a process to enter
3. Delta time exists
When coming and entering CS
Speed and Number of CPUs: No assumption may
be made about speeds or number of CPUs.
6.29
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
2
9
Process A
Process B
B blocked
A enters
critical region
B tries to enter
critical region
B enters
critical region
A leaves
critical region
B leaves
critical region
Time
Critical regions
! Use critical regions to provide mutual exclusion and help x race
conditions
! Four conditions to provide mutual exclusion
1. No two processes simultaneously in critical region
2. No assumptions made about speeds or number of CPUs
3. No process running outside its critical region may block another
process
4. A process may not wait forever to enter its critical region
6.30
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Concurrency requirements
! Among all threads that have CSs for the same resource
" Only one thread at a time is allowed into its CS,
! It must not be possible for a thread requiring access to a CS to be
delayed indenitely
" no deadlock
" no starvation
! When no thread is in a CS, any thread requesting entry to the CS
must be granted permission without delay
! No assumptions are made about the relative thread speeds or
number of processors.
! A thread remains inside its CS for a nite time only.
6.31
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Solution to Critical-Section Problem
1.Mutual Exclusion - If process P
i
is executing in
its critical section, then no other processes can
be executing in their critical sections

do {
entry section
critical section
exit section
remainder section
} while (TRUE);
do {
entry section
critical section
exit section
remainder section
} while (TRUE);
6.32
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Solution to Critical-Section Problem
2.Progress - If no process is executing in its critical
section and there exist some processes that wish to
enter their critical section, then the selection of the
processes that will enter the critical section next cannot
be postponed indenitely

do {
entry section
critical section
exit section
remainder section
} while (TRUE);
6.33
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Solution to Critical-Section Problem
3.Bounded Waiting - A bound must exist on the
number of times that other processes are allowed
to enter their critical sections after a process has
made a request to enter its critical section and
before that request is granted
! Assume that each process executes at a
nonzero speed
! No assumption concerning relative speed of
the N processes
6.34
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Comments
! Deadlock (all processes are blocked) represents a violation of
progress
! Starvation (a process never enters in CS) represents a violation of
bounded waiting.
6.35
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
35
Definitions
6.36
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Mutual Exclusion
! Need ways to enforce critical sections
" Prevent race conditions that cause errors
! Requirements for mutual exclusion
" Safety (aka mutual exclusion): only one process/thread at a time inside CS
" Liveness (aka progress): if nobody has access and somebody wants in,
somebody gets in
" No starvation (aka bounded waiting): if you want in, you will eventually get in
! Desirable properties:
" Efciency: can get into CS in relatively few instructions
" Low load: waiting for CS doesnt waste resources
" Fairness: if you want in, nobody else gets in ahead of you twice (i.e., If two
threads are both trying to enter a critical section, they have equal chances of
success).
6.37
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Types of solutions
! Software solutions
" algorithms whos correctness does not rely on any other assumptions
! Hardware solutions
" rely on some special machine instructions
! Operating System solutions
" provide some functions and data structures to the programmer
6.38
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Software solutions
6.39
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
do {
while ( turn ^= i );
/* critical section */
turn = j;
/* remainder section */
} while(TRUE);
Critical section problem
! Heres an example of a simple piece of code containing the components
required in a critical section.
! i is the current process, j the "other" process
! The variable turn indicates whose turn it is to enter the critical section.
Entry Section
Critical Section
Exit Section
Remainder Section
6.40
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Solving the problem
! Shared variables:
" char inside;boolean variable
initially inside = 0
! Now ask:
" Is this Mutual Exclusion? Progress? Bounded waiting?
Code is unsafe: thread 0 could finish the while
test when inside is false, but then 1 might check
before thread 0 can set inside to true!
do {
while (inside) continue;
inside = true;
critical section
inside = false;
reminder section
} while (1);
Algorithm 0
6.41
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Shared Pointer to Active Process

Algorithm 1
! Shared variables:
" int turn;
initially turn = 0
" turn = i ! P
i
can enter its critical section
! Process P
i

do {
while (turn != i) ;
critical section
turn = j;
reminder section
} while (1);
! Satises mutual exclusion, but not progress
" Pi, Pj, Pi, Pj strict alternation of processes
" Pi leaves, Pj busy with long I/O, Pi comes back to CS-entry;
" No one in the CS, but Pi has to wait until Pj to come to the CS
" What if Pj never comes back to CS ?
6.42
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Boolean Array
! FLAG FOR EACH PROCESS GIVES STATE:
" Each process maintains a ag indicating that it wants to get into the
critical section. It checks the ag of the other process and doesnt
enter the critical section if that other process wants to get in.
Are the three Critical Section
Requirements Met?
do {
ag[i] = true;
while (ag[j]) ;
critical section
ag [i] = false;
remainder section
} while (1);
Algorithm 2
Shared variables
# boolean ag[2];
initially ag [0] = ag [1] = false.
# ag [i] = true ! P
i
ready to enter its critical section
6.43
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Boolean Array
! Satises mutual exclusion, but not progress requirement.
Algorithm 2
Pi
do {
ag[i] = true;
while (ag[j]) ;
critical section
ag [i] = false;
remainder section
} while (1);
Pj
do {
ag[j] = true;
while (ag[i]) ;
critical section
ag [j] = false;
remainder section
} while (1);
Pi: sets ag[i] to true
Pj: sets ag[j] to true
Indenite wait: deadlock
Algorithm depends on the exact timing of the two processes
6.44
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
A solution that works: Dekkers Algorithm (1965)
! It was the rst provably-correct solution to the critical section problem.
Shared variables
" boolean ag[2];
initially ag [0] = ag [1] = false.
" int turn;
initially turn = 0
" turn = i ! Pi can enter its critical section
! do#
{$$$$$ag[i] = true;
$$$$$$$ while ag[j] do
$$$$$$$ $$$$$$$ if turn == j then
$$$$$$$ $$$$$$$ {$
$$$$$$$ $$$$$$$ $$$$$$$ ag[i] = false;
$$$$$$$ $$$$$$$ $$$$$$$ while turn = j do no-op;
$$$$$$$ $$$$$$$ $$$$$$$ ag[i] = true;
$$$$$$$ $$$$$$$ }
$$$$$$$ $$$$$$critical section#
$$$$$$$ turn = j;
$$$$$$$ ag[i] = false;
$$$$$$$ remainder section#
} while (1);
6.45
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Analysis of Dekkers algorithm
! Safety:
" No process will enter its CS without setting its inside ag.
" Every process checks the other process inside ag after setting its own.
" If both are set, the turn variable is used to allow only one process to
proceed.
! Liveness: The turn variable is only considered when both processes are
using, or trying to use, the resource
! Bounded waiting: The turn variable ensures alternate access to the
resource when both are competing for access.
6.46
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Postscript
! Dekkers algorithm does not provide strict alternation
" Initially, a thread can enter critical section without accessing turn
! Dekkers algorithm will not work with many modern CPUs
" CPUs execute their instructions in an out-of-order (OOO) fashion
" This algorithm won't work on Symmetric MultiProcessors (SMP) CPUs
equipped with OOO without the use of memory barriers
! Additionally, Dekkers algorithm can fail regardless of platform due to many
optimizing compilers
" Compiler may remove writes to ag since never accessed in loop
" Further, compiler may remove turn since never accessed in loop
! Creating an innite loop!
6.47
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Petersons Solution
! Two-process solution
! Assume that the LOAD and STORE instructions are
atomic (they cannot be interrupted).
! The two processes share two variables:
" int turn;
" Boolean ag[2]
! The variable turn indicates whose turn it is to enter the
critical section.
! The ag array is used to indicate if a process is ready to
enter the critical section. ag[i] = true implies that
process P
i
is ready!
Algorithm 3
6.48
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
do {
ag[i] = TRUE;
turn = j;
while (ag[j] && turn == j);
critical section
ag[i] = FALSE;
remainder section
} while (TRUE);
Petersons Solution: algorithm for Process P
i
Algorithm 3
6.49
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Prove this algorithm is correct
1. Mutual exclusion is preserved
2. The progress requirement is satised.
3. The bounded waiting requirement is met.

6.50
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Prove this algorithm is correct
1. Mutual exclusion is preserved

do {
ag[i] = TRUE;
turn = j;
while (ag[j] && turn == j);
critical section
ag[i] = FALSE;
remainder section
} while (TRUE);
do {
ag[j] = TRUE;
turn = i;
while (ag[i] && turn == i);
critical section
ag[j] = FALSE;
remainder section
} while (TRUE);
6.51
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Proof of correctness
! Mutual exclusion is preserved:
" P0 and P1 are both in CS
! only if
ag[0] = ag[1] = true
! and only if
turn = i for each Pi (impossible)
6.52
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Prove this algorithm is correct
2. Is the progress requirement satised ?

do {
ag[i] = TRUE;
turn = j;
while (ag[j] && turn == j);
critical section
ag[i] = FALSE;
remainder section
} while (TRUE);
do {
ag[j] = TRUE;
turn = i;
while (ag[i] && turn == i);
critical section
ag[j] = FALSE;
remainder section
} while (TRUE);
Pj stuck at this point
6.53
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Prove this algorithm is correct
2.1 The progress requirement is satised.

do {
ag[i] = TRUE;
turn = j;
while (ag[j] && turn == j);
critical section
ag[i] = FALSE;
remainder section
} while (TRUE);
do {
ag[j] = TRUE;
turn = i;
while (ag[i] && turn == i);
critical section
ag[j] = FALSE;
remainder section
} while (TRUE);
ag[i] = false ! Pj can enter
6.54
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Prove this algorithm is correct
2.2 Is the progress requirement is satised ?

do {
ag[i] = TRUE;
turn = j;
while (ag[j] && turn == j);
critical section
ag[i] = FALSE;
remainder section
} while (TRUE);
do {
ag[j] = TRUE;
turn = i;
while (ag[i] && turn == i);
critical section
ag[j] = FALSE;
remainder section
} while (TRUE);
6.55
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Prove this algorithm is correct
2.2.1 The progress requirement is satised.

do {
ag[i] = TRUE;
turn = j;
while (ag[j] && turn == j);
critical section
ag[i] = FALSE;
remainder section
} while (TRUE);
do {
ag[j] = TRUE;
turn = i;
while (ag[i] && turn == i);
critical section
ag[j] = FALSE;
remainder section
} while (TRUE);
turn = j ! Pj can enter
6.56
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Prove this algorithm is correct
2.2.2 Is the progress requirement is satised ?

do {
ag[i] = TRUE;
turn = j;
while (ag[j] && turn == j);
critical section
ag[i] = FALSE;
remainder section
} while (TRUE);
do {
ag[j] = TRUE;
turn = i;
while (ag[i] && turn == i);
critical section
ag[j] = FALSE;
remainder section
} while (TRUE);
turn = i ! Pi can enter
6.57
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Prove this algorithm is correct
2.2.2.a The progress requirement is satised.

do {
ag[i] = TRUE;
turn = j;
while (ag[j] && turn == j);
critical section
ag[i] = FALSE;
remainder section
} while (TRUE);
do {
ag[j] = TRUE;
turn = i;
while (ag[i] && turn == i);
critical section
ag[j] = FALSE;
remainder section
} while (TRUE);
ag[i] = false ! Pj can enter
6.58
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Prove this algorithm is correct
2.2.3 The progress requirement is satised.

do {
ag[i] = TRUE;
turn = j;
while (ag[j] && turn == j);
critical section
ag[i] = FALSE;
remainder section
} while (TRUE);
do {
ag[j] = TRUE;
turn = i;
while (ag[i] && turn == i);
critical section
ag[j] = FALSE;
remainder section
} while (TRUE);
turn = j ! Pj can enter
6.59
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Prove this algorithm is correct
3. The bounded waiting requirement is met

do {
ag[i] = TRUE;
turn = j;
while (ag[j] && turn == j);
critical section
ag[i] = FALSE;
remainder section
} while (TRUE);
do {
ag[j] = TRUE;
turn = i;
while (ag[i] && turn == i);
critical section
ag[j] = FALSE;
remainder section
} while (TRUE);
Pi will enter the CS after at most one entry by Pj
6.60
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Can we generalize to many threads?
! Obvious approach wont work:
! Issue: Whos turn next?
CSEnter(int i)
{
inside[i] = true;
for(J = 0; J < N; J++)
while(inside[J] && turn == J)
continue;
}
CSExit(int i)
{
inside[i] = false;
}
6.61
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Bakery Algorithm
! Think of a popular store with a crowded counter
" People take a ticket from a machine
" If nobody is waiting, tickets dont matter
" When several people are waiting, ticket order determines the
order in which they can make purchases.
! Before entering its critical section, process receives a number.
Holder of the smallest number enters the critical section.
" Line up processes in a total order
" Smallest element of the total order gets the critical section
! If processes Pi and Pj receive the same number, if i < j, then Pi is
served rst; else Pj is served rst.
! The numbering scheme always generates numbers in increasing
order of enumeration; i.e., 1,2,3,3,3,3,4,5...
6.62
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Bakery Algorithm: Take 1
! int ticket[n];
! int next_ticket;
CSEnter(int i)
{
ticket[i] = ++next_ticket;
for(J = 0; J < N; J++)
while(ticket[J] && ticket[J] < ticket[i])
continue;
}
CSExit(int i)
{
ticket[i] = 0;
}
! Access to next_ticket is a problem!
6.63
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Bakery Algorithm: Take 2
! int ticket[n];
CSEnter(int i)
{
ticket[i] = max(ticket[0], ticket[N-1])+1;
for(J = 0; J < N; J++)
while(ticket[J] && ticket[j] < ticket[i])
continue;
}
CSExit(int i)
{
ticket[i] = 0;
}
! Clever idea: just add one to the max.
Just add 1 to the max!
! 2 could pick the same value!
6.64
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Bakery Algorithm: Take 3
If i, j pick same ticket value, ids break tie:

(ticket[J] < ticket[i]) || (ticket[J]==ticket[i] && J<i)

Notation: (B,J) < (A,i) to simplify the code:

(B<A || (B==A && J<i)), e.g.:


#
(ticket[J],J) < (ticket[i],i)
6.65
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Bakery Algorithm: Take 4
! int ticket[N];

CSEnter(int i)
{
ticket[i] = max(ticket[0], ticket[N-1])+1;
for(J = 0; J < N; J++)
while(ticket[J] && (ticket[J],J) < (ticket[i],i))
continue;
}
CSExit(int i)
{
ticket[i] = 0;
}
! I could look at J when J is still storing its ticket, and yet J could have a lower
id than me (i)!
6.66
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Bakery Algorithm (Lamport, 1974)
! int ticket[N];
! boolean choosing[N] = false;

CSEnter(int i)
{
choosing[i] = true;
ticket[i] = max(ticket[0], ticket[N-1])+1;
choosing[i] = false;
for(J = 0; J < N; J++) {
while(choosing[J]) continue;
while(ticket[J] && (ticket[J],J) < (ticket[i],i))
continue;
}
}
CSExit(int i)
{
ticket[i] = 0;
}
6.67
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Drawbacks of software solutions
! Processes that are requesting to enter in their critical section are busy
waiting (consuming processor time needlessly)
! If CSs are long, it would be more efcient to block processes that are
waiting.
6.68
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Hardware Synchronization
6.69
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Hardware Synchronization
! Any solution to the critical-section problem requires a
simple tool a lock.
! Race conditions are prevented by requiring that critical
regions be protected by locks
do {
acquire lock
critical section
release lock
remainder section
} while (TRUE);
6.70
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Solution to Critical-section Problem Using Locks
! Lock: prevents someone from doing something
! Lock before entering critical section and
before accessing shared data
! Unlock when leaving, after accessing shared data
! Wait if locked: all synchronization involves waiting.

6.71
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Hardware Synchronization
! Many systems provide hardware support for critical section code
! Uniprocessors could disable interrupts
" Currently running code would execute without preemption
" Generally too inefcient on multiprocessor systems
! Operating systems using this not broadly scalable
! Modern machines provide special atomic hardware instructions
! Atomic = non-interruptable
" test memory word and set value
" swap contents of two memory words
6.72
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Critical Section Access - Disabling Interrupts
! One way to provide mutual exclusion is to disable interrupts (and thus
context switching), but
" It cannot be done for long (or some interrupts will be lost)
" User processes are not allowed to do that
" I/O may be needed while in a critical section (and it will never be
completed with interrupts disabled)
" It disables even time interrupts, thus not allowing preemption
" It does not work in a multi-processor system, anyway!
6.73
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Interrupt Disabling
! If it is guaranteed that no interrupt occurs while a thread is in the CS,
then no other thread can enter the same CS
Process Pi:
repeat
disable interrupts
critical section
enable interrupts
remainder section
forever
6.74
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Hardware solutions: interrupt disabling
! On a uniprocessor: no overlapping of execution
! Therefore, if a process doesnt get interrupted in its CS, mutual exclusion
is guaranteed.
! Degrades efciency because processor cannot interleave threads when
interrupts are disabled
! Simplest solution
" but it is not desirable to give a thread the power of controlling
interrupts
! On a multiprocessor: mutual exclusion is not preserved
! Generally not an acceptable solution.
6.75
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Lock Implementation
! Maintain a lock variable and impose mutual exclusion only during
operations on that variable
" Avoid interruption between checking and setting lock value
" Otherwise two threads could think that they both have lock
! Waiting queue.

Acquire() {
disable interrupts;

if (value == BUSY) {
put thread on queue waiting for lock;
Go to sleep();
// Enable interrupts?
} else {
value = BUSY;
}

enable interrupts;
}
Critical
Section
6.76
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Lock Implementation
Acquire() {
disable interrupts;

if (value == BUSY) {
put thread on queue waiting for lock;
Go to sleep();
// Enable interrupts?
} else {
value = BUSY;
}

enable interrupts;
}
Release () {
disable interrupts;
if anyone on wait queue of threads waiting for lock
{
take waiting thread off queue,
put on ready queue
}
else value = FREE ;

enable interrupt;
}
6.77
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Interrupt re-enable in going to sleep
! What about re-enabling ints when going to sleep?
! Before Putting thread on the wait queue?
" Release can check the queue and not wake up thread
! After putting the thread on the wait queue
" Release puts the thread on the ready queue, but the thread still thinks it needs to go
to sleep
" Misses wakeup (wakeup before sleep does not work) and still holds lock (deadlock!)
! Want to put it after sleep(). But how?
Acquire() {
disable interrupts;
if (value == BUSY) {
put thread on queue waiting for lock;
Go to sleep();
} else {
value = BUSY;
}
enable interrupts;
}
Enable Position
Enable Position
Enable Position
6.78
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
How to Re-enable After Sleep()?
! Responsibility of the next thread to re-enable interrupts
! When the sleeping thread wakes up, returns to acquire and re-enables interrupts
Thread A Thread B
.
.
disable ints
sleep
sleep return
enable ints
.
.
.
disable int
sleep
sleep return
enable ints
.
.
c
o
n
te
x
t
sw
itc
h

c
o
n
te
x
t
sw
itc
h

6.79
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Atomic Read-Write-Modify Instructions
! Modern machines provide special atomic hardware instructions
! Atomic = non-interruptable
! Atomically read old value, write new value
! Examples:
" Test & Set (most architectures)
" Exchange (Pentium)
" Compare & Swap (68K, Sparc)
6.80
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Hardware lock
! The hardware lock is done with a binary ag which indicates if the resource
is free or not
! Each task will test the ag before using the resource: if it is already used by
another task, it will do an active wait.
6.81
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Hardware lock functioning
! If the resource is free, the task will set the ag busy before using the
resource and will set it again free after nishing the job with the resource.
! It is necessary to have a means to test and set this ag in an indivisible (or
atomic) way.
! Processors usually have a TEST and SET instruction allowing to test and
set/reset a memory location in an atomic way.
6.82
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Atomic Operations
! Atomic Operation: an operation that always runs to completion (without
interruption) or not at all
" It is indivisible: it cannot be stopped in the middle and its state cannot be
modied by someone else in the middle
" Fundamental building block if no atomic operations, then have no way
for threads to work together
! On most machines, memory references and assignments (i.e. loads and
stores) of words are atomic
6.83
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Test and set
! We assume the existence of a shared lock variable
int lock = 0; // shared
! Will only have two possible values
" 0 meaning nobody is inside the critical section
" 1 meaning somebody has entered the critical section
6.84
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Test and Set
! Atomic operation:
" Test the value of a ag (lock)
" If it is set, leave it (and wait until it is reset by the other).
" Else set it (as saying "Ill enter CS")
! Example:
while ( testAndSet( lock ) == true )
;
// Ill enter CS.
6.85
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Test And Set Instruction
! Denition:
boolean TestAndSet (boolean *target)
{
boolean rv = *target;
*target = TRUE;
return rv:
}
# if target ==1 (locked), target stays 1 and return 1, wait
# if target ==0 (unlocked), set target to 1 (lock door), return 0, and enter
CS

test-and-set(lock)
{
temp=lock;
lock=1;
return temp;
}
6.86
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
A HW-supported solution: Test and Set Lock (TSL)
! The TSL instruction reads a value at a memory location and sets it to 1
both operations combining into an atomic one:
! Enter_Critical:
TSL A, @lock | Read lock and set it to 1
CMP A, #0 | Was it 0?
JNZ Enter_Critical | Cycle until it is 0
RTS | Return to caller

Exit_Critical:
MOVE @lock, #0
RTS
6.87
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
! Shared data:
boolean lock = false;
// if lock == 0, door open, if lock == 1, door locked
! Solution (Mutual-Exclusion):
do {
while ( TestAndSet (& lock ))
; // do nothing
// critical section
lock = FALSE;
// remainder section
} while (TRUE);


Solution using TestAndSet
6.88
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Bounded-waiting Mutual Exclusion with TestandSet()
do {
waiting[i] = TRUE;
key = TRUE;
while (waiting[i] && key)
key = TestAndSet(&lock);
waiting[i] = FALSE;
// critical section
j = (i + 1) % n;
while ((j != i) && !waiting[j]) //nds next waiting thread after i
j = (j + 1) % n;
if (j == i)
lock = FALSE; //No one is waiting
else
waiting[j] = FALSE; //process j enters next
// remainder section
} while (TRUE);
6.89
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Busy Waiting (Spinning)
! Busy-Waiting: thread consumes cycles while waiting
void acquire() {
while (testset(value))
{}
}

void release() {
value = 0;
}
spin-lock
6.90
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Properties of machine instructions
! Advantages:
" Applicable to any number of processes
" Machine can receive interrupts
" Can be used on single as well as multiple processor machines sharing
main memory
" Simple and easy to verify
6.91
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
The bad news
! Peterson's algorithm and both hardware solutions we have seen rely
on busy waits.
! Busy waits waste CPU cycles:
" Generate unnecessary context switches on single processor
architectures
" Slow down the progress of other processes
6.92
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Priority inversion
! A high priority process doing a busy wait may prevent a lower priority
process to do its work and leave its critical region.
6.93
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
In conclusion (I)
! We must avoid busy wait on single processor architectures
! We can use them only for short waits on multiprocessor architectures

6.94
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
In conclusion (II)
! Several operating systems for multiprocessor architectures offer two
different mutual exclusion mechanisms:
" Busy waits for very short waits
" Putting the waiting process in the waiting state until the resource
becomes free for longer waits.
! Like waiting for a table in a restaurant:
" If we are promised a very short wait, we will wait there
" Otherwise, we might prefer to go for a walk or have a drink at the bar
6.95
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Better Locks using test&set
! Can we build test&set locks without busy-waiting?
" Cant entirely, but can minimize!
" Idea: only busy-wait to atomically check lock value
lock () {
while (test&set (guard)) {} // like interrupt disable
if (value == FREE) {
value = BUSY
} else {
put on queue of threads waiting for lock
sleep() // dont add to ready queue
}
guard = 0 // like interrupt enable
}
unlock () {
while (test&set (guard)) {} // like interrupt disable
value = FREE
if anyone on queue of threads waiting for lock {
take waiting thread off queue, put on ready queue
value = BUSY
}
guard = 0 // like interrupt enable
}
6.96
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Swap Instruction
! Denition:
void Swap (boolean *a, boolean *b)
{
boolean temp = *a;
*a = *b;
*b = temp:
}

6.97
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Solution using Swap
! Shared Boolean variable lock initialized to FALSE; Each process
has a local Boolean variable key
! Solution(Mutual-Exclusion):
do {
key = TRUE;
while ( key == TRUE)
Swap (&lock, &key );
// critical section
lock = FALSE;
// remainder section
} while (TRUE);

6.98
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Operating System solutions
6.99
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Semaphores
! The hardware-based solutions for the CS problem are complicated for
application programmers to use
! To overcome this difculty, we use a synchronization tool called a
semaphore
! Proposed by Dijkstra (1965)
! Semaphores do not require busy waiting
! Semaphore S integer variable
! Two standard operations modify S:
" wait() and signal()
" Originally called
! P(): (from the Dutch probeer te verlagen: try to decrease, Wait
(Busy wait or sleep) if the resource is not available)
! V(): (from the Dutch verhogen = to increment, free the resource).
Edsger W. Dijkstra (1930-2002)
6.100
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Semaphore Definition
! A semaphore S is a shared variable (protected by the OS) that can be used
by processes to send and receive signals.
! The following operations apply:
" Initialize(S): S has to be initialized
" Wait(S)
" Signal(S)
! OS must guarantee that each of these operations are atomic.
" It must be impossible for two processes to execute Signals
simultaneously.
" The assembly language statements that implement these operations will
never be interleaved.
6.101
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Semaphores
! Can only be accessed via two atomic operations
" wait (S) {
while S <= 0
; // no-op
S--;
}
" signal (S) {
S++;
}
6.102
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Types of Semaphores
! Counting semaphore integer value can range over an
unrestricted domain

! Binary semaphore integer value can range only between 0


and 1; can be simpler to implement
" Also known as mutex locks
" Can implement a counting semaphore S as a binary
semaphore

6.103
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Binary Semaphore
! Integer value can range only between 0 and 1; can be simpler to
implement
" Also known as mutex locks as they are locks that provide mutual
exclusion.
! We can use binary semaphore to deal with the CS problem for
multiple processes.
! The n processes share a semaphore, mutex, initialized to 1
6.104
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 104
Using semaphores
! Semaphores can be used for mutual exclusion
" Semaphore value initialized to 1
" Wait on entry to critical section
" Signal on exit from critical section
6.105
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Semaphores
! The semaphore used by railroads indicates whether the train can
proceed. When its lowered (a), an oncoming train is expected. If it
is raised (b), the train can continue.
a) Stop

b) All Clear

6.106
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
106
Semaphores
! The semaphore concept was taken from railway signalling.
! It is used to control the access on a railway section by the trains
traveling one after the other (the railway is a shared resource)
! When the train enters a section, the semaphore at the entry blocks
is lowered, and the rest of the trains have to wait till the train inside
the section leaves it.
6.107
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
107
Semaphore: functioning example
6.108
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Mutual-Exclusion Implementation with semaphores
! Provides mutual exclusion (for Process P
i
)
Semaphore mutex; // initialized to 1
do {
wait (mutex);
// Critical Section
signal (mutex);
// remainder section
} while (TRUE);

6.109
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 109
Using Semaphores for Mutex
1 repeat
2 wait(mutex);
3 critical section
4 signal(mutex);
5 remainder section
6 until FALSE
1 repeat
2 wait(mutex);
3 critical section
4 signal(mutex);
5 remainder section
6 until FALSE
semaphore mutex = 1 -- unlocked
Thread A
Thread B
6.110
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 110
Using Semaphores for Mutex
semaphore mutex = 0 -- locked
1 repeat
2 wait(mutex);
3 critical section
4 signal(mutex);
5 remainder section
6 until FALSE
1 repeat
2 wait(mutex);
3 critical section
4 signal(mutex);
5 remainder section
6 until FALSE
Thread A
Thread B
6.111
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 111
Using Semaphores for Mutex
semaphore mutex = 0 --locked
1 repeat
2 wait(mutex);
3 critical section
4 signal(mutex);
5 remainder section
6 until FALSE
1 repeat
2 wait(mutex);
3 critical section
4 signal(mutex);
5 remainder section
6 until FALSE
Thread A
Thread B
6.112
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 112
Using Semaphores for Mutex
semaphore mutex = 0 -- locked
1 repeat
2 wait(mutex);
3 critical section
4 signal(mutex);
5 remainder section
6 until FALSE
1 repeat
2 wait(mutex);
3 critical section
4 signal(mutex);
5 remainder section
6 until FALSE
Thread A
Thread B
6.113
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 113
Using Semaphores for Mutex
semaphore mutex = 0 -- locked
1 repeat
2 wait(mutex);
3 critical section
4 signal(mutex);
5 remainder section
6 until FALSE
1 repeat
2 wait(mutex);
3 critical section
4 signal(mutex);
5 remainder section
6 until FALSE
Thread A
Thread B
6.114
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 114
Using Semaphores for Mutex
semaphore mutex = 1 -- unlocked This thread can
now be released!
1 repeat
2 wait(mutex);
3 critical section
4 signal(mutex);
5 remainder section
6 until FALSE
1 repeat
2 wait(mutex);
3 critical section
4 signal(mutex);
5 remainder section
6 until FALSE
Thread A
Thread B
6.115
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 115
Using Semaphores for Mutex
semaphore mutex = 0 -- locked
1 repeat
2 wait(mutex);
3 critical section
4 signal(mutex);
5 remainder section
6 until FALSE
1 repeat
2 wait(mutex);
3 critical section
4 signal(mutex);
5 remainder section
6 until FALSE
Thread A
Thread B
6.116
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Shared Account Problem
proc_0() { proc_1() {
. . . . . .
/* Enter the CS */ /* Enter the CS */
P(mutex); P(mutex);
balance += amount; balance -= amount;
V(mutex); V(mutex);
. . . . . .
} }
semaphore mutex = 1; // Shared variable
fork(proc_0, 0); fork(proc_1, 0);
V(s):[s = s + 1]
P(s):[while(s==0)
{wait};
s = s - 1]
" Assume Following Values:
# balance = 200
# amount = 50 amount = 75
" What are Possible Results?
" Is there a Lost Update?
6.117
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
proc_0() { proc_1() {
. . . . . .
/* Enter the CS */ /* Enter the CS */
P(mutex); P(mutex);
balance += amount; balance -= amount;
V(mutex); V(mutex);
. . . . . .
} }
V(s):[s = s + 1]
P(s):[while(s==0) {wait};s=s-1]
balance = 200
amount = 50
amount = 75
! proc_0 Executes P First
! If proc_0 Interrupted Waits proc_1
! Eventually proc_0 Resumes
balance = 250
! proc_0 Executes V
! proc_1 Executes P Sets balance =
175
! proc_1 Executes V
! proc_1 Executes P First
! If proc_1 Interrupted proc_0 Waits
! Eventually proc_1 Resumes
balance = 125
! proc_1 Executes V
! proc_0 Executes P Sets balance =
175
! proc_0 Executes V
6.118
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Critical Section for n Processes
Easier
than the
bakery
algorithm!
6.119
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Counting semaphore
! The concept of semaphore can be extended to the case where n
tasks can simultaneously access a resource controlled by the
semaphore
! The initial value of the counter S0 determines the number of tasks
which will be able to cross the semaphore before being blocked
(number of tasks which can access simultaneously the critical
section)
" To use a resource, wait()
" To release a resource, signal()

6.120
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
An analogy
! Paula and Victor work in a restaurant:
! Paula handles customer arrivals:
" Prevents people from entering the restaurant when all tables are busy.
! Victor handles departures:
" Noties people waiting for a table when one becomes available
6.121
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
An analogy (II)
! The semaphore represents the number of available tables
" Initialized with the total number of tables in restaurant
6.122
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
An analogy (III)
Paula
Victor
Bar
6.123
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
An analogy (IV)
! When people come to the restaurant, they wait for Paula to direct them:
" If a table is available, she let them in and decrements the table count
" Otherwise, she directs them to the bar
6.124
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
An analogy (V)
Paula
Victor
Bar
X
X
X X
6.125
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
An analogy (VI)
! When people leave, they tell Victor:
" Victor increments the semaphore and checks the waiting area:
" If there is anyone in there, he lets one group in and decrements the
semaphore
! Paula and Victor have worked long enough together and don't interfere with
each other
6.126
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Sempahore usage
! Counting semaphores are often used to control access to a number of similar
resources, such as disks, tape drives, CDs, etc.
" We may have 8 disks available for allocation to processes and a counting
semaphore keeps track of the number remaining to allocate (if any).
! A semaphore is typically initialized to the number of resources available
" Wait() decrements the semaphore; Signal() increments the semaphore.
Presumably, if the value of the semaphore is acceptable, the process enters its
critical section.
" If count goes to 0, then no more of these resources are available and the
requesting process will likely block until the semaphore becomes greater than 0.
6.127
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Jackson Francomme, Gilles Mercier 127
Shareable resource Example
T1
T2
R
A
M
1
R
A
M
3
R
A
M
2
Print = 3
Requte
Requte
Accs
Request Request
Access
6.128
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Counting semaphores
6.129
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Synchronization with Semaphores (I)
! We can use semaphores for synchronizing processes in an arbitrary fashion
! enforcing order of access between two processes
" Suppose there are two processes P1 and P2, where P1 contains code
C1 and P2 contains code C2
" Want to ensure that code C1 executes before code C2
" Use semaphores to synchronize the order of execution of the two
processes
Semaphore S=0; // initial value of semaphore = 0
Process P2:

wait(S); // P() the semaphore
C2; // execute C2
Process P1:

C1; // execute C1
signal(S); // V() the semaphore
6.130
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Synchronization with Semaphores (I) (cont.)
! In the previous example there are two cases:
" if P1 executes rst, then
! C1 will execute rst, then P1 will V() the semaphore, increasing its
value to 1
! Later, when P2 executes, it will call wait(S), which will decrement the
semaphore to 0 followed by execution of C2
! Thus C1 executes before C2
" If P2 executes rst, then
! P2 will block on the semaphore, which is equal to 0, so that C2 will
not be executed yet
! Later, when P1 executes, it will run through C1, then V() the
semaphore
! This awakens P2, which then executes C2
! Thus C1 executes before C2.
6.131
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
First Thread 1
6.132
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
First Thread 2
6.133
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Synchronization with Semaphores (II)
proc_A {
while(TRUE) {
compute A1;
write(x);
V(s1); //signal proc_B
compute A2;
// wait for signal from proc_B
P(s2);
read(z);
}
}

semaphore s1 = 0;
semaphore s2 = 0;
proc_B {
while(TRUE) {
// wait for signal from proc_B
P(s1);
read(x);
compute B1;
write(z);
V(s2); //signal proc_A
compute B2;
}
}

! In this case, the semaphore is used to exchange
synchronization signals among processes, as opposed to
solving the strict critical section problem.
P(s1) will not Execute
Until V(s1) sets s1 to 1
x Written Before Read
P(s2) will not Execute
Until V(s2) sets s2 to 1
y Written Before Read
6.134
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Exercise 2
! 2 processes execute concurrently, P1 and P2
! Part1 in P1 and Part2 in P2 can be done in either order
! Part3 in P1 can only be done after Part2 (in P2) is nished.
P1 P2

Part1 Part2

Part3
concurrent
precedes
6.135
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Synchronization
P1 P2

Part1 Part2

Part3
concurrent
precedes
Wait(s)
Signal(s)
If P2 gets the CPU rst, the s semaphore will get the value 1.
Thus, when P1 gets the CPU it will not be stopped by the
wait( ) call.
semaphore s = 0
6.136
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Three processes P1; P2; P3

semaphores s1 = 1, s2 = 0;

P(s1); P(s2); P(s2);


A B C
V(s2); V(s2); V(s1);


Which execution orderings of A, B, C, are possible?
Exercise 2
P1 P2 P3
6.137
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Solution
Three processes P1; P2; P3

semaphores s1 = 1, s2 = 0;

P(s1); P(s2); P(s2);


A B C
V(s2); V(s2); V(s1);


Which execution orderings of A, B, C, are possible?
( [(AC)*] A ) B* C)*
P*: means that P is executed at least once and at the most many times
[P]: means that P could not be executed.
P1 P2 P3
6.138
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Exercise 3
! There are three processes, each produces balls of some
color (e.g. Red, Green, Blue)
! Sequencing required:
" Red ball followed by Green followed by Blue and so-
on.
6.139
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Solution
! Solution:
!"#$%&'(" *+ , +-
!"#$%&'(" *. , /-
!"#$%&'(" *0 , /-

1('2"34(" 56789":"($;'(<=
>
3'
>
?$@;<*+=-

A":"($;"<5"3B$CC=-

*@A:$C<*.=
D
?&@C" <;(4"=-
D

1('2"34(" 9566E89":"($;'(<=
>
3'
>
?$@;<*.=-

A":"($;"<9("":B$CC=-

*@A:$C<*0=
D
?&@C" <;(4"=-
D

1('2"34(" BFG689":"($;'(<=
>
3'
>
?$@;<*0=-

A":"($;"<BC4"B$CC=-

*@A:$C<*+=
D
?&@C" <;(4"=-
D

6.140
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Semaphore Implementation
! The main disadvantage of previous mutual-
exclusion solution is the busy waiting (CPU is
wasting).
! This type of semaphore is called a spinlock.
! To overcome this, we can use the concept of
block and wakeup operations.

Typedef struc {
int value;
struct process *list;
} semaphore
6.141
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Semaphore Implementation with no Busy waiting
! With each semaphore there is an associated waiting queue. Each
entry in a waiting queue has two data items:
" value (of type integer)
" pointer to next record in the list
! Two operations:
" block place the process invoking the operation on the
appropriate waiting queue.
" wakeup remove one of processes in the waiting queue and
place it in the ready queue (using a FIFO policy).

6.142
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Semaphore Implementation with no Busy waiting
! Implementation of wait:
wait (semaphore *S) {
S->value--;
if (S->value < 0) {
add this process to S->list;
block();
}
}

6.143
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Semaphore Implementation with no Busy waiting
! Note that the semaphore value may be negative.
! Its magnitude is the number of processes waiting on that
semaphore.
! The list of waiting processes can be easily implemented
by a link eld in each process control block (PCB).
6.144
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Semaphore Implementation with no Busy waiting
! Implementation of signal:
signal (semaphore *S) {
S->value++;
if (S->value <= 0) {
remove a process P from S->list;
wakeup(P);
}
}
6.145
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
P and V Must Be Indivisible
! Semaphore operations must be indivisible, or atomic.
" Once OS begins either a P or V operation, it cannot be interrupted until it is
completed.
" P operation must be indivisible; otherwise there is no guarantee that two
processes wont try to test P at the same time and both nd it equal to 1.
! P(S): if S > = 1 then S = S 1#
else block the process on S queue
" Two V operations executed at the same time could unblock two processes,
leading to two processes in their critical sections concurrently.
! V(S): if some processes are blocked on the#
queue for S then unblock a process
else S = S + 1
Semaphores: observations, I.
! What does S.count represent?
" if S.count >=0: the number of processes that can execute
wait(S) without being blocked = S.count (not > 1 for mutual
exclusion)
" if S.count<0: the number of processes waiting on S is = |S.count|
! Atomicity and mutual exclusion: no 2 process can be in wait(S) or
signal(S) (on the same S) at the same time (even with multiple
CPUs)
! The order in which processes are awakened depends on the CPU
scheduling algorithm (not always FCFS)
! Hence the blocks of code dening wait(S) and signal(S) are, in fact,
critical sections.
Semaphores: observations, II.
! The critical sections dened by wait(S) and signal(S) are very short:
typically 10 instructions
! Solutions:
" uniprocessor: disable interrupts during these operations (ie: for a very
short period). This does not work on a multiprocessor machine.
" multiprocessor: use previous software or hardware schemes. The
amount of busy waiting should be small.
6.148
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
8-148
Semaphores
! Advantages
" OS guarantees that Wait and Signal are atomic
" Programmer does not need to worry about interleaving within the entry
and exit sections.
" No spin locks
" Semaphores are machine-independent
" They are simple but very general
" They work with any number of processes
" We can have as many critical regions as we want by assigning a
different semaphore to each critical region
! OS designer must use the features of the hardware to provide semaphores.
6.149
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Semaphores
P(s) /* wait(s) */
{
if (s>0) s--;
else{
queue the process on s,
change its state to blocked,
schedule another process
}
}
V(s) /* signal(s) */
{
if (s==0 && queue is not empty){
pick a process from the queue on s,
change its state from blocked to ready;
}
else s++;
}
There is a wait-queue associated with each semaphore.
s
6.150
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Process States
running ready
ready_queue
time-out
dispatch
running ready
6.151
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Process States
running ready
ready_queue
time-out
dispatch
ready
blocked
wait(si)
wait-queues
s1 sn
. . .
. . .
. . .
running
6.152
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Process States
running ready
ready_queue
time-out
dispatch
ready
blocked
wait(si)
wait-queues
s1 sn
. . .
. . .
. . .
6.153
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Process States
running ready
ready_queue
time-out
dispatch
ready
blocked
wait(si)
wait-queues
s1 sn
. . .
. . .
. . .
A running process calls signal(si).
running
signal(si)
6.154
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Process 4 Process 3 Process 2 Process 1
s
Semaphores
There is a wait-queue
associated with each
semaphore.
s
P(s)
CS1
V(s)
Program1
P(s)
CS2
V(s)
Program2
P(s)
CS3
V(s)
Program3
P(s)
CS4
V(s)
Program4
s = 2
6.155
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Process 4 Process 3 Process 2 Process 1
s
Semaphores
P(s)
CS1
V(s)
Program1
P(s)
CS2
V(s)
Program2
P(s)
CS3
V(s)
Program3
P(s)
CS4
V(s)
Program4
P(s)
s = 1
6.156
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Process 4 Process 3 Process 2 Process 1
s
Semaphores
P(s)
CS1
V(s)
Program1
P(s)
CS2
V(s)
Program2
P(s)
CS3
V(s)
Program3
P(s)
CS4
V(s)
Program4 Program2
s = 0
6.157
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Process 4 Process 3 Process 2 Process 1
s
Semaphores
P(s)
CS1
V(s)
Program1
P(s)
CS2
V(s)
Program2
P(s)
CS3
V(s)
Program3
P(s)
CS4
V(s)
Program4
Process 3
s = -1
6.158
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Process 4 Process 3 Process 2 Process 1
s
Semaphores
P(s)
CS1
V(s)
Program1
P(s)
CS2
V(s)
Program2
P(s)
CS3
V(s)
Program3
P(s)
CS4
V(s)
Program4
Process 3
Process 3
Process 4
s = -2
6.159
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Process 4 Process 3 Process 2 Process 1
s
Semaphores
P(s)
CS1
V(s)
Program1
P(s)
CS2
V(s)
Program2
P(s)
CS3
V(s)
Program3
P(s)
CS4
V(s)
Program4
Process 4
s = -1
6.160
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Process 4 Process 3 Process 2 Process 1
s
Semaphores
P(s)
CS1
V(s)
Program1
P(s)
CS2
V(s)
Program2
P(s)
CS3
V(s)
Program3
P(s)
CS4
V(s)
Program4
Process 4
s = 0
6.161
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Process 4 Process 3 Process 2 Process 1
s
Semaphores
P(s)
CS1
V(s)
Program1
P(s)
CS2
V(s)
Program2
P(s)
CS3
V(s)
Program3
P(s)
CS4
V(s)
Program4
s = 1
6.162
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Process 4 Process 3 Process 2 Process 1
s
Semaphores
P(s)
CS1
V(s)
Program1
P(s)
CS2
V(s)
Program2
P(s)
CS3
V(s)
Program3
P(s)
CS4
V(s)
Program4
CS4
s = 2
6.163
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
State transition diagram
! The state transition diagram for a job in an operating system that provides a
semaphore
New state: waiting
for a semaphore
6.164
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Deadlock
! Semaphores provide synchronization, but can introduce more complicated
higher level problems like deadlock
" two processes deadlock when each wants a resource that has been
locked by the other process
" e.g. P1 wants resource R2 locked by process P2 with semaphore S2,
while P2 wants resource R1 locked by process P1 with semaphore S1
6.165
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Deadlock
! Deadlock two or more processes are waiting indenitely for an event (a signal
operation) that can be caused by only one of the waiting processes
! Let S and Q be two semaphores initialized to 1
! If P0 waits on S and P1 waits on Q, simultaneously, then if P0 waits on Q, it will wait
indenitely for P1 to signal Q
! Sequence 1, 2, 3, 4 causes deadlock
! But sequence 1, 3, 2, 4 will not deadlock.
P0
wait(S);
wait(Q);
CS
signal(S);
signal(Q);

P1
wait(Q);
wait(S);
CS
signal(Q);
signal(S);

1
3
2
4
6.166
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Deadlock
! In the previous example,
" Each process will sleep on the other processs semaphore
" the signal() signalling statements will never get executed, so there is no
way to wake up the two processes from within those two processes
" there is no rule prohibiting an application programmer from wait()ing Q
before S, or vice versa - the application programmer wont have
enough information to decide on the proper order
" in general, with N processes sharing N semaphores, the potential for
deadlock grows.
6.167
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Setting up a rendezvous (I)
! To force two processes to wait for each other, we need two semaphores
both initialized at 0
semaphore waitforfirst = 0;
semaphore waitforsecond = 0;
6.168
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Setting up a rendezvous (II)
! When the rst process is ready, it will do
V(&waitforfirst);
P(&waitforsecond);
! When the second process is ready, it will do
V(&waitforsecond);
P(&waitforfirst);
6.169
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Setting up a rendezvous (III)
! What will happen if the rst process does
P(&waitforsecond);
V(&waitforfirst);
and the second process does
P(&waitforfirst);
V(&waitforsecond);


! We will have a deadlock

6.170
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Weakness of Semaphores
! Semaphores provide a convenient and effective mechanism for process
synchronization.
! However, incorrect use may result in timing errors.


...
critical section
...
signal(mutex);
signal(mutex);
...
critical section
...
wait(mutex);
wait(mutex);
...
critical section
...
wait(mutex);
wait(mutex);
...
critical section
...

incorrect order
(not mutual exclusive)
typing error
(deadlock)
forgotten
6.171
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Starvation
! Starvation indenite blocking. A process may never be
removed from the semaphore queue in which it is suspended:
" waiting queues are implemented in LIFO order.
6.172
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
172
Implementation of semaphores
! Any software schemes, such as Dekkers or Petersons algorithm,
can be used to implement semaphores. However, the busy-waiting
in each of them imposes a large overhead.
! Recall that the Petersons algorithm discussed above involves
only two processes. Generalizing this algorithm for n processes
to implement general semaphores has a large overhead.
! Hardware implementation based on
! test and set instruction
! the busy-waiting in the V() and P() operations are relatively
short
! disabling interrupts
! there is no wait loop, but this approach works only on a
single processor system (1 processor, multiple processes).
6.173
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 173
Semaphores with interrupt disabling
Signal(semaphore sem)
DISABLE_INTS
sem.val++
if (sem.val <= 0) {
th = remove next
thread from sem.L
wakeup(th)
}
ENABLE_INTS
struct semaphore {
int val;
list L;
}
Wait(semaphore sem)
DISABLE_INTS
sem.val--
if (sem.val < 0){
add thread to sem.L
sleep(thread)
}
ENABLE_INTS

6.174
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
type semaphore = record
value, ag: integer;
L: list of process;
end;

0
wait(S):
repeat until test-and-set(S.flag)
if (S.value == 0) {
add this process to S.L;
sleep & S.flag=0;
}
else
{
S.value = 0;
S.flag=0;
}
Implementing a binary semaphore by TAS
signal(S):
repeat until test-and-set(S.flag)
if (queue is not empty)
{
wakeup();
/* change its state from blocked to
ready; */
}
else S.value = 1;
S.flag=0
6.175
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
type semaphore = record
value, ag: integer;
L: list of process;
end;

-3
wait(S):
repeat until test-and-set(S.flag)
S.value--;
if (S.value <= 0) {
add this process to S.L;
sleep & S.flag=0;
}
else S.flag=0
Implementing a counting semaphore by TAS
signal(S):
repeat until test-and-set(S.flag)
S.value++;
if (S.value <= 0) {
remove a process P from S.L;
wakeup(P);
}
S.flag=0
6.176
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
176
Implementing a counting semaphore from binary
semaphores: (Barz 1983, Hsieh 1989)
wait(S):
wait(S2);
wait(S1);
S.value--;
if (S.value>0) then
signal(S2);
signal(S1);
signal(S):
wait(S1);
S.value++;
if(S.value == 1) {
signal(S2); }
signal(S1);
binary-semaphore S1=1, S2 = 1, value=k

6.177
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Classical Problems of Synchronization
! Consumer/Producer with Bounded-Buffer Problem
! Readers and Writers Problem
! Dining-Philosophers Problem
! The three problems are important, because they are
" examples for a large class of concurrency-control
problems.
" used for testing nearly every newly proposed
synchronization scheme.
! Semaphores are used for synchronization in our
solutions.
6.178
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Consumer/Producer with Bounded Buffer
! Two processes (at least) use a shared buffer in memory
! The buffer is nite (i.e. bounded)
! The producer writes on the buffer and the consumer
reads from it
! A full buffer stops the producer
! An empty buffer stops the consumer
producer consumer
buffer of size n
6.179
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Bounded buffer (II)
Producer
Producer
Consumer
Consumer
Consumer
Consumer
6.180
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Bounded-Buffer Problem (cont.)
! Correctness Constraints:
" Consumer must wait for producer to ll buffers, if
empty (scheduling constraint)
" Producer must wait for consumer to empty buffers, if
full (scheduling constraint)
" Only one thread can manipulate buffer queue at a
time (mutual exclusion)
! 3 Semaphores:
" mutex
" full
" empty.
6.181
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Bounded-Buffer Problem
! Shared data#
semaphore full, empty, mutex;
! Initially:
" full = 0 # of full cells
" empty = n # of empty cells
" mutex = 1
6.182
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
append(v): a function, used by
the producer, to add an item v to the
buffer in the next position (b[in])..

take():a function, used by the
consumer, to remove the next item
from the buffer (b[out]) to
prepare for consuming.

append and take are critical
sections because they use the shared
buffer.
append(v)
b[in] = v;
in = (in+1) % N;
take():
w = b[out];
out =(out+1) % N;
return w;
Bounded-Buffer Problem
6.183
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
do {
...
produce item
...
wait(empty);
wait(mutex);
...
append (item) ;
...
signal(mutex);
signal(full);
} while (1);
do {
wait(full);
wait(mutex);
...
item = take();
...
signal(mutex);
signal(empty);
...
consume the item
...
} while (1);
Producer
Bounded Buffer Problem (Cont.)
Consumer

0, iff no item
0, iff no
cells
free one
cell
add one item
6.184
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
do {
...
produce item
...
wait(empty);
wait(mutex);
...
append (item) ;
...
signal(mutex);
signal(full);
} while (1);
do {
wait(mutex);
wait(full);
...
item = take();
...
signal(mutex);
signal(empty);
...
consume the item
...
} while (1);
Producer
Bad solution
Consumer

6.185
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Order matters
! The order of the two P( ) operations is very important
" Neither the producer or the consumer should request exclusive access
to the buffer before being sure they can perform the operation they have
to perform
! The order of the two V( ) operations does not matter
6.186
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Readers-Writers Problem
Readers
Writers
6.187
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Readers-Writers Problem
Shared Resource
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Writer
Writer
Writer
Writer
Writer
Writer
Writer
Its logically acceptable for an arbitrary number of readers to access the shared resource
at the same time

but if a writer is accessing the shared resource, its unsafe to allow any other reader or
writer to access it at the same time.
6.188
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Computer Science Dept Va Tech September 2006 2006 McQuain & Ribbens
Readers-Writers Problem
Reader
Shared Resource
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Writer
Writer
Writer
Writer
Writer
Writer
Writer
Reader
Shared Resource
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Writer
Writer
Writer
Writer
Writer
Writer
Writer
OK
OK
6.189
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Readers-Writers Problem
Shared Resource
Reader
Reader
Reader
Reader
Reader
Reader
Writer
Writer
Writer
Writer
Writer
Writer
Writer Reader
Reader
Not OK
6.190
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Readers-Writers Problem
! A data set is shared among a number of concurrent processes
" Readers only read the data set; they do not perform any
updates. Many readers may access a database without fear
of data corruption (interference)
" Writers can both read and write#

! Problem allow multiple readers to read at the same time. Only


one single writer can access the shared data at the same time

Writers
W1
W2
Readers
R1
R2
Shared object,
e.g. file
Readers can share
with any other reader
but not a writer
a writer must have
exclusive access
6.191
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Readers-Writers Problem
! There can be only one writer at a time, but there can be many simultaneous
readers.
! Each writer has exclusive access.
! Options:
1. No reader will be kept waiting if there are writers waiting; readers wait
only if a writer has already obtained access permission
2. Writers have priority, start right away, temporarily blocking readers.
Once a writer is ready, that writer has to perform its write as soon as
possible, after old readers (or writer) are completed. Thus, if a writer is
waiting to access the object, no new readers may start reading.
! A solution to either problem may result in starvation.
" with reader precedence: Writers
" with writer precedence: Readers.
6.192
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Readers-Writers Problem
! Shared Data
" Data set
" Integer readcount initialized to 0 (current
number of readers)
" Semaphore mutex initialized to 1 (protect
readcount updates)
" Semaphore wrt initialized to 1 (protect
exclusion of writers)
6.193
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
A solution for the first problem
! The mutex (init =1) semaphore is used to ensure mutual
exclusion when the variable readcount is updated.
! Readcount (init =0) keeps track of how many processes
are currently reading the object.
! The wrt (init =1) semaphore functions as
" a mutual exclusion semaphore for the writers. It also
is used by the rst or last reader that enters or exits
the critical section.
" It is not used by the readers who enter or exit while
other processes are in their critical sections.
6.194
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Readers-Writers Problem #1
Writer Process
while(true) {
wait(wrt);

writing is performed

signal(wrt);
}
6.195
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Readers-Writers Problem #1
Reader Process

while(true) {
wait(mutex);
readcount++;
if (readcount == 1)
wait(wrt);
signal(mutex);

reading is performed

wait(mutex);
readcount--;
if (readcount == 0)
signal(wrt);
signal(mutex);
}
The last reader sends a
signal and, a reader or a
writer, may be scheduled
mutex protects
readcount updates
First in
mutex protects
readcount updates
6.196
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
The Readers/Writers Problem
! If multiple writers seek to write, then the write semaphore wrt provides mutual
exclusion
! If the 1st reader tries to read while a writer is writing, then the 1st reader blocks on wrt
" if subsequent readers try to read while a writer is writing, they block on mutex
! If the 1st reader reads and there are no writers, then 1st reader grabs the write lock
and continues reading, eventually releasing the write lock when done reading
" if a writer tries to write while the 1st reader is reading, then the writer blocks on
the write lock wrt
" if a 2nd or any subsequent reader tries to read while the 1st reader is reading,
then it falls through and is allowed to read.

! Readers can starve writers


! Updates can be delayed forever
! May not be what we want.
6.197
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Readers-Writers Problem (2)
! If a writer is in the CS and n readers are waiting, then
" one is queued on wrt
" the other n-1 are queued on mutex
! When a writer executes signal(wrt), either
" the waiting readers or
" a single writer are resumed. The selection is made by the scheduler.
6.198
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Readers-Writers Problem #2: writer precedence
reader() {
while(TRUE) {
<other computing>;

P(readBlock);
P(mutex1);
readCount++;
if(readCount == 1)
P(writeBlock);
V(mutex1);
V(readBlock);

access(resource);
P(mutex1);
readCount--;
if(readCount == 0)
V(writeBlock);
V(mutex1);
}
}
int readCount = 0, writeCount = 0;
semaphore mutex = 1, mutex2 = 1;
semaphore readBlock = 1, writeBlock = 1;
writer() {
while(TRUE) {
<other computing>;
P(mutex2);
writeCount++;
if(writeCount == 1)
P(readBlock);
V(mutex2);
P(writeBlock);
access(resource);
V(writeBlock);
P(mutex2)
writeCount--;
if(writeCount == 0)
V(readBlock);
V(mutex2);
}
}
6.199
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Readers-Writers Problem #2: writer precedence
reader() {
while(TRUE) {
<other computing>;

P(readBlock);
P(mutex1);
readCount++;
if(readCount == 1)
P(writeBlock);
V(mutex1);
V(readBlock);

access(resource);
P(mutex1);
readCount--;
if(readCount == 0)
V(writeBlock);
V(mutex1);
}
}
int readCount = 0, writeCount = 0;
semaphore mutex = 1, mutex2 = 1;
semaphore readBlock = 1, writeBlock = 1;
writer() {
while(TRUE) {
<other computing>;
P(mutex2);
writeCount++;
if(writeCount == 1)
P(readBlock);
V(mutex2);
P(writeBlock);
access(resource);
V(writeBlock);
P(mutex2)
writeCount--;
if(writeCount == 0)
V(readBlock);
V(mutex2);
}
}
1
2
3
First Writer does a
P(readBlock) to block
any new readers
6.200
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
reader() {
while(TRUE) {
<other computing>;

P(readBlock);
P(mutex1);
readCount++;
if(readCount == 1)
P(writeBlock);
V(mutex1);
V(readBlock);

access(resource);
P(mutex1);
readCount--;
if(readCount == 0)
V(writeBlock);
V(mutex1);
}
}
int readCount = 0, writeCount = 0;
semaphore mutex = 1, mutex2 = 1;
semaphore readBlock = 1, writeBlock = 1;
writer() {
while(TRUE) {
<other computing>;
P(mutex2);
writeCount++;
if(writeCount == 1)
P(readBlock);
V(mutex2);
P(writeBlock);
access(resource);
V(writeBlock);
P(mutex2)
writeCount--;
if(writeCount == 0)
V(readBlock);
V(mutex2);
}
}
1
2
3
Writer blocks on
P(writeBlock)
4
Next reader is blocked
because the first writer
did a P(readBlock)
Readers-Writers Problem #2: writer precedence
6.201
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
reader() {
while(TRUE) {
<other computing>;

P(readBlock);
P(mutex1);
readCount++;
if(readCount == 1)
P(writeBlock);
V(mutex1);
V(readBlock);

access(resource);
P(mutex1);
readCount--;
if(readCount == 0)
V(writeBlock);
V(mutex1);
}
}
int readCount = 0, writeCount = 0;
semaphore mutex = 1, mutex2 = 1;
semaphore readBlock = 1, writeBlock = 1;
writer() {
while(TRUE) {
<other computing>;
P(mutex2);
writeCount++;
if(writeCount == 1)
P(readBlock);
V(mutex2);
P(writeBlock);
access(resource);
V(writeBlock);
P(mutex2)
writeCount--;
if(writeCount == 0)
V(readBlock);
V(mutex2);
}
}
1
3
4
2
Last reader signals
writer to begin
Readers-Writers Problem #2: writer precedence
6.202
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
reader() {
while(TRUE) {
<other computing>;
P(writePending);
P(readBlock);
P(mutex1);
readCount++;
if(readCount == 1)
P(writeBlock);
V(mutex1);
V(readBlock);
V(writePending);
access(resource);
P(mutex1);
readCount--;
if(readCount == 0)
V(writeBlock);
V(mutex1);
}
}
int readCount = 0, writeCount = 0;
semaphore mutex = 1, mutex2 = 1;
semaphore readBlock = 1, writeBlock = 1;
writer() {
while(TRUE) {
<other computing>;
P(mutex2);
writeCount++;
if(writeCount == 1)
P(readBlock);
V(mutex2);
P(writeBlock);
access(resource);
V(writeBlock);
P(mutex2)
writeCount--;
if(writeCount == 0)
V(readBlock);
V(mutex2);
}
}
3
4
5
Any new writer
has priority over
any waiting reader
but is stuck until
first writer is finished
Any new reader must
wait until the last writer
signals
Readers-Writers Problem #2: writer precedence
6.203
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
! Any writer must wait for current readers to nish
! Any writer has priority over any new readers
! The writers can starve readers
! Reads can be delayed forever
! May not be what we want.
Readers-Writers Problem #2: writer precedence
6.204
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Dining Philosophers Problem
! Model allocating several resources among several processes.
! The Dining Philosophers Problem stated (1965) as follows.
" Five philosophers are seated around a circular table
" Five plates of foods (spaghetti in the original Dijkstra's paper ...)
" Five chopstics (forks)
" Between each pair of plates is one fork
" Philosophers spend time eating and thinking:
! Philosophers think about the world and ignore food
! When they want to eat, need two forks
! Pick up one and then another
! We want to write a program for each philosopher that does what it suppose
to do and never gets stuck (If all ve philosophers pick their left forks at the
same time, a deadlock will occur).
6.205
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
while(TRUE) {
Think();
Grab first fork;
Grab second fork;
Eat();
Put down first fork;
Put down second fork;
}
Each philosopher is
modeled with a thread
6.206
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Philosopher Process
! Shared data
" spaghetti (data set)
" Semaphore fork [5] initialized to 1
! Philosopher i:
repeat
wait( fork[ i]); // get left fork
wait( fork[ i+1 mod 5]); // right fork
...
eat
...
signal( fork[ i]); // return left fork
signal( fork[ i+1 mod 5]); // return right fork
...
think
...
until false;
6.207
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Dining Philosophers Problem
! In this algorithm, take-fork waits until the specied fork is available. The
solution is wrong because
" If all ve philosophers take their left fork simultaneously there will be
deadlock (i.e., process stay blocked forever)
! If we modify the solution by saying that after taking the left fork, the program
checks the availability of the right fork. If it is not, the philosopher puts down
the left fork , waits for some times, and repeats the process. Again if all
philosophers take their left fork simultaneously put it down and wait for the
same time these processes continue to run for ever but no progress is
made (this situation is called starvation).
6.208
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Simplest Example of Deadlock
Thread 0

P(R1)
P(R2)
V(R1)
V(R2)
Thread 1

P(R2)
P(R1)
V(R2)
V(R1)
Interleaving

P(R1)
P(R2)
P(R1) waits
P(R2) waits
R1 and R2 initially 1 (binary semaphore)
6.209
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Remedies
! Teach philosophers to eat spaghetti with 1 fork !
! Give them another fork
! Allow at most 4 philosophers at the table
! Check to see if both forks are available, then pick them up
! Use asymmetry odd philosophers pick up left rst, while even
philosophers pick up right rst
! Besides deadlock, any satisfactory solution to the DPP problem must
avoid the problem of starvation.

6.210
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Admit only 4 philosophers
! Then 1 philosopher can always eat
when the other 3 are holding 1 fork
! Hence, we can use another semaphore
T that would limit at 4 the number of
philosophers sitting at the table
Process Pi:
repeat
think;
wait(T);
wait(fork[i]);
wait(fork[i+1 mod 5]);
eat;
signal(fork[i+1 mod 5]);
signal(fork[i]);
signal(T);
forever

6.211
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Working towards a solution
#define N 5

Philosopher() {
while(TRUE) {
Think();
take_fork(i);
take_fork((i+1)% N);
Eat();
put_fork(i);
put_fork((i+1)% N);
}
}
take_forks(i)
put_forks(i)
6.212
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Working towards a solution
#define N 5

Philosopher() {
while(TRUE) {
Think();
take_forks(i);
Eat();
put_forks(i);
}
}
6.213
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Picking up forks
// only called with mutex set!

test(int i) {
if (state[i] == HUNGRY &&
state[LEFT] != EATING &&
state[RIGHT] != EATING){
state[i] = EATING;
signal(sem[i]);
}
}
int state[N]
semaphore mutex = 1
semaphore sem[i]

take_forks(int i) {
wait(mutex);
state [i] = HUNGRY;
test(i);
signal(mutex);
wait(sem[i]);
}
0
0 0 0 0 0
initial values
6.214
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Putting down forks
// only called with mutex set!

test(int i) {
if (state[i] == HUNGRY &&
state[LEFT] != EATING &&
state[RIGHT] != EATING){
state[i] = EATING;
signal(sem[i]);
}
}
int state[N]
semaphore mutex = 1
semaphore sem[i]

put_forks(int i) {
wait(mutex);
state [i] = THINKING;
test(LEFT);
test(RIGHT);
signal(mutex);
}
6.215
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Sleepy Barber Problem
! Finite capacity of shop - nite waiting queue
! One customer is served at one time
! Service provider, barber, sleeps when no customers are waiting, if Barber
Asleep, Arriving Customer Wakes Him.
! Customers Wait in a Waiting Room
! Customer leaves if shop is full
Exit
Entrance
Customers
Barbers Chair
Waiting Room
6.216
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
The sleeping barber
#dene CHAIRS5
semaphore customers = 0;
semaphore barbers = 0;
semaphore mutex = 1;
int waiting = 0;

void barber(void){
while(TRUE) {
wait(customers); /* block if no customers */
wait(mutex); /* access to waiting */
waiting = waiting - 1;
signal(barbers); /* barber is in.. */
signal(mutex); /* release waiting */
cut_hair();
}
}
6.217
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
The sleeping barber
void customer(void)
{#
wait(mutex); /* enter CS */
if(waiting < CHAIRS) {#
waiting = waiting + 1; /* increment waiting */
signal(customers); /* wake up barber */
signal(mutex); /* release waiting */
wait(barbers); /* block for 0 barbers */
get_haircut();
}
else {#
signal(mutex); /* shop full .. leave */
}#
}
6.218
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Monitors
! Introduced by Hoare (1974) and Brinch-Hansen (1975)
! Programming language construct that supports controlled access to shared data
" Compiler adds synchronization automatically
" Enforced at runtime
! Encapsulates
" Shared data structures
" Procedures/functions that operate on the data
" Synchronization between processes calling those procedures
! Only one process active inside a monitor at any instant
" All procedures are part of critical section

Hoare, C.A.R., Monitors: An Operating System


Structuring Concept, Communications of ACM, vol.
17, pp. 549-557, Oct. 1974
Brinch-Hansen, P. "The Architecture of Concurrent
Programming", Prentice Hall, 1975

6.219
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Monitors
! Monitors are a high level language construct for dealing with
synchronization
" similar to classes in Java
" a monitor has elds and methods
! Programmer only has to say what to protect
! Compiler actually does the protection
" compiler will use semaphores to do protection
! Found in many concurrent programming languages
! Concurrent Pascal, Modula-3, Java...
! Now supported by libraries also
! Can be implemented by semaphores...
6.220
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Monitors
! Is a software module containing:
" one or more procedures
" an initialization sequence
" local data variables
! Keys to monitor correctness
" Data is available only to functions within monitor
" Specic functions (gatekeepers) control access
" Only one process/thread allowed inside monitor at a time
" Queues keep track of who is waiting for monitor
6.221
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Monitors
monitor monitor-name
{
// shared variable declarations
procedure P1 () { . }

procedure Pn () {}

Initialization code ( .) { }

}
}
6.222
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
monitor mon {
int foo;
int bar;
double arr[100];
void proc1() {
}
void proc2() {
}
void mon() { // initialization code
}
};
Monitor usage
! This looks like C++ code, but its not supported by C++
! Provides the following features:
" Variables foo, bar, and arr are accessible only by proc1 and proc2
" Only one process can be executing in either proc1 or proc2 at any time
6.223
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
shared data
operations (procedures)
at most one
process in monitor
at a time
entry queue
inizialization code
Schematic view of a monitor
6.224
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Monitors
! Mutual exclusion
" only one process can be executing inside at any time
" if a second process tries to enter a monitor procedure, it blocks until the
rst has left the monitor
! The monitor ensures mutual exclusion: no need to program this constraint
explicitly
" Hence, shared data are protected by placing them in the monitor
! The monitor locks the shared data on process entry
! Once inside a monitor, process may discover it is not able to continue.
6.225
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Condition variables in monitors
! Problem: how can a process wait inside a monitor?
" Cant simply sleep: theres no way for anyone else to enter
" Solution: use a condition variable
! Condition variables support two operations
" Wait(): suspend this process until signaled
" Signal(): wake up exactly one process waiting on this condition
variable
! If no process is waiting, signal has no effect
! Signals on condition variables arent saved up
! Condition variables are only usable within monitors
" Process must be in monitor to signal on a condition variable
6.226
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Monitor with Condition Variables
condition x, y;
Two operations on a condition variable:
x.wait () means that the process
invoking this operation is suspended until
another process invokes
x.signal () The signal operation resumes
exactly one suspended process. If no
process is suspended, then the signal
operation has no effect.
6.227
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Monitor semantics
! Problem: P signals on condition variable X, waking Q
" Both cant be active in the monitor at the same time !
" Which one continues rst?
! Mesa-Brinch Hansen semantics (most OSs): signal and continue
" Signaling process (P) continues rst
" Q resumes when P leaves the monitor
" Seems more logical: why suspend P when it signals?
! Hoare semantics (most textbooks): signal and wait
" Awakened process (Q) continues rst
" P resumes when Q leaves the monitor
" May be better: condition that Q wanted may no longer hold when P
leaves the monitor
6.228
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Condition Variables
! Two ways to implement condition variables
" Hoares semantics
! p
1
does a wait
! p
0
signals
! p
0
is immediately suspended, p
1
is immediately resumed
! when p
1
nishes and leaves the monitor, p
0
continues
" Brinch Hansens semantics
! p
1
does a wait
! p
0
signals
! p
0
continues to execute, nishes and leaves the monitor
! p
1
can receive the signal.
6.229
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Conditional wait
! If several processes are suspended on condition x, and a signal x.signal()
operation is executed by some process, then how do we determine which of
the suspended processes should be resumed next?
! One simple solution is to use an FCFS ordering.
! In some cases this is not adequate. For this purpose, the conditional-wait
construct can be used.
! x.wait(c);
" where c is a number, called a priority number, and it is stored with the
name of the process that is suspended
" when x.signal() is executed, the process with the smallest priority
number is resumed next.
6.230
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
A Monitor to Allocate Single Resource
! Each process, when requesting an allocation of a critical resource, species the
maximum time it plans to use the resource.
! The monitor allocates the resource to the process that has the shortest time-
allocation request.
monitor ResourceAllocation
{
boolean busy;
condition x;

void acquire(int time) {
if (busy)
x.wait(time);
busy = true;
}

void release() {
busy = false;
x.signal();
}

void init() {
busy = false;
}
}
6.231
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Calling Resource Allocation
ResourceAllocation R

[fork several processes]

[in each process:]

R.acquire(t)

access the resource

R.release();


6.232
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Examples
! Bounded Buffer Producer Consumer
! Dining Philosophers
! Reader/Writers.
6.233
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Producer/Consumer problem
ProducerI:
repeat
produce v;
Append(v);
forever

ConsumerI:
repeat
Take(v);
consume v;
forever

! Two types of processes:
" producers
" consumers
! Synchronization is now conned
within the monitor
! append(v) and take(v) are
procedures within the monitor: they
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.
6.234
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
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:
! cwait(notfull): indicates that the buffer is full
! csignal(notfull) indicates that the buffer is not full
" notempty:
! cwait(notempty): indicates that the buffer is empty
! csignal(notempty) indicates that the buffer is not empty
! needs buffer pointers and counts:
" nextin: points to next item to be appended
" nextout: points to next item to be taken
" count: holds the number of items in buffer
6.235
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Monitor for the bounded P/C problem
Monitor 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);

6.236
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Dining Philosophers
! Dene the state of each philosopher:
" enum {thinking, hungry, eating} state[5];
" State[i] = eating only if neighbours not eating
! Dene a means for a philosopher to delay eating:
" condition self[5];
! each philosopher has a condition variable which tells
him whether he waits for the second fork
! Protect the whole with monitor DP
" include state[i] and condition variable self[i]
" include pickup, putdown, test and init
6.237
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Dining Philosophers Monitor
monitor dp
{
enum {thinking, hungry, eating} state[5];
condition self[5];

void pickup(int i) // following slide
void putdown(int i) // following slide
void test(int i) // following slide

void init() {
for (int i = 0; i < 5; i++)
state[i] = thinking;
}
}
6.238
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Dining Actions
void pickup(int i) {
state[i] = hungry;
test(i); // if neighbors are not eating, set own state to eating
if (state[i] != eating)
self[i].wait(); // test showed a neighbor was eating - wait
}

void putdown(int i) {
state[i] = thinking;
// test left and right neighbours gives them chance to eat
test((i+4) % 5); // signal left neighbor if she is hungry
test((i+1) % 5); // signal right neighbor if she is hungry
}

void test(int i) {
if ( (state[(i + 4) % 5] != eating) &&
(state[i] == hungry) &&
(state[(i + 1) % 5] != eating)) {
state[i] = eating;
self[i].signal();
}
}

6.239
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Dining Philosophers
dp.init
[fork five processes]

[in the ith process]
while(1)
{
dp.pickup(i) //simply calling monitor proc
// invokes mutual exclusion
eat // automatically

dp.putdown(i)
}
}
But if the neighbours never put down their forks, a
philosopher could starve!
6.240
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Readers-Writers
reader() {
while(TRUE) {

rw.startRead();
[read the resource]
rw.finishRead();

}
}
writer() {
while(TRUE) {

rw.startWrite();
[read the resource]
rw.finishWrite();

}
}
6.241
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Readers- Writers
monitor reader_writer
{
int numberOfReaders = 0;
boolean busy = FALSE;
condition okToRead, okToWrite;

public:
startread {
if (busy || (okToWrite.queue)) okToRead.wait;
numberOfReaders++;
okayToRead.signal;
};
finishRead {
numberOfReaders--;
if (numberOfReaders == 0) okToWrite.signal;
}
startWrite {
if ((numberOfReaders != 0) || busy) okToWrite.wait;
busy = TRUE;
}
finishWrite {
busy = FALSE;
if (okToWrite.queue)
okToWrite.signal
else
okToRead.signal;
}
}
Returns TRUE if at least
one process is suspended.
6.242
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Monitor Implementation Using Semaphores
! Variables
semaphore mutex; // (initially = 1) for mutual exclusion on entry
semaphore next; // (initially = 0) signaler waits on this
int next-count = 0; // # processes (signalers) suspended on next

! // Entering the monitor:
Each external procedure F will be replaced by (ie., put in monitor as):
wait(mutex); // block if the monitor is occupied

body of F; // same as a critical section
...
// exiting the monitor:
if (next-count > 0) // Counts the number of variables suspended on next
signal(next)
else
signal(mutex); // then let in any new guys
// Above is the overall monitor:
! Mutual exclusion within a monitor is ensured.
6.243
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Monitor Implementation
! For each condition variable x, we have:
semaphore x-sem; // (initially = 0) causes a wait on x to block
int x-count = 0; // number of processes waiting on CV x

! The operation x.wait can be implemented as:

x-count++;
if (next-count > 0) // any signalers queued up?
signal(next); // release a waiting signaler rst
else
signal(mutex); //else let a new guy in
wait(x-sem); // unconditionally block on the CV
x-count--; // Im outa here

6.244
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Monitor Implementation
! The operation x.signal can be implemented as:

if (x-count > 0) { //do nothing if nobody is waiting on the CV


next-count++; // I am (a signaler) gonna be suspended on next
signal(x-sem); // release a process suspended on the CV
wait(next); // get out of the way of the released process (Hoare)
next-count--; // released process done & it signaled me in
}

6.245
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Drawbacks of monitors
! If a monitor encapsulates the resource, concurrent access to the resource is
lost
" To allow concurrent access to the resource, the resource must be
separated from the monitor
! Nested monitor calls may cause deadlocks.
" Suppose a thread calls a monitor procedure that in turn calls another
lower level monitor procedure.
" If a wait is executed in the lower level monitor, the control of the lower
level monitor is relinquished, but not the control of the higher level
monitor.
" Since the higher level monitor is still being occupied, no other thread is
allowed to enter the higher level monitor and subsequently sends a
signal to the lower level monitor.
6.246
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Synchronization Examples
! Linux
! Pthreads
6.247
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Linux Synchronization
! Linux:
" Prior to kernel Version 2.6, disables interrupts to implement short critical
sections
" Version 2.6 and later, fully preemptive
! Linux provides:
" atomic operations
" spin locks
" semaphores
6.248
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Atomic Operations
! Atomic operations provide instructions that are executable atomically;
without interruption
! It is impossible for two atomic operations to occur on the same variable
concurrently
! The kernel provides two sets of interfaces for atomic operations: one for
integers and another for individual bits.
6.249
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Atomic operations: integers
! Atomic_t type: 24-bit atomic counter
! Can be used to implement counters incremented by more than one thread
! Example:
atomic_t v; /* define v */
atomic_t u = ATOMIC_INIT(0); /* define u and initialize it to zero */
atomic_set(&v, 4); /* v = 4 (atomically) */
atomic_add(2, &v); /* v = v + 2 = 6 (atomically) */
atomic_inc(&v); /* v = v + 1 = 7 (atomically) */
int x = atomic_read( atomic_ t *v) /* Read the integer value of v */
Function Description
atomic_read(v)
atomic_set(v,i)
atomic_add(i,v)
atomic_sub(i,v)
atomic_sub_and_test(i,v)
atomic_inc(v)
atomic_dec(v)
atomic_dec_and_test(v)
atomic_inc_and_test(v)
atomic_add_negative(i,v)
Return *v#
set *v to i#
add i to *v#
subtract i from *v#
subtract i from *v and return 1 if result is 0#
add 1 to *v#
subtract 1 from *v#
subtract 1 from *v and return 1 if result is 0#
add 1 to *v and return 1 if result is 0#
add i to *v and return 1 if result is negative
6.250
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Atomic Bit Handling Functions
! Operate at the bit level
! Example:
unsigned long word = 0;
set_bit(0, &word); /* bit zero is now set (atomically) */
set_bit(1, &word); /* bit one is now set (atomically) */
clear_bit(1, &word); /* bit one is now unset (atomically) */
change_bit(0, &word); /* bit zero is ipped; now it is unset (atomically) */
/* atomically sets bit zero and returns the previous value (zero) */
if (test_and_set_bit(0, &word))
{ /* never true */ }
Function Description
test_bit(nr, addr)
set_bit(nr, addr)
clear_bit(nr, addr)
change_bit(nr, addr)
test_and_set_bit(nr, addr)
test_and_clear_bit(nr, addr)
test_and_change_bit(nr, addr)
atomic_clear_mask(mask, addr)
atomic_set_mask(mask, addr)
return the nr-th bit of *addr
set the nr-th bit of *addr
clear the nr-th bit of *addr
invert the nr-th bit of *addr
set nr-th bit of *addr and return old value#
clear nr-th bit of *addr and return old value
invert nr-th bit of *addr and return old value#
clear all bits of addr specied by mask#
set all bits of addr specied by mask
6.251
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Atomic Integer Operations
! Uses atomic_t data type
! Can be used to implement counters incremented by more than one thread
! Operations include:
atomic_t v; /* define v */
atomic_t u = ATOMIC_INIT(0); /* define u and initialize it to zero */
atomic_set(&v, 4); /* v = 4 (atomically) */
atomic_add(2, &v); /* v = v + 2 = 6 (atomically) */
atomic_inc(&v); /* v = v + 1 = 7 (atomically) */
int x = atomic_read( atomic_ t *v) /* Read the integer value of v */


6.252
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Atomic Bitwise Operations
! Operate at the bit level
! Example
unsigned long word = 0;
set_bit(0, &word); /* bit zero is now set (atomically) */
set_bit(1, &word); /* bit one is now set (atomically) */ printk("%ul\n", word); /* will print "3" */
clear_bit(1, &word); /* bit one is now unset (atomically) */
change_bit(0, &word); /* bit zero is ipped; now it is unset (atomically) */
/* atomically sets bit zero and returns the previous value (zero) */
if (test_and_set_bit(0, &word))
{ /* never true */ }
6.253
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Spin Locks
! A spin lock can be held by at most one thread of execution
! Scenario:
" A thread attempts to acquire a spin lock
" If the spin lock is already held by a different thread, this thread busy loops (spins)
waiting for the lock to become available
" If the spin lock is not held, the thread acquires the lock and enters the critical
region
! Spinlocks are most effective in situations where the wait time for acquiring a lock is
expected to be very short, say on the order of less than 2 context switching.
6.254
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Spin Locks
! Designed to work in a multiprocessor environment
" Busy waiting
" Represented by spinlock_t structure
! lock:
1 unlocked
<=0 - locked
6.255
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Spin Lock Macros
6.256
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Spin Lock Macros
! Example:
spinlock_t mr_lock = SPIN_LOCK_UNLOCKED; //0 initially
spin_lock(&mr_lock);
/* critical region */
spin_unlock(&mr_lock);
6.257
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Warning!
! If you attempt to acquired a lock that you already hold
" You will spin; waiting for yourself to release the lock
" As you are busy spinning, you will never release the lock
" Hence, a deadlock occurs!
6.258
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Disable Interrupts!
! If you want to disable interrupts
spinlock_t mr_lock = SPIN_LOCK_UNLOCKED;
spin_lock_irq(&mr_lock);
//Disables the interrupts and acquires the lock
/* critical section ... */
spin_unlock_irq(&mr_lock);
//Unlocks and enables the interrupts
! But If the interrupts were initially disabled, you made a mess!
6.259
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Disable Interrupts!
! So you need to save the state of the interrupts and acquire your lock!
spinlock_t mr_lock = SPIN_LOCK_UNLOCKED;
unsigned long flags;
spin_lock_irqsave(&mr_lock, flags);
//Saves the current state of interrupts, disables them and obtains the lock
/* critical region ... */
spin_unlock_irqrestore(&mr_lock, flags);
//Unlocks and returns the interrupts to their previous state
! If interrupts were initially disabled, they will remain disabled
6.260
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Reader-Writer Spin Locks
! Threads can be divided into readers and writers
! When a list is updated (written to), no other thread should concurrently write to or
read from that list
! When a list is searched (read from), nothing else should write to that list, but
something else can read
! You can have multiple readers as there are no writers
! Linux provides reader-writer spin locks
6.261
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Reader-Writer Spin Locks (Cont.)
! Reader locks
" One or more readers can hold a reader lock
" Provide shared access to some region
! Writer locks
" Only one writer can hold a writer lock, without any readers
" Provide exclusive access to some region
6.262
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Usage
! Represented by the rwlock_t data structure
! The RW_LOCK_UNLOCKED macro initializes a read-write lock to 0
! Reader lock
read_lock(&mr_rwlock);
/* critical section (read only) ... */
read_unlock(&mr_rwlock);
6.263
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Usage (Cont.)
! Writer lock
write_lock(&mr_rwlock);
/* critical section (read and write) ... */
write_unlock(&mr_lock);
! In UML, locks are defined in linux/kernel/spinlock.c
6.264
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Semaphores in Linux
! Semaphore functions:
#include <sys/sem.h>
int semctl(int sem_id, int sem_num, int command, );
int semget(key_t key, int num_sems, int sem_flags);
int semop(int sem_id, struct sembuf *sem_ops, size_t
num_sem_ops);
6.265
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
semget()
int semget(key_t key, int num_sems, int sem_flags);
! The Unix semaphore variables are more complex than those invented by
Dijkstra.
! The function semget() allows to access an array of semaphores
" Can also create it if it did not exist.
6.266
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
semget()
! int semget(key, nsems, flags)
" key is semaphore array key
" nsems is number of semaphores in array
" flags is a set of ORed ags among which
! the semaphore protection bits
! IPC_CREAT ag#
species that semaphore should be created if it did not exist yet
! semget() returns semaphore id of array
! Initial value of semaphores in the array is zero
! When the IPC_CREAT ag is set
" The rst process accessing the semaphore array will create it
" The other processes will get the newly created semaphore array
6.267
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Jackson Francomme, Gilles Mercier 267
semget()
! The return of this function is the identier, that is the number which allows
the processes to act on the set of semaphore variables.
! The creation of a semaphore variable is done in the following manner:$
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semid;/* semaphore set ID */
/*creating a set having only one semaphore variable */
if((semid = semget (IPC_PRIVATE |0x666 ))== -1)
{printf("Semaphore creation error \n") ;
exit (-1);}
! at the moment of creation the semaphore is initialized with the value 0
6.268
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
semop()
! A process can increment, decrement or test individual semaphore elements with
the semop system call
int semop(sid, sops, nsops)
" sid is semaphore id of array
" sops points to an array of elements of type#
struct sembuf {
short sem_num;// index
short sem_op; // 1 or -1
short sem_flg; // flags
}
" nsops is the size of the sops array
! semop() species a set of nsops semaphore operations to be
performed on the elements of the semaphore sid specied by the
sem_num elds of the sops array
! semop returns 1 and sets errno on error
This is absurdly complicated!
6.269
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
struct sembuf
! struct sembuf has the following three elds
" short sem_num: The number of the semaphore element
" short sem_op: The particular operation to be performed on the
semaphore element
" shore sem_g: The ags to specify options for the operation
6.270
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
sem_op
! If sem_op > 0, semop adds the value to the corresponding semaphore element
and awakens processes waiting for semaphore element to increase
! If sem_op = 0, and semaphore element value is not 0, semop blocks the calling
process (waiting for 0) and increments the count of processes waiting for a zero
value of that element
! If sem_op < 0, semop adds the value to the corresponding semaphore element
value provided the result would not be negative. If the operation would make
the element value negative, semop blocks the process on the event that the
semaphore element value increases. If the resulting value is 0, semop wakes
the processes waiting for 0
6.271
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Example 1
struct sembuf GET_TAPES[2]
struct sembuf RELEASE_TAPES[2]

void set_sembuf_struct(struct sembuf *s, int num,
int op, int flg)
{
s->sem_num = (short) num;
s->sem_op = op;
s->sem_flg = flg;
return;
}

set_sembuf_struct (&(GET_TAPES[0]), 0,1,0);
set_sembuf_struct (&(GET_TAPES[1]), 1,1,0);
set_sembuf_struct (&(RELEASE_TAPES[0]), 0,1,0);
set_sembuf_struct (&(RELEASE_TAPES[1]), 1,1,0);

Process 1: semop(S, GET_TAPES,1);
<use tape A>
semop(S, RELEASE_TAPES,1);

Process 2: semop(S,GET_TAPES,2);
<use tapes A and B>
semop(S,RELEASE_TAPES,2);

Process 3: semop(S, GET_TAPES + 1,1);
<use tape B>
semop(S, RELEASE_TAPES + 1,1);
6.272
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
semctl()
! The function semctl() allows among other operations, to init, to read independently
the variables of a semaphore variable set.
! int semctl (int identifier, int number, int command,
union_semum attributes);
" identifier is the integer sent by semget(),
" number is the number of the semaphore set variable (starting at 0)
" command may be one of:
! GETVAL: Return the value of a specic semaphore element
! GETPID: Return process ID of last process PID of the last process having done an operation
! GETNCNT: Return number of processes waiting for element to increment
! GETZCNT:Return number of processes waiting for element to become 0
! SETVAL: Set value of a specic semaphore element
! IPC_RMID: Remove the semaphore identied by semid
! IPC_SET: Set the permissions of the semaphore
" Attributes: other parameters.
6.273
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
struct sembuf Example 1
GET_TAPES[0] RELEASE_TAPES[0]
num = 0 num = 0
op = 1 op = 1
g = 0 g = 0

GET_TAPES[1] RELEASE_TAPES[1]
num = 1 num = 1
op = 1 op = 1
g = 0 g = 0
6.274
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
POSIX Synchronization
! POSIX.1b standard was adopted in 1993
! Pthreads API is OS-independent
! It provides:
" semaphores
" mutex locks.
" condition variables
6.275
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Semaphore in POSIX
! POSIX.1b standard was adopted in 1993
! Semaphore variable is of type sem_t
! Atomic operations for initializing, incrementing and decrementing value
! Semaphore functions start with sem_
6.276
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Semaphore Operations
#include <semaphore.h>
int sem_init (sem_t *sem, int pshared, unsigned int value);
int sem_destroy (sem_t *sem);
int sem_wait (sem_t *sem);
int sem_try (sem_t *sem);
int sem_post (sem_t *sem);
int sem_getvalue (sem_t *sem, int *sval);
! All semaphore functions return 1 and set errno on error
! It is uncertain what semaphore functions return on success, but usually 0.
6.277
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
sem_init
int sem_init (sem_t *sem, int pshared, unsigned int value);
! Initializes semaphore to value parameter
! pshared is the type of semaphore;
" if 0, then semaphore is local to the current process ()
" else the semaphore may be shared between processes (the process
that initializes it and by children of that process)
6.278
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
sem_destroy
int sem_destroy (sem_t *sem);
! Destroys a previously initialized semaphore
! If sem_destroy attempts to destroy a semaphore that is being used by
another process, it may return 1.
6.279
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
sem_wait and sem_try
int sem_wait (sem_t *sem);
int sem_try (sem_t *sem);
! sem_wait is a standard semaphore wait operation
! If the semaphore value is 0, sem_wait blocks until it can successfully
decrement value
! sem_try is similar to sem_wait except instead of blocking on 0, it
returns 1.
6.280
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
sem_post
int sem_post (sem_t *sem);
! sem_post increments the semaphore value and is the classical semaphore
signal operation.
6.281
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
sem_getvalue
int sem_getvalue (sem_t *sem, int *sval);
! Allows the user to examine the value of a semaphore
! Sets the integer referenced by sval to the value of the semaphore
! If there are processes waiting for the semaphore, POSIX.1b allows setting
sval to either 0 or a negative number whose absolute value is equal to the
number of waiting processes
6.282
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Example 1
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

void *thread_function(void *arg);


sem_t bin_sem;

#dene WORK_SIZE 1024


char work_area[WORK_SIZE];

int main() {
int res;
pthread_t a_thread;
void *thread_result;


6.283
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Example 1
res = sem_init(&bin_sem, 0, 0);
if (res != 0) { perror("Semaphore initialization failed");
exit(EXIT_FAILURE);}
res = pthread_create(&a_thread, NULL, thread_function, NULL);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
printf("Input some text. Enter 'end' to nish\n");
while(strncmp("end", work_area, 3) != 0) {
fgets(work_area, WORK_SIZE, stdin);
sem_post(&bin_sem);
}
printf("\nWaiting for thread to nish...\n");
res = pthread_join(a_thread, &thread_result);
if (res != 0) {
perror("Thread join failed");
exit(EXIT_FAILURE);
}
6.284
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Example 1
printf("Thread joined\n");
sem_destroy(&bin_sem);
exit(EXIT_SUCCESS);
}

void *thread_function(void *arg) {


sem_wait(&bin_sem);
while(strncmp("end", work_area, 3) != 0) {
printf("You input %d characters\n", strlen(work_area) -1);
sem_wait(&bin_sem);
}
pthread_exit(NULL);
}
6.285
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
285
Solving Reader-Writer Problem
! Reader-writer problem:
" Share a buffer which holds one item (an integer)
" A single reader and writer
" Reader: only read when there is item in buffer
" Writer: only write when there is space in buffer
" How to make the writer enter the critical section rst?
" How to make the reader & writer alternate to enter critical section?
6.286
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
286
Solving Reader-Writer Problem
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
sem_t readers_turn, writers_turn; /* semaphore declaration */
int buffer, loopcnt = 5;
void * reader_function(void *)
{
int i;
for (i=0; i<loopcnt; i++) {
sem_wait( &readers_turn );
printf("reader consumes one item: %d.\n", buffer);
sem_post( &writers_turn );
}
}
void writer_function(void) {
int i;
for (i=0; i<loopcnt; i++) {
sem_wait( &writers_turn );
buffer = rand();
printf("writer produces one item: %d\n", buffer);
sem_post( &readers_turn );
}
}
6.287
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
287
Solving Reader-Writer Problem
int main()
{
pthread_t reader;

if (sem_init(&readers_turn, 0, 0) < 0) {
perror("sem_init");
exit(1);
}
if (sem_init(&writers_turn, 0, 1) < 0) {
perror("sem_init");
exit(1);
}
if(pthread_create( &reader, NULL, reader_function, NULL) != 0) {
perror("pthread_create");
exit(1);
}

writer_function();
sem_destroy(&readers_turn);
sem_destroy(&writers_turn);
return 1;
}

6.288
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Mutex Variables
! Used for mutual exclusion locks.
! A mutex variable can be either locked or unlocked
pthread_mutex_t lock; // lock is a mutex variable
! Lock operation
pthread_mutex_lock( &lock ) ;

! Unlock operation
pthread_mutex_unlock( &lock );

! Initialization of a mutex variable by default attributes
pthread_mutex_init( &lock, NULL );


6.289
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Mutual Exclusion and Pthreads
! Pthreads provide a simple mutual exclusion lock
! Lock creation
int pthread_mutex_init(
pthread_mutex_t *mutex,
const pthread_mutexattr_t *attr);

" returns 0 on success, an error code otherwise


" mutex: output parameter, lock
" attr: input, lock attributes
! NULL: default
! There are functions to set the attribute (look at the man pages if youre
interested)
6.290
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Pthread: Locking
! Locking a lock
" If the lock is already locked, then the calling thread is blocked
" If the lock is not locked, then the calling thread acquires it
int pthread_mutex_lock(
pthread_mutex_t *mutex);

" returns 0 on success, an error code otherwise


" mutex: input parameter, lock
6.291
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Pthread: Locking
! Just checking
" Returns instead of locking

int pthread_mutex_trylock(
pthread_mutex_t *mutex);

" returns 0 on success, EBUSY if the lock is locked, an error code


otherwise
" mutex: input parameter, lock
6.292
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Synchronizing pthreads
! Releasing a lock
int pthread_mutex_unlock(
pthread_mutex_t *mutex);

" returns 0 on success, an error code otherwise


" mutex: input parameter, lock
! Pthreads implement exactly the concept of locks as it was described in the previous
lecture notes
6.293
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Cleaning up memory
! Releasing memory for a mutex attribute

int pthread_mutex_destroy(
pthread_mutex_t *mutex);

! Releasing memory for a mutex



int pthread_mutexattr_destroy(
pthread_mutexattr_t *mutex);

6.294
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
294
Example 1
! Reader-writer problem:
" Share a buffer which holds one item (an integer)
" A single reader and writer
" Reader: only read when there is item in buffer
" Writer: only write when there is space in buffer

6.295
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
295
Example 1 (cont.)
#include <pthread.h>
#include <stdio.h>
int buffer_has_item = 0;
int buffer;
pthread_mutex_t mutex;

void * reader_function(void *)
{
while(1){
pthread_mutex_lock( &mutex );
if ( buffer_has_item == 1) {
printf("reader consumes one item: %d.\n", buffer);
buffer_has_item = 0;
}
pthread_mutex_unlock( &mutex );
}
}

6.296
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
296
Example 1 (cont.)
void writer_function(void)
{
while(1) {
pthread_mutex_lock( &mutex );
if ( buffer_has_item == 0 ){
buffer = rand()*100;
printf("writer produces one item: %d\n", buffer);
buffer_has_item = 1;
}
pthread_mutex_unlock( &mutex );
}
}
void main()
{
pthread_t reader;

pthread_mutex_init(&mutex, NULL);
pthread_create( &reader, NULL, reader_function,NULL);
writer_function();
}
6.297
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Condition Variables
! In a critical section (i.e. where a mutex has been used), a thread can
suspend itself on a condition variable if the state of the computation is not
right for it to proceed.
" It will suspend by waiting on a condition variable.
" It will, however, release the critical section lock (mutex) .
" When that condition variable is signaled, it will become ready again; it
will attempt to reacquire that critical section lock and only then will be
able proceed.
! With Posix threads, a condition variable can be associated with only one
mutex variable.
6.298
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Condition Variables
! pthread_cond_t SpaceAvailable;
! pthread_cond_init (&SpaceAvailable, NULL );

! pthread_cond_wait (&condition, &mutex)
! pthread_cond_signal(&condition)
unblock one waiting thread on that condition variable (that thread should
still get the lock before proceeding)

! pthread_cond_broadcast(&condition)
unblock all waiting threads on that condition variable (now all of them will
compete to get the lock)
6.299
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
pthread_cond_init()
! Creating a condition variable
int pthread_cond_init(
pthread_cond_t *cond,
const pthread_condattr_t *attr);

" returns 0 on success, an error code otherwise
" cond: output parameter, condition
" attr: input parameter, attributes (default = NULL)


6.300
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
pthread_cond_wait()
! Waiting on a condition variable
int pthread_cond_wait(
pthread_cond_t *cond,
pthread_mutex_t *mutex);

" returns 0 on success, an error code otherwise
" cond: input parameter, condition
" mutex: input parameter, associated mutex


6.301
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
pthread_cond_signal()
! Signaling a condition variable
int pthread_cond_signal(
pthread_cond_t *cond;

" returns 0 on success, an error code otherwise
" cond: input parameter, condition

! Wakes up one thread out of the possibly many threads waiting for the
condition
! The signaling thread has priority over any thread that may be
awakened
" Signal-and-continue semantics.

6.302
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
pthread_cond_broadcast()
! Signaling a condition variable
int pthread_cond_broadcast(
pthread_cond_t *cond;

" returns 0 on success, an error code otherwise
" cond: input parameter, condition

! Wakes up ALL threads waiting for the condition
" May be useful in some applications
6.303
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Condition Variable: example
! Say I want to have multiple threads wait until a counter reaches a maximum value and be
awakened when it happens
pthread_mutex_lock(&lock);
while (count < MAX_COUNT) {
pthread_cond_wait(&cond,&lock);
}
pthread_mutex_unlock(&lock)

" Locking the lock so that we can read the value of count without the possibility of a race
condition
" Calling pthread_cond_wait() in a while loop to avoid spurious wakes ups
" When going to sleep the pthread_cond_wait() function implicitly releases the lock
" When waking up the pthread_cond_wait() function implicitly acquires the lock
" The lock is unlocked after exiting from the loop
6.304
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
pthread_cond_timed_wait()
! Waiting on a condition variable with a timeout
int pthread_cond_timedwait(
pthread_cond_t *cond,
pthread_mutex_t *mutex,
const struct timespec *delay);

" returns 0 on success, an error code otherwise
" cond: input parameter, condition
" mutex: input parameter, associated mutex
" delay: input parameter, timeout (same elds as the one used for
gettimeofday)
6.305
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Producer-Consumer Problem
! Producer will produce a sequence of integers, and deposit each integer in a
bounded buffer (implemented as an array).
! All integers are positive, 0..999.
! Producer will deposit -1 when nished, and then terminate.
! Buffer is of nite size: 5 in this example.
! Consumer will remove integers, one at a time, and print them.
! It will terminate when it receives -1.
6.306
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Definitions and Globals
#include <sys/time.h>
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#define SIZE 10

pthread_mutex_t region_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t space_available = PTHREAD_COND_INITIALIZER;
pthread_cond_t data_available = PTHREAD_COND_INITIALIZER;

int b[SIZE]; /* buffer */
int size = 0; /* number of full elements */
int front,rear=0; /* queue */
6.307
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
void *producer()
{
int i = 0;
while (1) {
pthread_mutex_lock(&region_mutex);
while (size == SIZE) {
pthread_cond_broadcast(&data_available);
pthread_cond_wait(&space_available,&region_mutex);
}
add_buffer(i);
pthread_cond_broadcast(&data_available);
pthread_mutex_unlock(&region_mutex);
i = i + 1;
}
pthread_exit(NULL);
}
Producer Thread
6.308
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Consumer Thread
void *consumer()
{
int i,v;
for (i=0;i<100;i++) {
pthread_mutex_lock(&region_mutex);
while (size == 0) {
pthread_cond_broadcast(&space_available);
pthread_cond_wait(&data_available,&region_mutex);
}
v = get_buffer();
pthread_cond_broadcast(&space_available);
pthread_mutex_unlock(&region_mutex);
printf("got %d ",v);
}
pthread_exit(NULL);
}

6.309
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Main program
main()
{
pthread_t producer_thread,consumer_thread;
void *producer(),*consumer();
pthread_create(&consumer_thread,NULL,consumer,NULL);
pthread_create(&producer_thread,NULL,producer,NULL);
pthread_join(consumer_thread,NULL);
}
void add_buffer(int i){
b[rear] = i; size++;
rear = (rear+1) % SIZE;
}
int get_buffer(){
int v;
v = b[front]; size--;
front= (front+1) % SIZE;
return v ;
}
6.310
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Scoreboard: operations
! main starts up operation
! producer thread
" Locks scoreboard
" Waits for row to be available
" Marks row as in use
" Unlocks scoreboard
" Fills buffer row with random ints
" Locks scoreboard
" Marks row as sortable
" Unlocks scoreboard
AVAILABLE 0
#define FILLING 1
#define SORTABLE 2
#define SORTING 3
Scoreboard
Row Status
0 AVAILABLE
1 AVAILABLE
2 AVAILABLE
3 AVAILABLE
4 AVAILABLE
5 AVAILABLE
... ...
6.311
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Scoreboard: operations
! main starts up operation
! producer thread
" Locks scoreboard
" Waits for row to be available
" Marks row as in use
" Unlocks scoreboard
" Fills buffer row with random ints
" Locks scoreboard
" Marks row as sortable
" Unlocks scoreboard
AVAILABLE 0
#define FILLING 1
#define SORTABLE 2
#define SORTING 3
Scoreboard
Row Status
0 FILLING
1 AVAILABLE
2 AVAILABLE
3 AVAILABLE
4 AVAILABLE
5 AVAILABLE
... ...
6.312
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Operation
! main starts up operation
! producer thread
" Locks scoreboard
" Waits for row to be available
" Marks row as in use
" Unlocks scoreboard
" Fills buffer row with random ints
" Locks scoreboard
" Marks row as sortable
" Unlocks scoreboard
AVAILABLE 0
#define FILLING 1
#define SORTABLE 2
#define SORTING 3
Scoreboard
Row Status
0 SORTABLE
1 AVAILABLE
2 AVAILABLE
3 AVAILABLE
4 AVAILABLE
5 AVAILABLE
... ...
6.313
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Operation
! sorter threads
" Lock scoreboard
" Wait for row to be sortable
" Mark row as sorting
" Unlock scoreboard
" Sort row (using bubblesort)
" Lock scoreboard
" Mark row as available
Scoreboard
Row Status
0 SORTABLE
1 AVAILABLE
2 AVAILABLE
3 AVAILABLE
4 AVAILABLE
5 AVAILABLE
... ...
6.314
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Operation
! sorter threads
" Lock scoreboard
" Wait for row to be sortable
" Mark row as sorting
" Unlock scoreboard
" Sort row (using bubblesort)
" Lock scoreboard
" Mark row as available
Scoreboard
Row Status
0 SORTING
1 AVAILABLE
2 AVAILABLE
3 AVAILABLE
4 AVAILABLE
5 AVAILABLE
... ...
6.315
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Operation
! sorter threads
" Lock scoreboard
" Wait for row to be sortable
" Mark row as sorting
" Unlock scoreboard
" Sort row (using bubblesort)
" Lock scoreboard
" Mark row as available

Scoreboard
Row Status
0 AVAILABLE
1 AVAILABLE
2 AVAILABLE
3 AVAILABLE
4 AVAILABLE
5 AVAILABLE
... ...
6.316
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
1000
10
sorter
sorter
sorter
sorter
sorter
sorter
sorter
7
Scoreboard
producer
6.317
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#define SIZE 1000 /* Size of sort buffers */
#define SCOUNT 7 /* Number of sorters */
#define ROWS 10 /* Number of buffers */
#define STEPS 22 /* Buffers full of data to
sort */
#define NONEFOUND -1 /* Used in searching */

6.318
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
/* Allowable states for row buffers (in scoreboard) */
enum {AVAILABLE, FILLING, SORTABLE, SORTING};
enum {NO, YES};

static int data[ROWS][SIZE]; /* The buffers */
static int available; /* Num of buffers
available to fill */
static int sortable; /* How many are
avail to sort */
static int scoreboard[ROWS]; /* Row access
scoreboard */
static int run; /* Flag used to
shutdown
gracefully */

6.319
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
/* Scoreboard mutex lock */
static pthread_mutex_t scorelock;
/* The producer can work! */
static pthread_cond_t pcanwork;
/* A sorter can work! */
static pthread_cond_t sorterworkavail;


/* Function prototypes */
static void *producer();
static void *sorter();
void sort(int);

6.320
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
int main(int argc, char* argv[])
{
pthread_t producer_id;
pthread_t sorter_id[SCOUNT];
pthread_attr_t attr;
int i;

available = ROWS;
sortable = 0;

run = YES;


6.321
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
pthread_attr_init(&attr);
/* This binds thread to lwp allowing kernel to
schedule thread (Will allow threads to run on
different cpu's) */
pthread_attr_setscope(&attr,PTHREAD_SCOPE_SYSTEM);
pthread_mutex_init(&scorelock, NULL);
pthread_cond_init(&pcanwork, NULL);
pthread_cond_init(&sorterworkavail, NULL);
for (i=0; i < ROWS; i++) {
scoreboard[i] = AVAILABLE;
}
if(argc == 1) /* No concurrency */
pthread_create
(&producer_id, NULL, producer, NULL);
else
pthread_create
(&producer_id, &attr, producer, NULL);
6.322
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
for(i = 0; i < SCOUNT; i++)
{
if(argc == 1)
pthread_create
(&sorter_id[i], NULL, sorter, NULL);
else
pthread_create
(&sorter_id[i], &attr, sorter, NULL);
}
printf("main> All threads running\n");
pthread_join(producer_id, NULL);


6.323
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
/* After the producer is finished we send signals
to all sorters to wake up and see that they
should quit */
for(i = 0; i < SCOUNT; i++)
{
pthread_cond_signal(&sorterworkavail);
}

for(i = 0; i < SCOUNT; i++)
{
pthread_join(sorter_id[i], NULL);
}
printf("Normal Termination\n");
return 0;
}
6.324
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
static void *producer() {
int pcount;
int target;
int i;
for(pcount = 0; pcount < STEPS; pcount++) {
pthread_mutex_lock(&scorelock);
while(available == 0) {
pthread_cond_wait(&pcanwork, &scorelock);
}
target = NONEFOUND;
for(i=0; i< ROWS; i++) {
if(scoreboard[i] == AVAILABLE) {
target = i;
available = available - 1;
break;
}
}

6.325
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
pthread_mutex_unlock(&scorelock);
if(target == NONEFOUND) {
printf("*** Producer cannot find"
" available row!\n");
pthread_exit(NULL);
}
printf("p> Filling row %d\n", target);
for(i=0; i < SIZE; i++) {
data[target][i] = rand();
}
printf("p> Row %d complete\n", target);
pthread_mutex_lock(&scorelock);
scoreboard[target] = SORTABLE;
sortable = sortable + 1;
pthread_mutex_unlock(&scorelock);
pthread_cond_signal(&sorterworkavail);
}
6.326
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
run = NO;
return NULL;
/* pthread_exit(NULL); */
}

6.327
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
static void *sorter() {
int i;
int target;
pthread_t me;
me = pthread_self();
while(1) {
pthread_mutex_lock(&scorelock);
while(sortable == 0 && run == YES) {
pthread_cond_wait
(&sorterworkavail, &scorelock);
}


6.328
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
/* If the producer says stop and there is no
work...exit */
if(run == NO && available == ROWS) {
printf(" S> %x Exiting..."
"prod done & no filled rows\n", me);
pthread_mutex_unlock(&scorelock);
pthread_exit(NULL);
}
target = NONEFOUND;
for(i = 0; i < ROWS; i++) {
if(scoreboard[i] == SORTABLE) {
target = i;
sortable = sortable - 1;
scoreboard[target] = SORTING;
break;
}
}
6.329
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
if(target == NONEFOUND) {
/* We get here if the producer is finished
and some threads are being sorted but
none are available for sorting */
printf("S> %x couldn't find thread to "
"sort.\n", me);
pthread_mutex_unlock(&scorelock);
pthread_exit(NULL);
}
pthread_mutex_unlock(&scorelock);
printf("S> %x starting...\n", me);
sort(target);
printf("S> %x finishing min = %d max = %d\n",
me, data[target][0],
data[target][SIZE-1]);


6.330
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
pthread_mutex_lock(&scorelock);
scoreboard[target] = AVAILABLE;
available = available + 1;
pthread_mutex_unlock(&scorelock);
pthread_cond_signal(&pcanwork);
}
}

6.331
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
void sort(int target) {
int outer;
int inner;
int temp;
outer = SIZE - 1;
for(outer = SIZE - 1; outer > 0; outer--) {
for(inner=0; inner < outer; inner++) {
if(data[target][inner] >
data[target][inner+1]) {
temp = data[target][inner];
data[target][inner] =
data[target][inner+1];
data[target][inner+1] = temp;
}
}
}
}
(Bubble sort)
6.332
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Drinking Philosophers
! Extension of dining philosophers
! Arbitrary number of philosophers
! Each likes own drink, mixed from bottles on table
" Can only mix drink when holding all necessary bottles
" Each drink uses different subset of bottles
! Problem: control access to bottles, such that there is no deadlock and no
starvation
! Solution uses Dining Philosophers as sub-problem.
6.333
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Soda Jerk Problem
! Three Soda Jerks at Ice Cream Fountain Trying to Make Cones for
Screaming Kids
! Each Wish to Use Cone, Ice Cream, Scoop
" Only Need the Three Resources Periodically
" Must Have All at Once
! 3 Processes (Jerks) Sharing 3 Resources
! Make Following Assumptions
" Multiple Cones (N Counter Semaphore)
" One Container of Vanilla Ice Cream
" One Ice Cream Scope
! Solvable, but Difcult
! How Does Increasing to Two Containers and Two Scoops Alter the
Problem?
6.334
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Passing through a one-way Tunnel
! One-way tunnel enables any number of processes in the same direction
! a process in the right direction cannot enter if there is at least one
process in the left direction inside the tunnel.

Potrebbero piacerti anche