OS (3 CHP)

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 33

CHAPTER 3

PROCESS
SYNCHRONISATION

COMPETINGPROCESSES
Achieving Mutualexclusion
THE CRITICAT SECTION PROBLEM
Two-Process Solutions
Multiple Process Solutions
SYNCHRONIZATION HARDWARE

EMAPHORES
Usage
Implementation
Deadlocks and Starvation
Binarysemaphores
CLASSIcAL PROBLEMS ON SYNGHRONZATION
The BoundedbBiffer Problem
The Readcrs-Wrlters Problem
The Dining Philasophers Problem
CRITICA REGIONS
MONITORS
66 Process 8ynchronla
3.1. INTRODUCTION

Wthin this book, we have described a typlcal environment


nputer provides for the simultaneous execution ofmany separate proce
.
ve described the nature of processes and how their conpeuuon Ior the 1
matce
is managed by the system scheduler. Later, in the book sharing of the
active processes is described. owever, we heem
of the computer between
now, rat
ather glossed over certain significant conseguences and ramificat Un
the co-exi
existence of processes within one system. What we require to loo
more detail are the effects of processes competing ior resources and the at
processes which want to communicate with each other. needs

In general, all processes co-existing within a computer will be competing


for
System resources but if we look more closely we can identify several ral possibt
relationships between the processes. Possibilities are:

Fully independent processes: Users working on separate appltoas


within the one system such as students compiling or running theio
programns.

i Independent but related processes: Users contributng to one applicats


Such as several clerks in an order processing department. Each clerkn
be running their own copy of a data entry program but be accessing
updating one database an

Concurrent programming applications: This refers toapplications actual-


constructed as a set of cooperating processes. This is common in real tima
applications whích have td deal with asynchronous events. Also, man
problems can be more readily solved by defining the soluton
in terms of
parallel processes. Some high level languages, such as ADA, Cöncurrent
Pascal and Concurrent C, have been designed to facilitate the productiono
concurrent programs.
The most obvious example of a concurrent programming
course, an operating system. Real-time systems such as application is, of
process control, on-line
databases, network controllers etc. also exemplify concurrent
applications.
The work of the operating system is managing the resources.
The less obvious
Togical'resources are data iterms, in main memory or on secondary storage,
employed
for system and application purposes, such as message
queues, shared data
structures etc. In effect, such items only constitute a resource
processes have to share them. when two. or more

Resources can be classified as reusable or consumable. A


is not destroyed by betng used: physical resources such
reusable resource
memory are clearly reusable. If the resource can only beas the by
processor and main
used one process at a
time it is called serlaly reusable. For example, a printer would
be called serlaiy
Process Synchronisation 67

reusable since it is not feasible to send the output from several processes to the
samephysca printer Some kinds of resources are not subject to this sharing
problem, notably disk files which, with some restrictions, can be shared by several
proceses simultaneously.
Aconsumable resource is a transient data 1tem or a signal which is created
by one process and ceases to exist when recelved by another. A typical consumable
resource is a message sent between one process and another.

The principal problem frorn the sharing


arising of resources is to ensure
that serialy reusable resources
are only used by one process at one time: le. to
ensure mutual exclusion. we assume, for example. that a printer is being used
If
by a process, then the printer must remain allocated to the process until the printout
is completed. This iactor gives rise to most of the problems encountered in handling
concurrency.

The principal problemn created by the need for mutual exclusion 1s the
potential danger of deadlock. A process is said to be deadlocked if it is walting for
an event which will never occur. In the context of resource sharing. this can occur
when two or more processes are each waiting for a resource held by the others. For
example, assume that process Pl has a printer allocated to it and attempts to open
a file F. Process P2, meanwhile, has already obtained exclusive access to fille F and
now requests the printer. Each process is waiting for a resource held by the other,
while holdingaresource required by the other. In principal more than two processes
could be involved in such a deadlocked circle.

Processes that work together to some common purpose or within some shared
environment require to 'talk to each other. A number of techniques are available
in this respect, such as shared memory, shared file or message system. The sinmplest
form of such communication is a signal from one process to another indicating
completion of a event on which the second process is waiting: this is kmown as
synchronisation. Process synchronization is the task of organizing the access of
several concurrent processes to shared (i.e. jointly used) resources without causing
any conflicts. In this.chapter, we discuss in more detail the topic of competing
processes and process synchronization.

3.2 cOMPETING PROCESSES

As we indicated in
the introduction, the mutual excluslon requirement is
he over-riding consideration
in dealing with competing processes. In the case of
shared physical resources, such as a printer or a mnemory or a shared variable ,it is
learly necessary to avoid-data corTuption and intermingling. but it is equally
alid in many other contexts.
The problem is one of mutual exclusion; in effect, we must insist that these
ensitive operations can only be performed by one process at a time. An important
oint to note is that the potential for interprocess clashes only arises at certain
68 Process 8ynchronla

processes, where the critical manipulations are carried out. Thus, t


ie e
narm in the processes generally golng about their Dusiness provia
ofa process Which Is sens
Pauuons are taken at these critical ponts. The area
process
at to guarantee mutual clusion, only one (potentially dashfng
It can
complications is called a Critical reglon (or section).process be
shou
s
De allowed into its critical region at anyone time. Thus we eea some klnd

nc ight system which will allow one process to enter its criuical reglon
nen stop all other processes from entering thelr critical region. Tnis situation
represen
Figure 3.1 for two such processes A and B; the shaded area
srated in
the critical region of the process, and the arrows indicate the curtent polnt
CNCCudon. critical reglons and the principle of mutual exclusion related to ead
ea
other.

Process Process Process


A A B

Nelther process A enters critical A exits, B now enter


is in critical region reglon. B cannot enter. critical region.

Figure 3.1 Critücal Regions

3.2.1 Achieving Mutual exclusion

Mutual excusion of system resources is readily achteved stnce access


these is centralised ín the operating system. For logical resources a number a
methods have been proposed to manage the mutual exclusion problem. What thes
amount to are techniques and/or facilitles which would enable programmers t
write applications which are safe in terms of allowing concurrent processes
exist without fear of data loss or corruptlon and, provide an eficient and equitab
handiing of shared resources.

Assume that two processes are sharing some resource and, therefore, ha
each a critical reglon of code. We requfre to guard entry to the critical reglons
ensuring that whem one process has entered Its reglon, the other process is there
barred from entry untl the tirst process edts. This appears to have the characterisu
of a gate which can only be open for one process at a time.
Process 8ynchronisatlon 69

Conslder the following simple example:

sharedintx=3:
process1 0

printf(%d".x);
process 20
x= x+1;
printf%d'. z:

Note that although x =x +1 looks like one statement, it probably complles


into at least two and probably three machine instructions. A likely translatlon is:

LOAD r1<-X
ADD r1+1->r1
STORE rl->X

Because of this, depending on when context switches occur, any of the


x
ollowing sets of output and final values in are possible:
Frocess 1 Process 2 Variable

By seeing the above. x= x+1 is not indívisible or atomic action. An atomic


action is an indivisible action - an action taken by a process than cannot be
nterrupted by a context.switch. When accesses to a shared varlable are not atomic,
t Ieads to several problems. If the program is keeping bank balances,someone's
iepositjust got lost. Ifit's controlling chemotherapy. maybe thelr life. When two or
more concurrent processes share the system resources, race condition may occur
f the order of scheduling of these processes results in different computations.

A critical region is part of the code of a process which accesses some shared
esource which could potentially be accessed by another process at the same time.
ro ensure mutual excluslon. the processes involved must not be in their critical
eglons simultaneously. There are some hardware and software solutlons to achieve
nutual excluslon They are:

1. Test and set


2. Semaphores
3. Monitors
4. Crltical reglons
70 Procese Synchronla
3.3 THE CRITICAL-SECTION PROBLEM
Conslder a system consisting of n processes {Pl.P2..Pl} Each pro
a segment of code, called a critical section, in whichthe process ma
changing common variables. updating a table, writing a file, and so on.y
portant feature of the system is that, when one process is executing in its Cri
cuon, no other process is to be allowed to execute in its critical section.
execution of critical sections by the processes is mutually exclusive in t
twooccur if the order scheduling of these processes results differe
ay
or more concurrent processes share the system resources race condt
in proces
computations. The critical-section problem is to design a protocol that the
t

n use to cooperate. Each process must request permission to enter its crtiT
econ. The section of code implementing this request is the entry section,
critcal section may be followed by an exit section. The remaining code is
remainder section.

do
ert secilon
ctllcal seculon
exitsacion
gemandar sectton
while

General structure of a typical processP,


A solution to the critical-section problem
must satisfy the following thre
requirements:

Mutual Excluslon:lf process P, is executing in its critical


other processes can be executing in their critical section, then =
sections.
Progress: Ifno process is executing in its critical
wish to enter their critical sections, then only section and some processe-
processes
those that are no
executing in thelr remainder. section can participate
which will enter its critical section next, and in' the decision o-
postponed tndefinitely. this selection cannot b-

Bounded Waiting: There


processes are allowed to exists a bound on the number of times that oth=
enter thelr critical sections after a process ha:
made a request to énter its criticalsection and before
that request is granted
We assume that each process is executing
at
no assumption concerning the relatve speed of thea nonzero speed. We can make
n processes. Let us work up
the solutions to the critical-section problem that satisfy
these three requirements
Process 8ynchronlsation 71
3.3.1 Two-Process Solutions
Let us restrict our attentlon to algorithms that are applicable to only two
processes at a time. The processes are numbered P, and
P. For convenience., when
oresenting P, we use P, to denote the other process; that is, j == 1-1.
Algorithm 1

while (tutE
crltical secifon
turn
emainder section
whild (1iD

The structure of process P,in algorithm l

Our first approach is to let the processes share a common integer variable
urn initialized to 0 (or 1). If turn == i, then process Pis allowed to execute in its
ritical section. The structure of process P, is shown above. This solution ensures
hat only one process at a time can be in its critical section. However. it does not
atisly the progress requirement, since it requires strict alternation of processes in
he execution of the critical section. For example, if turn == 0 and P, is ready to enter
s critical section, P, cannot do so, even thcugh P may be in its remainder section.
1gorithm 2
The problem with algorithm 1 is that it does not retain sufflcient informmation
bout the state of each process: it remembers only which process is allowed to
nter its critical section. To remedy this problem, we can replace the variable turn
dth the following array:

Lzboolean flagi2]:
The elements of the array are initialized to false. If flag [1] 1s true, this value
idicates that P, is ready to enter the critical section. The structure of process P, is
1own below:

eptidat segtfoa
emaincder segto
wbne
The structure of process Pin algorithm 2
Procese Synchronlaa
72
atl
slgnalingthat
toIn this algorithm. process P, Arst sets flag [| to be true,proces that
that ess PIs noi
Pis not
ready
ready to enter
its critical section. Then. P, checks to verify al
to
ready to enter
ready P, were ready, then
P, would walt until p
its (that is, until ha
critical section. If
indicated
aicated that it no longer
longer neded
needed to to be in the critical section
was false). At thi: point, P, would enter eritical
the critical section onOn eung the crts
exitng tne
section, P would set lag [i] to be false, allowing the other process it iswaiting
(1f crt
waittng
mutual-exclusion requiremen
tratent
Cer its critical section. In this solution, the
satisfied. Unfortunately. the rogress requirement is not met. To llust th
problem, we conslder the following execution sequence

Psets flag [0) = true


To:
T:P, sets flag 1] = true
Ow P and P, are looping forever in thelr respective while statements.

This algorithm is crucially dependent on the exact timing of thetw


processes. The sequence could have been derived in an environment where the
are several processors executing concurrently, or where an interrupt (such as
timer interrupt) occurs immediately after step To is executed. and the CPU switche
from one process to another. Note that switching the order of the instructions ft
setting flag (| and testing the value of a flag (il will not solve our problem. Rathe
we will have a situation where it is posstble for both processes to be in the critlca
section at the same time, violating the mutual-excluslon requirement

Algorithmn3

We combine the key ideas of algorithm 1 and algorithm 2, to obtain a correct


solution to the critical-section problem, where all three requirements are met. The
processes share two variables:

boolean flagi2
int turn;

Initially aglo) = flag [1] = false, and the value of turn is immaterial (but is
either 0 or 1). The structure of process P,is shown below.

do
lag I)E fue
tum=f
VileMagiikriun
tlcal secoton
lag 0 als
remamder seciton
Jwtille 0¥
The structure of process P, in algorithm 3
Proceas Synchronisation 73

enter the critical section,


To process P, first sets flag [1] to be true and then
sets turn to the valuej. tlhereby asserting that if the other process wishes to enter
the critical section it can do so. If both processes try to enter at the same time. turn
will be set to both 1 andj at roughly the same time. Only one of these assignments
will last; the other will occur, but will be overwritten 1rmmediately. The eventual
value
section
turn
offlrst. decides which of the two processes i allowed to enter its critical

To prove that this solution is correct, we need to show that:


1 Mutual exclusion is preserved,
2. The progress requirement is satisfied.
3. .The bounded-waiting requirement 1s met.

To prove property 1, we note that each P, enters its critical section only if
either flag l] == false or turm == 1. Also note that, if both processes can be executing
in their critical sections at the same time. then flag [O] == flag [l] == true. These two
observations imply that P, and P, could not have successfully executed their while
statenments at about the same time. since the value of turn can be either O or 1, but
cannot be both. Hence, one of the processes-say P-must have successfiilly executed
the while statement, whereas Pi had to execute at least' one additional statement
(turn ==j *). However. since, at that time, flag jl == true, and turn ==j. and this
condition will persist as long as P, is in its critical section, resulting in P: Mutuaal
exclusion is preserved.

To prove properties 2 and 3, we note that a process P, can be prevented from


entering the critical section only if it is stuck in the:while loop with condition
flagjl == true and turn ==j: this loop is the only one. If P, not ready to enter the
critical section, then flag U]== false in and while P, can enter criical section. f P, has set
flag (jl to true and is also executing its. statement. then either turm == i or
turn ==j. If turn == 1, then P will enter the critical section. If turn ==j. then Pjwill
enter the critical section. However once P, exits its critical section, it vwill reset flag
U1 to false, allowing P,enter its critical section. IfPresets flag (] to true, it must also
set turn to 1. Thus, since P, does not change the value of the variable turn while
executing the while statement, P, will enter the critical section (progress) after at
most one entry by P, (bounded waiting.

3.3.2, Multiple-Process solutions

We have developed algorithm 3 which solves


the critical-section problem
for two processes. Now let us develop an algorithm for solving the critical-section
problem for n processes. This algorithm is known as the bakery algorithm. and it is
based on a scheduling algorithm commonly used in bakeries, ice-creann stores.
motor-vehicle registries, and other locations where order must be made out of
chaos. This algorithm was developed for a distributed envirornment, but at this point
we are concerned with only those aspects of the algorithm that pertain to a
centralized environment.
74
Process Synchronisatlo
On entering customer uis
the lowest numberthe sto cach customer recelves a number. The algorlthm Ath
guarantee that two is served next. Unfortunately, the bakery cannot
case of a tie, processes
ses (customers) do not receive the same number. er. In
the process with the lowest name is served first. That is. P. an
the
same
receive the same number
Teceive ss is, P, and
names are
and fi<j. then P is served first. Since process na P
e and totally ordered, letely
our algorithm is completely deterministtc.
determinisuc.
The common data structures are
boolean choosinglnl:
int umberlnl:
Initially. these data structures are initialized to false and 0. respectively
respectively.,
For convenience, we
define the following notation:
. (a.b)< (c.d) ifa<corifa == c and b <d.
ii.
maxla. ais a number, k, such that k>=a,for i = 0,..,n-1
The structure of process P, used in the bakery algorithm, is shown here.

do
choosingli= tue
numberlemaxtnumber iO uumber lmumbe
choosingl= false:
for=0JnJ
whle(choosingj
while humber U1 0) & number
critical section fel
numberl-0
emanier sectiou
iwhile
The structure of process P in the bakery algorithm
To prove that the bakery algorithm is correct, we
is in its critical section and P, (k != need first to show that, if P
1)
has already chosen its number kl= 0,
(number [I 9 < (number [k] .k). then

Given this result, it is now stmple to show that


Indeed, consider P, in its critical section and mutual exclusion is observed.
P, trying to enter the P, critical section.
When process P, executes the second whíle statement
forj ==i,t finds that
i. number [] !=0
ii. (numberi )< (number k] .k).

Thus, it continues looping in the while statement


until P, leaves the P, critical
section. If we wish to show that the progress and bounded-walting
requirements
Process 8ynchronisatlon
75
are preserved, and that the algorithm
ensures fainess, It is sufficient to observe
that the processes enter thelr critical section on
a first-come, first-served basiS.
3.4 SYNCHRONIZATION HARDWARE

In this section, we present some


simple hardware instructions that are
available on many systems, and
show how they can be used effectively in solving
the critical-section problem.

The critical-section problem


could be solved simply in a uniprocessor
environment if we could forbid interrupts to
occur while a shared variable is being
modified. In this manner, we
could be sure that the current sequence of
instructions would be allowed to execute in order
without preemption. No other
instructions would be run, so no unexpected modifications
shared variable. Unfortunately, this could be made to the
solution is not feasible in a multiprocessor
environment Disabling interrupts on a
multiprocessor can be time-consuming, as
the message is passed to all the processors.
Thís message passing delays entry
into each critical section, and system efficiency
therefore provide special hardware decreases. Many machines
modify the content of a word, or to
instructions that allow us either to test and
swap the contents of two words, atomically.-that
is, as one uninterruptible unit. We
can use these special instructions to solve the
critical-section problem in a relatively
simple manner.
The TestAndSet instruction can be defined
as shown here.
boolean TestAndSet(boolean &target)

boolean rv= target;


target true;
return rv
The important characteristic is that
Thus, if two TestAndSet instructions arethis instruction is executed atomically.
executed
different CPU), simultaneously (each on a
they will be executed sequentially in some
arbitrary order.
If the machine supports the
TestAndSet instruction, then we can
mutual excluslon by declaring a Boolean variable implement
structure of process P, is shown below. lock, initialzed to false. The

do
Whe resttAndSctogk
critiealserton
gak faise
eoaindlr secto

Matual-exclusion implementation
with TestAndSet
76 Process 8ynchronlsat
The Swap instruction, defined as shown below operates on the contetentson
wO ntomically.
Words: like the TestAndSet instruction, it is executed atomicauy.

do

void Swaplboolean &a,


boolean &b)

boolean temp=a
abEtempP
b

The deflnition of the Swap instruction.


can
the machine supports the Swap instruction, then mutual excluslon
be provided as follows. A global Boolean variable lock is declared and is initlalzed
to false. In addition. each process also has a local Boolean variable key. The
structure of process P, is shown here.

do

key=true
whle (keytruejSwap (Clock key)
criical section
lock= false,
remaindersection
while (0
Mutual-exclusion implementation with the Swap instruction

These algorithms do not satisfy the bounded-waiting requirement. We


present an algorithm that uses the TestAndSet instruction below. This algorithm
satisfies all the critical-section requirements. The common data structures are

boolean waltingln]
boolean 2lock;

These data structures are initialized to false.

do
walftingil}=
key e true
truer
wile wafingul 88key)
key TesiAndsetiloek,walttigl=fasei
crticalsection
77
process 5ynchronisatlon
e (41) % n
wHlle(S0&8 lwalting0D
JE0+1 %n
in) ock=falsc,
else
waltingUE false
remalnder sectlon
whilc (4)

Bounded-waiting mutual exclusion with TestAndSet

To verify that the mutual-exclusion requirement is met, we note that


process
==
false or key == false. The
P can enter its critical section only if either waitinglt executed. The first
value of the key can become false only if the TestAndSet is The
process to execute the TestAndSet will find key == false; all others must wait.
section;
variable waiting i] can become false only if another process leaves its critical
requirement.
only one waiting [] is set to false, maintaihing the mutual- exclusion
argument
To prove the progress, requirement is met, we note that the
the critical
presented for mutual exclusion also apply here, since a process entering
section elther sets lock to false, or sets waitingj] to false. Both allow
a process that
is walting to enter its critical section to proceed.

To prove the bounded-waiting requirement is met, we note that, when


a
process leaves its critical section, it scans the array waiting in the cyclic ordering
(1+1,1+2, ... n- 1,0,...-1): It designates the first
process in this orderlng that is in
critical section.
the entry section (waitingjl == true) as the next one to enter the
Any process waiting to enter its critical section will thus do so within
n-1 turns.
Unfortunately for hardware designers, implementing atomic TestAndSet
instructions on multiprocessors is not a trivial task.

3.5 SEMAPHORES

The solutions to the critical-section problem presented so far are not easy
to generalize to more complex problems. To overcome this difficulty, we can use a
synchronization tool called a semaphore. A sermaphore S is an integer varlable
that, apart from initialization, is accessed only through two standard atomic
operations: walt and signal. These operations were originally termed P (for walt;
from the Dutch proberen, to test) and V (for signal; from verhogen, to increment).
The classical definitlon of walt in pseudocode is
walt (S)

while (S<= 0)
no-op
S
//
The classical definitions of signal in pseudocode is
78
Pro 8ynchron
signal(S)

S+
Modifications
to the integer value of the semaphore in the
operations must be executed wait ana
indivisibly. That is, when one process
semaphore value, no moi
value. In idition, other process can simultaneously modiy that same s
SIS<=0). and its in the case of the wait (S). the testing of the intedaph
possible modification (S--). must also be executed
uption. We shall see how these operations can be ue
see how semaphores implemented. First,
First
can be used. let
3.5.1 Usage
We can use semaphores to deal with the n-process
Then processes share a semaphore, mutex critical-sectionr
(standing 1or mutual exclte bl
initialized to 1. Each process P, is organized as shown lusto-
here.
do

wait (mutex)
critical section
signal (mutex);
remainder section
while (1):
3.5.1.1 Mutual-exclusion implementation with
semaphores
We can also use semaphores to solve various
synchronization problems.m
example, consider two concurrently running processes:
and P, with a statement 31. Suppose that we P with a statement
30 has completed. We can implement this require that 31 be executed only af
scheme
share a common semaphore synch, initialized to 0, andreadily by letting P, and
by inserting the stateme-

S,
signal(synch):
in process P,. and the statements
walt (synch);
S
in process P2.
Because synch is initialized to O, P, will execute 31 only after Pha
invoked signal (synch), whích is after 30.

3.5.2 Implementatlon

The main disadvantage of thè mutual-exclusion solutions discuss


previously, and is of the semaphore definition given here, is that they all requ
busy waiting. While a prOcess is in its critical section, any other process that u
79
Process 8ynchronisatlon
to enter critical section must loop continuously in the entry code. This continual
looplng is clearly a problem in a real multprogramming system, where a singie
CPU 1s shared among many processes. Busy waiting wastes CPU cycles that some
other process might be able to use productively. This type of semaphore 1s also
called. a spinlock (because the process "spins" whlle walting for the lock). SpinlockS
are useful in multtprocessor systems. The advantage ofa spinlock is thatno context
switch is requlred when a process must wait on a lock. and a context switch may
take considerable time. Thus, when locks are expected to be held for short umes,
spinlocks are useful.

To overcome the need for busy waiting, we can modify the definition of the
walt and signal semaphore operations. When a process executes the wait operation
and finds that the semaphore value is not positve, it must walt. However, rather
than busy wating, the process can block itself. The block operation places a process
into a waiting queue associated with the semaphore, and the state of the process is
switched to the waiting state. Then, control is transferred to the CPU scheduler,
which selects another process to execute.

A process that is blocked, waiting on a semaphore S, should be restarted


when some other process executes a signal operation. The process is restarted by a
wakeup operation, which changes the process from the waiting state to the ready
state. The process is then placed in the ready queue. (The CPU may or may not be
Switched from the running process to the newly ready process, depending on the
CPU-scheduling algorithm.) To implement semaphores under this definition, we
define a semaphore as "C" struct:

typedef struct

int value;
struct process "L
semaphore:

Each semaphore has an integer value and a list of processes. When a process
must wait on a semaphore, it is added to the list of processes. A signal operation
removes one process from the list of waiting processes and awakens that process.

The wait semaphore operation can now be defined as


vold wait(semaphore S)

S.value-
if (S.value < 0)

add this process to S.L


block0
60 Process Synchron
ne signal semaphore operation can now be defined as
void signal(semaphore S)

S.value++
if (S.value <= 0)
remove a process P from S.L:
wakeup(Pl:

The block operation suspends the process that invokes 1t. The wakeunn
Operatton resumes the execution of a blocked process P. These fwo operau
provided by the operating system as basic system calls.

Note that, although under the classical definition of semaphores with bs


wafting the semaphore value is never negative, this implementation may ha
negative semaphore values. If the semaphore value is negative, 1ts magnitude
the number of processes waiting on that semaphore. This fact is a result
of th
Switching of the order of the decrement and the test in the implementation of
operation. The list of waiting processes can be easily implemented by a ln
t
aft
tield in each process control block (PCB). Each semaphore contains an intege
value and a pointer to a list of PCBs. One way to add and remove processes from
th
list, that ensures bounded waiting would be to use a FIFO queue, where th
semaphore contains both head and tail pointers to the queue. In general, however
the list may use any queuing strategy. Correct usage ofsemaphores does not depen
on a particular queuing strategy for the semaphore lists. The critical aspect
semaphores is that they are executed atomically. We must guarantee that notw
processes can execute wait and signal operation on the same semaphore at the
same time. This situation is a critical-section problem, and can be solved in elthea
of two ways.

In a uniprocessor environment (that is, where only one CPU exidsts), we can
simply inhibit interrupts during the time the wait and signal operations art
executing. This scheme works in a uniprocessor environment because, onct
interrupts are inhibited, instructions from different processes cannot be interleaved
Only the currently running process executes, until interrupts are reenabled and
the scheduler can regain control. In a multuprocessor environment, iInhibiting
interrupts does not work. Instructions from diferent processes (running on differen
processors) maybe interleaved in some arbitrary way.
It is important to admit that we have not completely eliminated busy waltin
with this definition of the walt and slgnal operations. Rather, we have remove
busy waiting from the entry to the critical sections of application programs
Furthenmore, we have limlted busy waiting to only the critical sections of the wa
and signal operations, and these sections are short (tf properly coded, they shoud
rocess Synchronlsatlon 81

never
e no more than about 10 instructions). Thus, the critical section is almost
ccupled, and busy waltng occurs rarely, and then for only a short time. An entirely
ufferent situation exists with application programs whose critical sections may be
ong (minutes or even hours) or may
be almost always occupied. In this case, busy
vaiting is extremely inefficient.

.5.3 Deadlocks and Starvation


The implementation of a semaphore with a waiting queue may resut in
processes are walting indefnitely for an event that
a
ituation where two or more
an be caused only by one of the waiting processes. The event in question is the
xecution of a signal operation. When such a state is reached, these processes are
said to be deadlocked. We say that a set of processes is in a deadlock state when
every process in the set is waiting for an event that can be caused only by another
orocess in the set. The events with which we are mainly concerned here are resource
acquisition and release. Another problem related to deadlocks is indefinite blocking
or starvation, a situation where processes walt indefinitely within the semaphore.

indelinite blocking may occur if we add and remove


processes from the list
associated with a semaphore in LIFO order.

3.5.4 Binary Semaphores


commonly
The semaphore construct described in the previous sections is
range over an
known as a counting semaphore, since its integer value can value
unrestricted domain. A binary semaphore is a semaphore with an integer
can be sim-pler to
that can range only between 0 and 1. A binary semaphore
ämplement than a counting semaphore, depending on the underlying hardware
implemented
architecture. We will now, show how. a counting.semaphore can be
using binary semaphores. Let S be a counting semaphore. To
implement it in terms
of binary semaphores we need the following data
structures:

binary-semaphore S1, S2;


int C

Initlally S1 1, $2 =0, and the value of integer C is set to the initial


= value of
the counting semaphore S.
implemented as follows:
The wait operation on the counting semaphore S can be

wait(S1);
T
C--
f (C <0)
signal(S1)
wait($2);

signal(Sl):
82 Process Synchronlaat
The signal eration on the counting
semaphore S can be implemented
follows:
wait(S1)
C+
if (C=O) signal($2):
else
signal(S):
3.6 CLASSICAL PROBLEMS OF SYNCHRONIZATION

Here we present a number of different synchronization problems as exa.


for a large class of concurrency-control problems. These problems are le
used fo
testing nearly every newly proposed synchronization scheme. Semaphores:
for synchronization in our solutions. iset

3.6.1 The Bounded-Buffer Problema

The bounded-buffer problem discussed in previous chapter is commonhcon


used to illustrate the power of synchronization primitives. We present here a de
structure of this scheme, without committing ourselves to any parte
implementation. We assume that the pool consists of n buffers, each capahla
holding one item. The mutex semaphore provides mutual exclusion for accessest
the buffer pool and is initialized to the value 1. The empty and full semaphoT
count the number of empty and full buffers, respectively. The semaphore emptyt
fnitialized to the value n: the semaphore full is initialized to the value 0.

The code for the producer process is shown below.

do

produce andieuinnextp
waltempty
watt (mgte x
adanep to buffe
signalmuios
sgnalfu
wile (P
The structure of the producer process
The code for the consumer proces is shown here.

do

waiiiful
wall mutex
process Synchronlsatlon 83

remove an tem from buffer tonexte


Sgnalmutexhslgnalempty)
Consumethe tem in nextc
while (1)
The structure of the consumer process
Note the symmetry between the producer and the consumer We can interpret
this code as the producer producing full buffers for the consumer, or as the
consumer producing empty buffers for the producer.

3.5.2 The Readers- Writers Problem

.A data object (such as a file or record) 1sto be shared among severa


concurrent processes. Some of these processes may want only to read the content
may want to update (that is, to read and, write
of the shared object, whereas others
the shared object. We distinguish between these two types of processes by referring
to those processes that are interested in only reading as readers, and to the rest as
writers. Öbviously, if two readers access the shared data object simultaneously, no
adverse effects will result. However, if a writer and some other process (elther a
reader or a writer) access the shared object simultaneously, chaos may ensue.

To ensure that these difficulties do not arise, we require that the writers
have exclusive access to the shared object. This synchronization problem is referred
to as the readers-writers problem. Since it was originally stated, it has been used
to test nearly every new synchronization primitive. The readers. writers problem
has several variations, all involving priorities. The simplest one, referred to as the
first readers-writers problem, requires that no reader will be kept waiting unless a
Writer has already obtained permission to use the shared object. In other words, no
reader should wait for other readers to finish simply because a writer is waiting.
The second readers-Writers problem; requires that, once a writer is ready, that writer
performs its write as soon possible. In other words, if a writer is walting to access
the object, no new readers may start reading. A solution to elther problem may
result in starvation. In the first case, writers may starve; in the second case, Teaders
may starve. For this reason, other variants of the problem have been proposed. In
this section, we present a solution to the first readers-writers problem.

In the solution to the frst readers-wrlters problem, the reader processes


share the following data structures:

semaphore mutex, Wrt;


int readcount;

The semaphores mutex and wrt are initialized to 1; readcount is initialized


to 0. The semaphore wrt is common to both the reader and writer processes. The
mutex semaphore is used to ensure mutual exclusion when the variable readcount
Is updated. The readcount varlable keeps track of how many processes are curTenty
Process Synchronl
84
as a mutual-excluslon
eading the object. Thesemaphore wrt functionsor last reader that enters
sa
or ah
for the ters. It is also used by the first or exit rea.
eriucal section. It is not used by readers who, enter
While other readers
in their critical sections. a

The code for a writer process is shown here.


wait(wrt):
writing is perlormned
signal(wrt

The structure of a writer process 9


Note that, if a writer is in the critical section and n readers aree walti
are queued on mutex,
then one reader is queued on wrt, and n-1 readers
observe that, when a writer executes signal (wrT), We may resume the execut
either the waiting readers or a single waiting writer. The selection is madebyth
Scheduler. The code for a reader process is shown below.
waitmutex);
readcount+t
if read count1)
wait(wrt)
SIgnal mutex];
Teading 1s performed

waltfmutex
readcount
frreadcoumtsignalwrt
signalmutex
The structure of a reader process

3.5.3 The Dining-Philosophers Problem

Consider five philosophers who spend their lives thinking and eating.
philosophers share a common circular table surrounded by five chairs, ead
belonging to one philosopher. In the center of the table is a bowl of rice, and ul
table is lald with five single chopsticks. When a philosopher thinks, she does
interact wth her coleagues. From time to time, a philosopher gets hungy
tries to plck up the two chopsticks that are closest to her (the chopsticks that a
between her and her left and right nelghbors). A philosopher may pick up onyo
chopstick at a time. Obviously, she cannot pick up a chopstick that is already
the hand of a nelghbor. When a hungry philosopher has both her chopsticks al
same time, she eats without releasing her chopsticks. When she is finished ea
she puts down both of her chopsticks and starts thinking again.
rocess 8ynchronisatlon 85

o RICE

Figure 3.2 The situation of dining phílosophers


The dining-phllosophers problem is considered a classic synchronization
oroblem, neither because of its practical importance nor because computer
scientists dislike philosophers, but because it is an example of a large class of
oncurrency-control problems. It is a simple representation of the need to allocate
several resources among several processes in a deadlock and starvation free manner.

One simple solution is to represent each chopstick by a semaphore. A


ohilosopher tries to grab the chopstick by executing a wait operation on that
semaphore: she releases her chopstlcks by executing the signal operation the
approprlate semaphores. Thus, the shared data are

semaphore chopstick[5]:

where all the elements of chopstick are initialized to 1. The structure of philosopher
is shown below.

alighopsdeki
walleopsteslis
onsteKD
gnaltonopsIA

The structure of philosopher i


86 rocess
chronlu,
Although this solution guarantees that no two ors are
nelghboro
Simultaneously. 1it nevertheless must be rejected because has the possibillt
it eat
creating a deadlock. Suppose that all five philosophers becom become
Simultaneously, and each grabs her left chopstick. All the elements ofun hung
wnow be equal to 0. When each philosopher tries
will be delayed forever.
to grab her right chonPs
stck.
s
Several poss!ble remedies to the deadlock problem are listed here
re.
1. Allow at most four philosophers to be sittng simultaneously at s
the table.
2. Allow a philosopher to pick up her chopsticks only both chopsticks
if
available (to do this she must pick them up in a critical section). are

3. Use an asymmetric solution; that is, an odd philosopher plcks up


plcks up her right chopstick and then her left chopstick.
firsther
left chopstick and then her right chopstick, whereas an even phllosonh
opher
.
Finally. any satisfactory solution to the dining-philosophers
guard against problem mue
the possibility that one of the philosophers wll starve to death.
deadlock-free solution does not necessarily eliminate the
possibility of starvat
3.6 CRITICAL REGIONS

Although semaphores provide a


process synchronization, their incorrect convenient and effective mechanism for
use can still result in timíng errors that
are difficult to detect, since these errors
sequences take place, and these sequences happen only if some particular execution
do not always occur.
We have seen an example of such types
our solution to the producer-consumer problem. of errors in the use of counters in
happened only rarely, and even then the counterIn that example, the timing problem
value-off by only 1. Nevertheless, this solution value appeared to be a reasonable
is obviously not an acceptable one.
It is for this reason that semaphores were
introduced in the first place.
Unfortunately, such timing errors can
still occur with the use of semaphores
To illustrate how, let us review the solution.to
semaphores. All processes share a semaphore the critical-section problem using
to 1. Each process must execute wait (mutex) variable mutex, which is initlali
and signal (mutex) afterward. If this sequence before entering the critical sectio
be in their critical sections simultaneously. is not observed, two processes m

Let us examine the various diffleultles these


difficulties will arise if even a single process is that may result. Note that t
may be the result of an honest programmingnot well behaved. This
ay be situau
cooperattve
programnmer. error or of an uncoopere
87
Process 6ynchronisation

Suppose that a process interchanges the order in whtch the walt and signa
operations on the semaphore mutex are executed, resulting in the following
execution:
slgnal(mutex)
critical section
wait(mutex);

In this situatlon, several processes may be executing in their critical section


simultaneously, vlolating the mutual-exclusion requirement. Thís error may
be discovered only If several processes are simultaneously active in thelr
critical sections. Note that this situation may not always be reproducible.

replaces stgnal (mutex) with walt (mutex). That is, 1t


2. Suppose that a process
executes
walt(mutex);
critical section
wait(mutex);

In this case, a deadlock will occur.

3. Suppose that a process omits the walt (mutex), or the signal (mutex), or both.
In this case, elther mutual excluston is violated or a deadlock will occur.

These examples llustrate that various types oferrors can be generated easlly
when semaphores are used incorrectly to solve the critlcal-section problem. Simlar
problems may arise in the other synchronizatlon models we have discussed.

To deal with the type of errors we have outlined, a number of high-level


language constructs have been introduced. In this section, we describe one
fundamental high-level synchronization construct-the critical region (sometimes
referred to as conditional critical reglon) another fundamental synchronization
construct-the monitor. In our presentation of these two constructs, we assume
that a process consists af some local data, and a sequential program that can operate
on the data. The local data can be accessed by only the sequential program thatis
encapsulated within the same process. That is, one process cannot directly access
the local data of another process. Processes can, however, share global data.

The critical-region high-level language synchrontzation construct requires


that a varable v of type T, which is to be shared among many processes, be declared as
v: shared T:

The varlable v can be accessed only inslde a regton.statement of the


following form:
88
Process
Synchronl
region v when B do S:
This construct means that. while statement S is being execut. ed, no
process can access the variable v. The expression B IS a Boolean empressi uth
8overns the access to the critical region. When a process tries to lOn
critical-section region, the Boolean expression B is evaluated. If the emer
true, statement S is executed. If it is false, the process relinqutshes the
exclusion and is delayed until B becomes true and no other process cess isnuh
region associated with v. Thus, if the two statements, in
region v when (true) Sl;

region v when (true) S2;

are executed concurrently in distinct sequential processes, the result will


equtvalent to the sequential execution "S1 followed by S2" or "$2 followed by b
SI

The critical-region construct guards against certain simple errors associa


with the semaphore solution to the critical-section problem that may be made byi
programmer. Note that it does not necessarly ellminate all synchronization em
rather. 1t reduces their number. If errors occur in the 1ogic of the progran
reproducing a particular sequence of events may not be simple.

The critical-region construct can be effectively used to solve certain gene


synchronization problems. To illustrate, let us code the bounded-buffer scheme
The buffer space and ts pointers are encapsulated in

struct buffer
tem poolfn:
int count, in. out;

The producer process inserts a new item nextp into the shared bulfer y
executing fegion buffer when

(count < n
poolin nextp:
in = (in+1) % n;
countt+

utsitn
The consumer process removes an item from the shared buffer and put
nextc by executing
monitoE TmoniftoT 1ame

shared vartable declaratons

procedite body P

cedure bodyPl)

dure body PA

tftaltzaion.cote

Syntax of a monitor

The representation of a monltor type cannot be used directly by the various


processes. Thus, a procedure defined within a monitor can access only those
variables declared locally within the monitor and its formal parameters.Similarly,
the local varlables of a monltor can be accessed by only the local procediures.

The monitor construct ensures that only one process at a time can be
active
code this
within the monitor. Consequently, the programmer does not need to
synchronization constraint explicitly.
Process 8ynchronlaan
90
Entry queue

Shared Data

00-
Operations

Initialisation Code

Figure 3.2 Schematic view of a monitor


poOwe
However, the monitor construct, as defined so far, is not sufficlently werfl
for modeling some synchronization schemes. For this purpose, we need to det
additional synchronization mechanisms. These mechanisms are provided by t
condition construct. A programmer who needs to write her own tailor-ma
synchronization scheme can define one or more variables of type condition:

condition x, y:.

The only operations that can be invoked on a condition variable are wat
and signal. The operation x.walt0 means that the process invoking this operatim
is suspended until another process invokes x.signal( ). The x.signal) operation
resumes exactly one suspended process. Ifno process is suspended, then the signa
operation has no effect: that is, the stateofx is as though the operation were nev
executed (Figure 3.3). Contrast this operation with the signal operation assoclated
with semaphores, which always affects the state of the semaphore.

Now suppose that, when the x. signal() operation is invoked by a processr


there is a suspended process associated with condition x. Clearly, if the queue
associated with suspended process 9 is allowed to rèsume Its execution, tne
signaling process, P must walt. Otherwise, both P and wi11 be act
simultaneously within the monitor. Note, however, that an
both processes c
conceptually continue with their executlon. Two possibilities
exist:
1. P elther walts until 9 leaves the monitor, or
waits for another cond n
2. Q elther waits until P leaves the monitor,
or waits for another condiu
process 8ynchronisatlon 91

Entry queue

Queues assoclated
with XY
conditions
Shared Data
HHHHHI
O0--
Operations

Initialisation Code

Figure 3.3 Monitor with condition variables

There are reasonable arguments in favor of adopting elther option or option


1

2. Since P was already executing in the monitor, cholce 2 seems more reasonable.
However, if we allow process P to continue, the "loglcal" condition for which 9 was
waiting may no longer hold by the time 9 is resumed.

Chotce 1 was advocated by Hoare, mainly because the preceding argument


n
favor of it translates directly to simpler and more elegant proof rules. A
compromise between these two choices was adopted in the language Concurrent
c. When process P executes the signal operation, process is immediately resumed.
This model is less powerful than Hoare's, because a process cannot signal more
han once during a stngle procedure call.

Let us illustrate these concepts by presenting a deadlock-free solutlon to


he dining-philosophers problem. Recall that a philosopher is allowed to pick up
ner chopsticks only if both of them are available. To code this solution, we need to.
distingutsh among three states in which a philosopher may be. For this purpose,
we introduce the following data structure:

enum thinking, hungry, eating} statel5

Philosopher 1
can set the varlable state [1] = eating only if her two neighbors
are not eating: (state I(t+4) % 5) 1= eating and (statell+1) % 5] 1= eating. We also
need to declare

Condition seli{5
Process synchronla

philosopher i can delay herself when she is hungry, but is unable to


opsticks she needds. dbta

We are now in a position to describe our solution to the dining-phil


dining-philos
n.

monitor dp

enum fthinking, hungiy, eatingi statel51; condition sell15


void pickuplint i) state[lil= hungry: test ();
{

if (statellEeating) selfil wait0:

void putdownint i

statelil thinking: testi + 4] % 5); testi +165);

votd testlint i}

1statelli +4)% 51 eatung &8


(statelil==hungryl &&.

(stateli + 1) 6 5] 1=eating))

statelil = eating:
selflsignal0

Toid tnit0

for int i 0is5i


statefilthlnking
93
process 8ynchronisation
Operation pickup. This may result in the suspenston of the philosopher process.
After the successul completion of the operatlon, the philosopher may
eat. Folowing8
this. the philosopher invokes the put-down operation, and may start to think. Thus,
philosopher 1 must invoke the operations pickup and putdown in the following
sequence

P.plckup(1):
eat
dp.putdown():

It is easy to show that this solution ensures that no two nelghbors are eating
simultaneously, and that no deadlocks will occur. We note, however, that it is
possible for a philosopher to starve to death. We shall now consider a possible
implementation of the monitor mechanism using semaphores. For each monitor, a
semaphore mutex (initialized to 1) is provided, A process must execute walt (mutex)
before entering the monitor, and must execute signal (mutex) after leaving the
monitor.

Since a signaling process must wait until the resumed process either leaves
or waits, an additional semaphore, next, is introduced, initialized to 0,. on which
the slgnaling processes may suspend themselves. An integer varlable i next_count
will also be provided to count the number of processes suspended'on next. Thus,
each external procedure F will. be replaced by.

wait (mutex.);
body of F
if (next_count> 0)
signalnext:
else
signal(mutex):
Mutual exclusion within a monitor is ensured.:

We can now describe how condition variables are implemented. For each
condition x, we introduce a semaphore xsem and an integer varlable x_count,
both initialized to O. The operation x.wait can now be implemernted as

X_count++
if (next_count> 0)
signalnext:
else
signal(mutex);
wait (x_sem);
X_count-;

The operation x.signal 0 can be implemented as


94
PrOcee Synchron
if x_count> 0) aluuu

next_count++;
signal (x_sem):
wait{next):
next_count--;

This implementation
is applicable to the definitlons of
both Hoarè and Brinch-Hansen. monitors gven

We turn now to the subject


of process-resumption order within monit
several processes are suspended on a nltor
condition x, and an x.signal operati
executed by some process, then how do we tion
processes should be resumed determine which of the suspend
next? One simple solution is to use a susper
so that the process FCFS orde
walting the longest is resumed first. In many
however, such a simple scheduling circumstan
scheme is not adequate. For this purposence
conditional-wait construct can be used; it se, th
has the form

x.wait(c)
where c is an integer expression that
is evaluated when the wait operatlon
executed. The value of c which is called a
name of the process that is suspended. priorlty number, is then stored with t
When x.signal is executed, the proces
with the smallest associated priority
number is resumed next.

QUESTIONS
1. What is meant by cooperating processes?
2. What is process synchronization?
3. What is race condition?
4 Define critical section.
5. How to achieve mutual exclusion?
6. What are the requirements to solve critical
section problem?
7 Write an algorithm to solve critical section
problem.
8. What are the problems faced in critical
section problem?
9. Write an algorithm for solving producer and consumer
problem.
10. Explain bakery algorithm.
11. What is the hardware solution for process synchronization?
12. Explain TestAndSet instruction.
13. How mutual exclusion is achleved using testandset instruction?
96
Process 8ynchronisatlon

14. What ls swap instructlon?


16. How mutual excluslon is achieved uslng swap instruction?
16. What are the disadvantages of testandset instruction?
17. What is semaphore?
18. What is counting semaphore?
19. What is binary semaphore?
20. How mutual excluslon is achieved using semaphore?
21. What are the problems with semaphores?
22. Explain binary semaphores?
23. Solve the bounded buffer problem using semaphores.
24. Explain how readers and writes problem solved with semaphores.
25. Give the solutton to dining philosophers problem using semaphores.
26. What is critical reglon?
27. How the problem of semaphores can be solved using critical regions?
28. What is monitor?
29. Give the syntax of a monitor.
30. Explain monitor.
31. What are condition variables in monitor?
32. Explain the monltor solution to dining phllosophers problem.
33. What are the advantages of monitors?

EXAMINATION QUESTIONS

1. Discuss the dining philosopher's problem for synchronization.


February 2002

2. Write short notes on interprocess communication.


August-September 2002

3. Explain semaphores and the operations that can be performed on it.


January 2003
4. Discuss process synchronization. June 2003

5. Explain semaphore. June 2003

6. Write short notes on:


1) Semaphores January 2004
11) Medium term scheduler January 2004

7. Write short notes on Semaphores. June 2004


96
PrOcess
8. Synchronlat-
Explain semaphores in brief. Nov-Dec 2004
9. EXplain in detall any one of the classical problem process
with its solution. ol synchront
Nov-Dec 2004
10. Write short notes on Semaphores. Nov-Dec 2005
Explain the need for the synchronization with examples.
Nov-Dec 2006

*12. Explain the role of a semaphore and its types. Nov-Dec 2006

7
CHAPTER 4

DEADLOCK

EXAMPLES OE DEADLOCK

INDEEINITE PosTPONEMENT
SYSTEM MODEL
DEADIoCK CHARACTERIZATION
Necessary Conditions
Resource Allocation Graph
METHoDS FOR HANDLING DEADLOCKS
DEADLOCK PREVENTION

DEADLOCK AVODANCE
Safe Stafe
Resource Alocation Graph Algorithm
Bankerte Algorithm
DEADIOcK DETEeTION
Stngle nstance of EachiRCSource Type
Detection-Algorithm Usago
RECOVERY FROM DEADLoCK
RrocessTerminaton
ResomrcPrecmpton

You might also like