Professional Documents
Culture Documents
Concurrencia PDF
Concurrencia PDF
Concurrencia PDF
Concurrent
Programming
M . Ben-Ari
Tel-Aviv University
London
Toronto
N ew Delhi
W ellington
ISBN
0-13-?010?fi-A
109876543
CONTENTS
Preface
xiii
xv
18
Introduction
18
Mutual Exclusion 19
Correctness 20
Timing 22
Implementing Primitive Instructions 24
Concurrent Programming in Pascal*S 26
Summary 27
Exercises 28
10
CO N ItN TS
29
3.1 Introduction 29
3.2 First Attem pt 30
3.3 Second Attempt 32
3.4 Third Attempt 34
3.5 Fourth Attempt 36
3.6 D ekkers Algorithm 38
3.7 A Proof of Dckkers Algorithm
3.8 Conclusion 43
3.9 F.xereises 43
S em aphores
40
SO
-..1
M u iu a i tA ^iusior.
4.3
4.4
4.5
4.6
4.7
M onitors
5.1
5.2
5.3
5.4
5.5
5.6
5.7
5.8
58
73
Introduction 73
Definition of Monitors 75
Simulation of the Semaphore 78
The Readers and Writers Problem 80
Proving Properties of Monitors 83
The Simulation of Monitors by Semaphores
Unrestricted Signals 88
Exerciscs 90
5!
93
Introduction 93
The Accept Statement 94
The Select Statement 99
Proving Properties of the Rendezvous
Exerciscs 105
105
86
CONTE N'IS
T h e D in in g P h ilo s o p h e r s
109
A. I
A.2
A.3
A.4
A .5
A.6
A .7
A.#
fnlrodiicljun 119
The Compiler 120
The P-Code 121
Procedure Calls 124
Concurrency 129
Semaphores 132
Random ^aiion
133
Program Listing 133
Bibliography
165
Textbooks
165
Sources 165
Index
171
119
115
XI
PREFACE
C oncurrent program m ingthe program m ing tools and techniques for deal*
ing with parallel processes has traditionally been a topic in operating
systems theory texts. T h ere are several reasons why concurrent program
ming deserves a book o f its own and should be the core of an advanced
com puter science systems course:
1. C oncurrent program m ing is what distinguishes operating systems and
real-tim e systems from o th er software systems. C om puter scicnce stu
dents who have taken courses in program m ing, d ata structures, com pu
ter architecture and probability can easily m aster the applications of
these disciplines in operating systems, but they need to be introduced to
techniques that will enable them to deal with parallelism.
2 . I d o u b t if m a n y o f m y s t u d e n ts w ill e v e r d e s ig n o r c o n s tru c t a m u ltip ro
c e s sin g tim e -s h a r in g sy s te m w h e re a lg o r ith m s f o r p a g in g a n d sc h e d u lin g
a r e o f p rim e im p o r ta n c e . I a m c e r ta in th a t th e y w ill b e d e s ig n in g a n d
c o n s tru c tin g r e a M im e sy s te m s f o r m in i- a n d m ic r o c o m p u te rs . A s o u n d
k n o w le d g e o f c o n c u r r e n t p r o g ra m m in g w ill e n a b le th e m t o c o p e w ith
r e a l-tim e sy s te m s in p a r tic u la r w ith th e s e v e re re lia b ility r e q u ir e
m e n ts th a t a r e im p o s e d .
3. T here isa trend tow ards increasing use o f abstract concurrency that has
nothing to do with the parallelism o f actual systems. D ata flow diagrams
used in softw are engineering are nothing m ore than netw orks o f concur*
rent processes. T raditionally, such a design must be im plem ented in a
sequential language, but UNIX* is a program m ing system which
encourages the use of concurrent processes. Ada*, the new language
designed for the U.S. D epartm ent o f D efense, includes concurrent
program m ing features as an integral p art o f the language.
t U N IX is a tradem ark o f Bell L aboratories.
J A da is a trad em ark o f the U nited S tates D ept, o f Defense.
xiii
Kiv
PRbhACE
ACKNOWLEDGEMENTS
tv
WHAT IS CONCURRENT
PROGRAMMING?
1.1
FR O M S E Q U E N T IA L T O C O N C U R R E N T P R O G R A M M IN G
0. I, 2
A simple complexity analysis will now show ihat even w ithout help of
colleagues, the parallel algorithm can still be more efficient th an the sequen
tial algorithm . In the inner loop o f an interchange sort, there arc (n-~ l ) +
( n - 2 ) + . . . + ! ( / - 1)/2 com parisons. This is approx. n 3/ 2. To sort n /2
CHAP. I
program sortprogram ;
const n = 40;
var a: array[ 1..n] of integer;
k: integer,
procedure sort(low,high: integer);
var
i,j, tem p; integer;
begin
for i:= low to high - 1 do
for j := i +1 to high do
if a[j] < a[i] then
begin
tem p := a[j];
a [j]:= a [i]
a [ j ] := te m p
end
end;
begin {* m ain program *}
for k
:=1 to n do read (a[k]);
sort (1,n );
for k: = 1 to n do write (a[k])
end.
F ig. l . l .
elem ents, however, requires only ( n /2 ) 2/2 = n 2/ S com parisons. Thus the
parallel algorithm can perform the entire sort in twice n2/ 8 = n2/ 4 com pari
sons to sort the two halves plus another n com parisons to m erge. The table in
Fig. 1.2 dem onstrates th e superiority o f the new algorithm . T he last column
shows th at additional savings can be achieved if the two sorts arc perform ed
simultaneously.
n
40
100
1000
n 2/ 2
(n2/ 4 ) + n
(n 2 /8)+ n
800
5000
S00 000
440
2600
251 000
140
1350
126 000
Fig. 1.2.
SECT- I i
f r o m s e q u e n t ia l t o c o n c u r r e n t p r o g r a m m in g
program sortprogram ,
const n = 20;
twon = 40;
var a: array[1..twon] of integer;
k: integer,
procedure sort{low , high: integer);
(* as before *)
procedure m erge(low, m iddle, high: integer);
var co u n t1, co u n t2 . integer;
k , in d ex1, index 2: integer;
begin
c o u n t1 := low ,
count2 := m id d le;
while count 1 < m iddle do
if a[count1] < a[count2] then
begin
write (a[count1]);
count1 : = c o u n t 1+ 1;
if c o u n t1 > = m iddle t hen
for index2 : = count2 to high do
write(a[index2])
end
else
begin
write (a [ c o u n t2 ] );
count2 : = count2 + 1;
if count2 > high then
begin
for index1 : = c o u n t1 to m id d le- 1 do
write
c o u n t 1 : = m iddle (* terminate *)
end
end
end;
begin (* m ain program *)
for k := 1 to tw on do read (a[k]);
sort( l , n);
so rt(n + 1, tw o n );
m erge(1, n + 1 , tw on)
end.
F l* . 1.3.
CHAR I
The program s o f Figs. 1.3 and 1.4 a re identical ex cep t for the
cobegin-cotnd in Fig. 1.4. T here would be no need for both versions if the
definition o f cobegin-cocnd was modified. Instead o f requiring th at the
procedures be executed in parallel, cobegin-coend becom es a declaration
that the procedures m ay be executed in parallel. It is left to the im plem enta
tionthe system hardw are and softw are to decide if parallel execution will
be done. Processors may be added o r rem oved from the system without
affecting the correctness of the program only the tim e th at it would take to
cxccuic iIk; program.
T he word concurrent is used to describe processes that have the poten
tial for parallel execution. We have shown how an algorithm can be
im proved by identifying procedures th at may be executed concurrently.
While the greatest im provem ent is obtained only under true parallel execu
tion. it is possible to ignore this im plem entation detail w ithout affecting the
superiority o f the concurrent algorithm o v er the sequential algorithm,
1 .2
C O N C U R R E N T P R O G R A M M IN G
C oncurrent program m ing is the name given to program m ing notations and
techniques for expressing potential parallelism and for solving the resulting
synchronization and com m unication problem s. Im plem entation o f parallel
ism is a topic in com puter systems (hardw are and softw are) th at is essentially
SCC I. 1.2
CONCURRENT PROGRAMMING
Initially
Colleague 1 cxcltangcs
Collcaguc2 cxchangcs
You merge
You merge
You merge
C olleague)
Coltcague2
You
4 . 2. 7. 6 . 1
8. 5, 0, 3, 9
8, 5, 0, 3. 9
5. 8. 0, 3. 9
_
-
2. 4, 7, 6 , 1
2. 4, 7, 6. 1
,,
..
2
2 .4
2. 4. 5
F ig. 1.4.
K g . 1.7.
Parallelism is im portant not only for the im provem ent that can be
achieved in program perform ance but also in program quality. C onsider the
CHAP. I
* ----------
" ----------
**........
OUTPUT
cards
Processes P | ,
1 .3
CO RRECTNESS OF C O N C U R R E N T PR O G R A M S
1.4
IN TE R LE A V IN G
1 .4
IN T E R L E A V IN G
CHAP 1
THE O R IG IN OF O P E R A TIN G S Y S T E M S
II
SfcCT I 5
M liim
iiiJ E M
iL iM
a M
T M
I T f r
see that (he m anual procedures that must be perform ed m ounting tapes,
selling up card decks, o r changing places at th e consolearc disjoint from
the actual com pulation and can be perform ed concurrently with (he com pu
ter's processing.
T he sccond generation o f com puters used a supervisor program to
butch jobs. A professional com puter o p erato r sat at the console. Program
m ers prepared card decks which were concatenated into batches" that were
fed into the com puter once an hour or so. The increase in throughput (a
m easure o f the efficiency o f a com puter; ii is the num ber of jobssuitably
w eighted thai can be run in a given tim e period) was enorm ousthe jobs
were run one after another with no lost m inutes. The program m ers, how
ever, Inst the ability to dynamically track th e progress of th eir program s since
they no longer sat at the com puter console. In the event of an error in one
job, (he com puter simply com m enced execution o f the next jo b in Hie batch,
leaving the program m er (o puzzle o u t w hat happened from core dumps.
With h turnaround time (the am ount of time that elapses between a job
being subm itted for execution and th e results being printed) of hours or
days, the task of program m ing became more difficult even though certain
aspects were im proved by high-level languages and program libraries.
D espite this im provem ent in throughput .system s designers had noticed
another source o f inefficiency not apparent to the hum an eye. Suppose that a
com puter can cxccute one million instructions p er sccond and that it is
connected to a card reader which can read 300 cards per m inute ( = one card
in 1/5 second). T hen from the time the read instruction is issued until the
time the card has been read , 200 0 0 0 instructions could have b een executed.
A program to read a deck o f cards and print the average of the numbers
punched in the cards will spend over 99 % of its tim e doing nothing even
though 5 cards per sccond seem s very fast.
The firsl solution to (his problem was spooling. The I /O speed o f a
magnetic (ape is much greater th an that o f the card read er and the line
printer that are the interface betw een the com puter and the program m er.
We can decom pose the operation of the com puter into three processes: a
process to read cards to tape; a process lo cxecute the program s on the tape
and wrile the results onto a second tape; and a process to print the inform a
tion from (he second tape. Since these processes are disjoint (cxcept for the
exchange o f the tapes after processing a batch), the throughput can be
greatly increased by running each process on a separate com puter. Since
very simple com puters can be used to transfer inform ation to and from (he
magnetic tape, the increase in cost is not very great com pared lo the savings
achieved by more efficient use of the main com puter.
L ater generations of com puter systems have attacked these problems
by switching the com puter am ong several com putations whose programs
and data are held sim ultaneously in memory. This is known as m ultiprog
ramming. While I / O is in progress for program P, the com puter will execute
"
"
'
10
CHAP. 1
1 .6
O PE R A TIN G S Y S T E M S A N D C O N C U R R E N T P R O G R A M M IN G
If you could sense the operation of a com puter thai is switching itself every
few milliseconds am ong dozens o f tasks you would certainly agree that the
com puter seem s to be perform ing these tasks sim ultaneously even though
we know that the com puter is interleaving the com putations of the various
tasks. I now argue th at it is m ore than a useful fiction lo assum e that the
com puter is in faci perform ing its tasks concurrently. To see why this is so, let
us consider task switching in greater detail. Most com puters use interrupts
t A tim e-sharing system is a com p uter system th at allows many program m ers to
work sim ultaneously at teim inats. E ach program m er m ay w ork under the
illusion (hat ihe co m p u ter is w orking for him alone (though Ihe co m p u ter may
seem lo be w orking slowly if loo m any term inals are connccted).
SECT I 6
II
for this purpose. A typical scenario for task switch by interrupts is as follows.
Program
m akes a read request and then has its execution suspended. 11k
CPU may now cxccute program Pt . W hen th e read requested by P, has been
com pleted, the I /O device will interrupt the execution of Pt to allow the
operating system to rccord the com pletion o f the read. Now the execution of
cither P, or Pt may be resum ed.
The interrupts occur asynchronously during the execution of programs
by the C PU . Oy this is m eant that ihere is no way o f predicting o r coordinat
ing the occurence of the interru p t with the execution o f any arbitrary
instruction by the CPU. For exam ple, if the o p erato r who is m ounting a
magnetic tape happens to sneeze, it may delay the tape read y " signal by
8.254387 seconds. I low cvcr, if he is slow" with his handkerchief, the delay
might be 8.254709 seconds. Insignificant as that difference may seem, it is
sufficient for the CPU lo execute dozens of instructions. T hus for all practi
cal purposes it m akes no sense lo ask: W hat is the program that the
com puter is executing?" The com puter isexecuting any one o f a vast number
of execution sequences that may be obtained by arbitrarily interleaving the
execution of the instructions of a num ber of com puter program s and I/O
device handlers.
This reasoning justifies the abstraction th at an operating system consists
of many processes executing concurrently. The use o f the term process
rather than program em phasizes tin; fact that we need not differentiate
betw een ordinary program s and external devices such as term inals. They are
all independent processes that may, how ever, need to com m unicate with
each other.
T he abstraction will try to ignore as many details of the actual applica
tion as possible. For exam ple, we will study the p roduccr-consum er problem
which is an abstraction both of a program producing d ata for consum ption by
a printer and of a card reader producing data for consum ption by a program.
The synchronization and com m unication requirem ents are the same for
both problem s even though the details of program m ing an input routine are
rather different from the details o f an o utput routine. Even as new I/O
devices are invented, the input and output routines can be designed within
the fram ew ork of the general producer-eonsum er problem .
O n Ihe other hand, we assume th at each process is a sequential process.
It is always possible to refine the description of a system until it is given in
term s o f sequential processes.
The concurrent program m ing paradigm is applicable to a wide range of
systems, not just to the large m ultiprogram m ing operating systems that gave
rise to this viewpoint. M oreover, every com puter (except perhaps a cal
culator or the simplest m icrocom puter) is executing progam s that can be
considered to be interleaved concurrent processes. M inicom puters are sup
plied with small m ultiprogram m ing systems. If not, (hey may em bedded in
12
CHAP. I
A N O V E R V IE W OF TH E BOOK
Within the overall context of writing correct software this book treats the
single, but extrem ely im portant, technical point of synchronization and
communication in concurrent program m ing. T he problem s are very subtle;
ignoring the details can give rise to spectacular bugs. In C hapter 2 we shall
define the concurrent programming abstraction and the argum ents that
justify each point in the definition. The abstraction is sufficiently general
that it can be applied w ithout difficulty to real systems. O n the o ther hand it
is sufficiently sim ple lo allow a precise specification of both good and bad
behavior o f these program s.
Form al logics exisl which can form ulate specifications and prove prop
erties o f concurrent program s in this abstraction though we will limit o u r
selves to informal o r at most semi-formal discussions. The fact th at the
discussion is inform al must not be construed as m eaning th at the discussion is
imprecise. A m athem atical argum ent is considered to be precise even if it is
not formalized in logic and set theory.
The basic concurrent program m ing problem is that o f m utual exclusion.
Several processes com pete for the use o f a certain resource such as a tape
drive but the nature of the resource requires that only one process at a time
actually accessed the resource. In o th er words, the use of the resource by one
process excludes o th e r processes from using the resource. C hapter 3 pre
sents a scries of attem pts to solve this problem culm inating in the solution
known as P c k k e r's algorithm . The unsuccessful attem pts will each point out
a possible "b a d behavior of a concurrent program and will highlight the
differences betw een concurrcnt and sequential programs.
D ekkcrs algorithm is itself too complex to serve as a model for more
complex program s. Instead, synchronization primitives are introduced. Just
as a disk Tile can be copied o n to tape by a single control language com m and
t W hciircas a lim e-sharing system gives the usei live ability to use all (he
resources o f a com puter, the term real-tim e system is usually restricted to
system s th at arc required to respond to specific pre-dcfincd requests from a
user o r an external sensor. Exam ples w ould be air-traffic control system s and
hospital m onitoring systems.
M A T. 1.7
13
or a file can be read by writing read in a high level language, so we can define
programming language constructs for synchronization by th eir semantic
definitionwhat they are supposed lo d o and not by their im plem enta
tion. Wo shall indicate in general term s how these primitives can be
im plem ented but the detail* vary so much from system to system that to fully
describe them w ould defeat our purpose o f studying an abstraction. H ope
fully. it should be possible for a ''casu al systems program m er to write
concurrcni program s w ithout knowing how the prim itives arc implemented.
A model im plem entation is described in the Appendix.
C hapter 4 com m ences the study of high level prim itives with E. W.
D ijkstras sem aphore. T he sem aphore has proved extraordinarily successful
as the basic synchronization primitive in term s of which all others can be
defined. The sem aphore has bccomc the standard of com parison. It is
sufficiently powerful that interesting problem s have elegant solutions by
sem aphores and it is sufficiently elem entary that it can be successfully
studied by formal m ethods. T he chaptcr is based on the producer-consum er
problem m entioned above; the mutual exclusion problem can be trivially
solved by sem aphores.
Most operating systems have been based on monolithic monitors. A
central executive, supervisor o r kernel program is given sole authority over
synchronization. M onitors, a generalization o f this conccpt formalized by
H oarc, arc the subject o f C hapter S. T he m onitor is a powerful conccptua!
nolion that aids in the developm ent of well structured, reliable programs.
The problem studied in this chapter is the problem o f the readers and the
writers. This is a variant of the m utual exclusion problem in which there arc
two classes of processes: w riters which need exclusive access to a resource
and readers which need not exclude one another (though as a class they must
exclude all writers).
The advent of distributed systems has posed new problem s for concur
rent program m ing. C. A. R. Ilo arc has proposed a m ethod of synchroniza
tion by com m unication (also known as synchronization by rendezvous)
appropriate for this type of system. T he designers o f the Ada programming
language have chosen to incorporate in the language a variant of H oares
system. A nticipating the future im portance of the A da language. C hapter 6
studies the A da rendezvous.
A classic problem in concurrent program m ing is (hat of the Dining
Philosophers. T hough the problem is o f g reater entertainm ent value than
practical value, it is sufficiently difficult to afford a vehicle for the com pari
son o f synchronization primitives and a standing challenge to proposers of
new systems. C hapter 7 reviews the various primitives studied by examining
solutions to the problem of (he Dining Philosophers.
Program m ing canno( be learned w ithout practice and concurrent pro
gram ming is no exception. If you are fortunate enough to have easy access to
ClIAP. I
PR O C R A M N O T A TIO N
The exam ples in the text will be w ritten in a restricted subset o f Pascal*
S, which is itself a highly restricted subset of Pascal. T his subset must of
course be augm ented by constructs for concurrent programming. It is
intended th at the exam ples be legible to any program m er with experience in
Pascal, A da, C, A lgol, o r P L /I.
The im plem entation kit in the A ppendix describes an interpreter for
this language that will execute the exam ples and that can be used to program
the exercises. The language in the kit contains m ore Pascal language features
than arc used in th e text o f the book and thus users of the kit are assumed to
be able to program in sequential Pascal. These extra features are necessary
in o rd er to use the kit to solve the exercises, although the exercises them
selves could be program m ed in o th er languages th at provide facilities for
concurrent programming.
The exam ples in the chapter on m onitors are standard and can be
adapted to the m any systems that provide the m onitor facility such as
C oncurrent Pascal, Pascal-Plus, or C S P /k. The exam ples in the chapter on
the A da rendezvous are executable in A da.
We now present a sketch of the language that should be sufficient to
enable program m ers unfam iliar with PasCHl to understand the examples.
1. C om m ents are inserted betw een ( and ).
2. The first line in a program should be
program name;
3. Symbolic nam es for constants may be declared by the word const
followed by the constant itself:
const rw'O/i*40;
4. All variables in each procedure in the main program must be declared
by the word v ar followed by the nam es o f the variables and a type:
var i, j, temp: integer,
fo u n d : boolean;
SECT. I $
PROGRAM N O IA IIO N
IS
The available types are : integer, boolean (with constants true and false)
and arrays:
var a:rr%y{lo\vindex...highindex] of integer;
5. Following tltc declaration of the variables, procedures and functions
may be declared: procedure nam e ( fo rm a l parameters ); and func*
lion nam e ( fo rm a l parameters ): retu rn typ e,. The formal param e
ter definition has the same form as that of a variable list:
procedure sort (low .high: integer)-,
function lust(index: integer): boolean)
6. The body of the main program o r of procedures is a sequence of
statem ents separated by sem i-cotons betw een begin and end. The main
program body is term inated by a period and the procedure bodies by
sem icolons. T he usual rules on nested scopes apply.
7. The statem ents are:
assignment statement
If boolean -expression then statement
if boolean-expression then statement else statement
for index-variable : = low index to highindex do statement
while boolean-expression do statement
repeat sequence-of-statements until boolean-expression
The syntactic difference betw een while and repeat is that while takes a
single statem ent and repeat takes a sequence of statem ents (separated
by semi-colons). The sem antic diffcrcnce is th at the while lests before
the loop is done and repeat tests afterw ards. Thus repeat executes its
loop at least once.
8. A sequence of statem ents may be substituted for siatem cn t" in the
above forms by enclosing the sequence of statem ents in the bracket
begin ... end to form a single com pound statem ent:
if c\j] < a{t] then
begin
tem p := a(/'];
a[j] : a[i];
[i] := temp
end
In detail this is read: If the boolean expression (c[j) < *[]) has the value
true, then cxccute the com pound statem ent which is a sequence of
three assignm ent statem ents. If the expression is false, then the (com
pound) statem ent is not executed and the execution continues with the
next statem ent.
16
W H A T IS CONCURRENT PR O G R AM M IN G
C HA P I
1 .9 E X E R C tS E S t
1.1
1.2
1.3
#
EXERCISES
1.4
17
Perform a similar analysis (or sonprogram. You will have to make some
assumptions on Ihe number of interchanges lhat will be done.
Run the program in Fig. 1.8 several times. Can you explain the results?
program increment',
const m 20;
var n: integer;
procedure incr;
var i: integer,
begin
for i :* 1 lo m do n : n+ 1
end;
bgin ( main program )
n : * 0;
cobegin
incr; incr
cuend;
writeln (' ihe sum is n)
end.
Pig. 1.8.
2 .1
THE CONCURRENT
PROGRAMMING ABSTRACTION
IN T R O D U C T IO N
SECT. 2.2
M U TU AL EXCLUSION
19
2 .2
M U T U A L E X C L U S IO N
20
CHAP. 2
tailed protocols before and possibly after (he critical section. These pro
to c o l will ensure that (he critical section is in fact executed so as to exclude
all other critical sccitons. O f course, just as (he critical section should be
short relative to the main program in order to benefit from concurrency, (he
protocols must also be relatively short. The protocols represent the over*
head paid for concurrency. Hopefully, if the critical sections and the pro*
tocols are sufficiently short (hen the significant processing abstracted as
remainder can he overlapped (hus justifying (he design o f the multipro
gramming system.
There is another, more im portant, reason for requiring loose connec
tion am ong concurrent processes and that is to ensure reliability. We want to
be assured (hat if ihere is a hug in one o f (he processes, then i( will not
propagate itself into a system "crash . It should also be possible 10 gracefully
degrade the perform ance of a system if an isolated device should fail ("fail*
soft ). It would be absurd to have a system crash just because one tape drive
becam e faulty.
T he abstract requirem ent will be that, if a process abnorm ally term i
nates outside the critical section then no o th er process should be affectcd.
(F o r this purpose the protocols are considered to be p art of the critical
section.) Since the critical section is where the com m unication is taking
place, it is not reasonable to require the same of (he critical sections. We
might use (he following m etaphor. If a runner in a relay race fell after he has
passed the baton then the race should not be affected. It is unreasonable to
hope that the race is unaffected if the fall occurred at the critical moments
during the baton exchange.
This restriction is not unreasonable even in practice. Critical sections
such as disk I/O will often be executed by com m on system routines or by
com piler-supplied routines which have been w ritten by a com petent systems
program m er. T he probability of a softw are e rro r in such a routine should be
much sm aller than in a run-of-the-mill program.
2 .3
CO RRECTNESS
.IfcCT. 2.3
CORRECTNESS
21
24
1 H I: C O NCURRENT P KO G R AM M IN C A B S IR A C IIO N
CHAP. 2
2 .5
IM P L E M E N T IN G P R IM IT IV E IN S T R U C T IO N S
O u r solu tio n s to the m utual exclusion p ro b lem will alw ays ch c a t by m aking
use o f m u tu al exclusion p rovided on a low er level th e hard w are level. Just
as the u ser of a high level language n eed not know how a co m p iler w orks as
long as he is p ro v id ed w ith an accu rate d escrip tio n o f the syntax and
sem antics o f the lan g u ag e, so we will no t co n cern o urselves w ith how the
hard w are is im p lem en ted as long a s we a re supplied w ith an accurate
descrip tio n o f the syntax an d sem antics o f the arch itectu re. Presum ably the
sam e thing h ap p en s a t low er levels th e c o m p u te r logic d esig n er need not
know exactly how an in te g ra te d circuit is im p le m e n te d ; the in teg rated circuit
desig n er need only co n ccrn him self w ith ihe elec tro n ic p ro p e rtie s o f sem i
co n d u cto rs an d n e e d not know all Ihe d etails o f the q u a n tu m physics th at
explain th ese p ro p ertie s.
In com m on m em ory system s th ere is an arbiter w hich p ro v id es for
m utual exclusion in th e access lo an individual m em ory w ord. T h e w ord
access is a g en eric term fo r read and w rite o r, as they a rc usually called.
L oad and S tore co rresp o n d in g to the a ssem b ler in stru ctio n s for these
actions. T he a rb ite r e n su res th at in case o f o v erlap am ong accesses, m utual
exclusion is o b ta in e d by ex ecu tin g th e acccsscs o n e a fter the o th er. T h e
o rd e r o f the acccsscs is n o t g u ara n te ed to the p ro g ram m er. O n th e o th er
hand, the consistency o f th e access is e n su re d as d escrib ed in C h a p te r 1.
N ote th at the access to a single w ord is a n action th a t m ay not be
a p p aren t in a high level language. Suppose th at n is a global v ariable th a t is
initially zero an d is used a s a c o u n te r by several p ro cesses executing the
S fctT. I 5
23
instruct ion: n : * + l.T h e com piler com piles such a statem en t into the three
assem bler instructions:
U>ad n
A dd I
Store />
C onsider now the follow ing scen ario . T h e value o f/i is 6. / ', executes L oad/t
jmd then f*3 also ex ecu tes L o u d /i. / , in crem en ts th e v alue o f/i in its interm it
register to o b tain 7. Sim ilarly,
o b ta in s th e v alue 7 in its in tern al register.
Finally, the tw o p ro ccssese x ec u te the S tore in stru ctio n in succession and the
value 7 is sto re d tw icc. H ence the final value o f n is 7. 'Ilia t is wc have
increm ented the value 6 tw ice an d have o b ta in e d 7.
C om m on m em ory a rb ite rs a rc found b o th o n m u ltip ro cesso r systems
am i o n single p ro cesso r system s w hose I / O e q u ip m e n t is c o n n e cte d fo r direct
m em ory access (D M A ). N orm ally a n I / O device w ould tra n sfe r each data
word to th e C P U for th e C P U to sto re in th e m em ory. H o w ev er, th is im poses
an unaccep tab le o v e rh e a d on the C P U . In stead , th e I / O device is given the
address o f a block o f m em ory. It o nly in te rru p ts (he C P U w hen the transfer
of th e w hole block is co m p leted . T h e re is an a rb ite r lo en su re th a t only one
device (o r the C P U ) h as access to ihe m em ory at any o n e tim e.
In this case we say th a l D M A is bein g im p le m e n te d by cycle stealing.
T h e m em ory is assum ed to be driven a t its m axim um access sp eed , say one
access p e r m icrosecond. E ach such access is also called a m em ory cycle. To
im plem ent D M A th e C P U is norm ally allow ed to co m p u te and access
m em ory. W hen a d a ta w ord arrives front an I / O device th e right to access
m em ory is u su rp ed from th e C P U a n d the device is allow ed to " s te a l" a
m em ory cycle. T h e re is no real o v e rh e ad . T h e m em ory cycle is needed
anyw ay to store the w ord an d w ith cycle stealing (h e C P U n eed n o t concern
itself w ith individual w ords.
Ilie co m p u te r h ard w are will be tru ste d to fu n ctio n pro p erly . W c only
concern o u rselv es w ith th e co rre ctn e ss o f the system softw are. T his is not
alw ays tru e o f coursc an d in practice o n e m ust be a le rt (o h a rd w a re malfunclion. O n e o f the m ost speclu cu lar bugs know n to th e A u th o r w as caused by a
hardw are faull that resu lte d in m ixing (wo m em ory ad d re sse s instead of
interleaving them . T h e net result w as a sto re o f d a ta in (he m ixed-up address,
an d (he presence o f foreign d a ta in th e se m em o ry ad d resses was never
explained by softw are specialists. F o rtu n a te ly th is so rt o f th in g rarely hap*
pens.
A n o th e r w ay o f using a co m m o n m em ory system is (o d efine a primitive
p ro ced u re call th a t is g u a ra n te e d to ex clude o th e r calls o f the sam e p ro ce
dure. T h at is, if tw o p rocesses try lo call Ihe sam e p ro c ed u re , only o n e will
succeed and the losing process will have lo w ait. A s usual it is not specified in
which o rd e r sim u ltan eo u s req u e sts are g ran te d .
26
CHAP 2
Sequential Pascal (and the subset used in this book) must be augmented by
concurrcnt programming constructs. The concurrent processes arc written
as Pascal procedures and their identity as concurrent processes is established
by their appearancc in the cobegin . . . coend s(a(emcnt
cobegin Px; P2; . . P coend.
A request for concurrent execution of several processes may appear only in
the main program and may not be nested. The semantics of the cobegin . ..
coend statement are specified as follows:
The cobegin statement is a signal to the system that the enclosed
procedures are not to be executed but are lo be marked for concurrent
execution. When the coend statem ent is reached, the execution of Ihe
main program is suspended and the concurrcnt processesare executed.
The interleaving of the executions of these processes is not predictable
and may change from one run to another. When all concurrent pro
cesses have terminated, then the main program is resumed at the
statement following the coend.
An additional notational device that we make use of is the statement
repeal . . . forever which is exactly equivalent in its semantic content with
repeat. . until/alse. However, the latter is rather obscure and wc prefer the
more transparent notation.
SECT. 2 *
27
2.7
SUM M ARY
28
T U t CONCURRfcNJ rM O C KA M M IN C ABSTRACTION
CHAP 2
2 .8 EXERCISES
2.1
2.2
3.1
IN T R O D U C T IO N
32
C H AP 3
3 .3
SECO NO A T TE M P T
K g . 3.3.
SCT. J.3
........... -
SECOND A T ll- M p r
33
while c , 0 do;
c ,:- 0 ;
eril ];
c. ;= J;
rem 1
forever
end;
p ro ced u re p 3\
begin
repeat
while c , = 0 do;
C2
0;
cm 2;
c,
I;
rem 2
forever
end;
begin (* m ain program *)
1;
Ci : * 1;
cobegin
PuPi
coend
end.
F it . 3 .4 .
c,
1
1
1
0
0
0
0
c
1
1
1
1
0
0
0
Since/*, and P2 are sim ultaneously in th eir critical sections, the program is
incorrect.
. . . e M U TU AL EXCLUSION PROBI EM
3 .4
CHAP. 3
T H IR D A T T E M P T
program thirdattempi;
var
c c2: integer,
procedure p x\
beg/n
repeat
c, := 0;
while C j=0 do;
crti 1;
Ci
1;
rem 1
forever
end;
procedure p };
begin
repeat
^2 " 0*>
while c, = 0 do;
c r itl;
< , : 1;
re m 2
forever
end;
begin ( m ain program *)
c, : 1;
Cj : * 1;
cobegin
p t.p i
coend
end.
Fit. 3.5.
Analyzing the failure of the sccond attem pt, we note th at, oncc P, has
ascertained th at P2 $ not in its critical section, P, is going to chargc right into
itscriticalscction. Thus, the instant that P , has passed the while statem ent. Pt
is in e ffe c t in its critical section. This contradicts our intention that c, * 0
should indicate that P, is in its critical section because there may be an
arbitrarily long wait betw een the while statem ent and the assignment
statem ent.
The third attem pt (Fig. 3 .5) corrects this by advancing the assignment
statem ent so that t , 0 will indicate th at P, is in its critical scction even
before itch e c k sc 3. Hcncc P, is in its critical section the instant that the while
has been successfully passed.
SECT. 3.
TH IR D AVILM P T
35
Initially
P, sets c,
P 2 sets e2
P, checks c 2
P2 checks C|
36
I l t r M U tU A l. EXCLUSION PROBLEM
CHAP J
F O U R TH A T TE M P T
program fourthattempt;
v ar Ct, Cji integer,
procedure p ,\
begin
repeat
c, := U;
while C j*0 do
begin
c , : = 1;
( do nothing fo r a fe w m om ents )
c , ;= 0
end;
crit I ;
c, := I;
rem 1
forever
end;
procedure p 2',
begin
repeat
c2 := 0;
while c, = 0 do
begin
Ci : I;
( do nothing fo r a fe w m om ents *)
c ,:- 0
end;
c r itl;
1;
retn2
forever
end;
begin (* main program )
c,
1;
Ci := 1;
cobegin
P i P i
coend
end.
SECT S.S
FOURTH A T I hM K l
37
1
0
0
0
0
1
1
0
0
1
I
0
0
0
0
I
1
0
It is d e a r that this could be indefinitely extended and that liveness docs not
hold because neither process will ev er e n te r its critical section. However, it is
extrem ely unlikely ever to occur. N evertheless we are forced to reject this
solution. The main objection here is not so much that n either process will
ever e n te r the critical section (it is unlikely that perfect synchronization
continues indefinitely) but that we have no way of giving an a priori bound
on the num ber of iterations that the loops will execute before they arc
passed. Thus we have no way o f guaranteeing the perform ance of such a
system.
Should this bug be classified as deadlock o r lockout? On the one hand,
both processes are looping on a protocol which is certainly not useful
com pulation and the situation is similar to (he previous attem pt. However,
we prefer to call this lockout to em phasize the following distinction. In the
previous attem pt the situation is hopeless. From the instant that (he program
is deadlocked, all future executions sequences rem ain deadlocked. In this
38
CHAP. 3
case however, the slightest aberration of the scenario will free one of the
processes and in practice (his will eventually happen. The key notion here is
the conspiracy betw een the processes and not the hopelessness o f the situa
tion. It is only because we wish to be able to guarantee a worst-case behavior
(hat we reject the current attem pt.
3 .6
OEKKER'S ALGORITHM
program
var
D ekker,
turn: integer,
c c2: integer;
procedure p x\
begin
repeat
c, := 0;
while c2 = 0 do
if turn * 2 (hen
begin
c, := 1;
while lu rn 2 do;
c ,:- 0
end;
cril 1;
turn := 2;
c, := 1;
rem I
forever
end;
procedure p t :
begin
repeat
c , := 0;
while C| 0 do
If tu rn * I then
begin
e , : 1;
while turn= 1 do;
c2
0
end;
crit2\
. turn : = 1;
c2 := 1;
rem2
forever
end;
SECT. i 6
D tK K b R 'S A I O O H IIIIM
3V
Fig. 3.8.
40
CHAP J
its critical section. U pon term in a tio n . P, n o t only frees the critical section by
se ttin g c , to I but also resets turn to 2 b o th to free Pt from Ihe in n e r loop anil
to tra n sfer the right to insist to Pt .
M utual exclusion is p ro v ed exactly a s in S ection 3.4 since the value of
turn has no cffect o n the decision to e n te r the critical section.
P roving livencss is som ew hat o f a ch allenge. S ym m etrically it is suffi
cient to prove th a t, if P x ex ecu tes c, : = 0 indicating its in ten tio n to e n te r the
critical section, th en ev entually il d o cs so. T his is d o n e in tw o parts. First we
prove th a t if P, a tte m p ts to e n te r its critical section but c a n n o t d o so,
eventually the v ariable turn is p e rm an en tly lield at (he value I . B ut if turn is
held perm an en tly a t 1 th en P, can alw ays e n te r its critical section.
3 .7 A P R O O F OF D E K K E R 'S A L G O R IT H M
Fig. 3.9
42
Theorem
CHAP 3
P roof
1. ( a 2 and never a , ) and (turn held at 2) imply eventually (c, held at 1).
Since (never a j) , Pt eventually passes a , and thence t o a 4. Since
(turn held at 2), P, reachcs <*6 and or* and is then blocked in the
loop at a #. By 11, as long as P, is at ora, c, must equal 1.
2. (c, held at 1) and (turn held at 2) imply eventually (turn 1).
The truth of the two clauses concerning c, and turn together with
the assum ption that processes arc not term inated implies that P2
must eventually reach 0 7 and assign the value 1 to turn.
But (turn held at 2 ) and eventually (turn - I) m eans that there
will be a point of tim e when turn is sim ultaneously 1 and 2. This
contradicts the consistency o f the values in the com m on memory.
From ( a 2 and never <*j) and (turn held at 2) we have deduced a
contradiction. Thus it must be that ( a 2 and never a s) implies
eventually (turn is not 2). Since turn * 2 or turn * 1 we have
proved.
3. (a 2 and never <*j) implies eventually (turn = 1 ).
4. ( a , and never a*) implies (never a s) and (never a T) and (never a ,) .
The only way to reach a , o r a Tfrom a 2 is to pass through a y But
wc assume that wc never reach a y
5. (a 2 a n d never a s) implies eventually (turn held at 1).
Once the value of turn is 1 (as ensured by (3 )) the only way that
the value can changc back to 2 is to execute a , . By 4 this will
never happen.
6. ( a , and never a , ) implies eventually (P , loops forever at o ,-o t4)By (4) and (5), cventuallyf(<r/r held at 1) and (P, is never at a s)].
H ence since P, must reach aj-ft fro m a ,,a r4o r a , it will then loop
forever at a j - a 4.
7. ( a 2 and never a*) im plies eventually (c, held at 0).
By (6), eventually we loop at j-ar4 which implies by 11 that ct will
be held at 0.
8. (c, held at 0) and (turn held at 1) imply eventually (cj held at 1).
Similar to (1): P 2 must eventually lo o p at/3 .T h en b y 12, c 2 is held
at 1.
9. ( a , and never a t ) implies eventually (c2 held at 1).
From (5), (7 ) and (8).
But (8) contradicts (6): if c2 is held at 1 then P, cannot be looping
seci.
CONCLUSION
43
at <k3- a 4. From ( a 2 and never a , ) we have deduced a contradiction. Thus ( a 2 and never a>) is false.
3 .8
C O N C L U S IO N
EXER CISES
3.! (DijksUa) Fig. 3.10 is u solution to the mutual exclusion problem for n processes
that is a generalization of Dckkers solution. .
(a) *Show that mutual exclusion holds.
(b) Show that deadlock does not occur.
(c) Show ihat lockout is possible.
44
CHAP 3
p ro g ra m Difksira;
const
= . . . ; ( n u m b er o f processes )
var
b , c: a rr a y (0 . . n ) o f
boolean,
turn: integer,
p ro c e d u re p ro cess(i : integer)',
v ar
/: integer-,
o k : boolean;
begin
rep eal
b(i]false;
rep eat
w hile tu rn < > i do
begin
<(j)
true;
i f b{lurn) Ihen turn := j
end;
c {/J : fa lse;
o k := true;
fo r j : m 1 lo a do
If / < > then
o k : =* o k a n d cf/'J
u n til o k ;
crit;
eCO lrue MO
,rue>
turn
0;
rent
fo rev er
end;
begin ( m ain program )
fo r turn : * 0 to n do
begin
b{turn] := true;
c\lu rn ) : = true
end;
turn : 0;
cobegin
p r tx e s s { \) ,
p roct4s{2);
process(n)
coend
end.
Fig. 3.10.
EXEKCISfcS 45
I;
fl, : n , + l;
while (si2 < > 0 ) a n d (n 2 < " ) do;
crit 1;
: 0 ;
rem I
forever
end;
p ro ced u re p 2;
begin
rep eat
2
/ij : f|+ I ;
w hile (/i, < > 0 ) a n d ( n , < - n 2) do;
c h /2 ;
/i2 : * 0;
r e tn l
forever
end;
begin ( m ain program *)
fl,
0;
n 2 := 0;
cobegin
P1 IP 2
coend
end.
Fig. 3.11.
46
CHAP 3'
program bakery,
var
f | . <2. i. j- integer,
procedure p t \
begin
repeat
e,
1;
i := 2+ l ;
c,
0;
Ci
fl, := 0;
n2
0;
cobegln
PuPl
coend
end.
Fig. 3.12.
3.4 Fig. 3.13 is a solution lo ih e m utual exclusion problem for two processes. Discuss
ihc correctness o f the solution: if it is corrcct, then prove it. If not. write scenarios
that show (hat the solution is incorrect.
Several sychronizaiion primitives that have been used are based on hardware
instructions th at enable several assignment statem ents to be executed as one
(indivisible) primitive instruction. The solutions to the m utual exclusion prob
lem using these primitives are very simple, but they rem ain busy wait algorithms
in contrast to algorithm s using the primitives to be studied in the next chapter.
E X tR C IS tS
;
t
f
:
47
program attempt',
var
e ,. cy. integer,
procedure />,;
begin
repeat
rem 1;
repeal
c,
I - c2
forever
end;
begin ( /nat'/i program *)
e,
1;
ct
1;
cobcgin
Pi i Pl
coend
end.
Fig. 3.13.
3.S The IBM 3 6 0 /3 7 0 com puters have an instruction called T S T (Test and Set).
There is a system global variable called e (Condition Code). Executing TST(i)
for local variable / is equivalent to the following two assignments:
I
c
c;
I.
(a) Discuss the correctness (safety, deadlock, lockout) o f the solution of the
m utual exclusion problem shown in Fig. 3.14.
(b) Generalize to n processes.
(c) W hai would happen if the primitive T S T instruction were replaced by the
two assignments?
(d) Modify the im plem entation kit lo include the T S T instruction.
48
CHAP. 1
p ro g ra m teu a n d iet,
var
c: integer,
p ro c e d u re /,;
var
/: integer;
begin
rep eal
r e m) ;
rep eal
7571(0
u n til / * 0;
crit 1;
c
0
fo rev er
end;
p ro c e d u re p i,
var
I: integer,
begin
re p e a t
rem2;
re p e a t
T 5 T (l)
u n til / = 0;
criQ ;
c
fo rev er
cad;
begin ( m ain program )
c : 0;
cobegin
Pi> P i
coend
end
llg . 3.14.
D iscuss the co rrectn ess (safety, d ead lo c k , lo ck o u t) o f the solu tio n fot
m u lu al exclusion show n in Pig. 3.15.
(b ) G en eralize to n processes.
(c ) W h at w ould h ap p en if the prim itive E X in struction w ere rep laced by the
ih ree assignm ents?
(d ) 'M o d ify th e im p lem en tatio n kii to include the E X instruction.
fcX K R C im
4V
p ro g ram exchange;
var
c: integer;
p ro ced u re p \;
v ar
/: integer;
begin
/ : 0;
rep eal
rem 1;
rep eal
E X (cj)
until / - 1;
crit 1;
E X {cj)
forever
end;
p ro ced u re p y,
var
/: integer;
begin
0;
repeal
re m 2;
rep eat
E X ( Cj )
u n lii I I;
m /2 ;
AT (c,/)
forever
end;
begin ( /noin pro gram )
c := I;
cobegia
P i; P i
coead
end.
Fig. 3.15.
4 .1
SEMAPHORES
IN T R O D U C T IO N
The scicntific study o f concurrent program s was given a decisive thrust with
the introduction o f the sem aphore by D ijkstra. Sem aphores are easy lo
im plem ent and yet sufficiently pow erful that they can he used to give elegant
solutions to concurrent program m ing problems. They can be used to define
or im plem ent more powerful structured primitives.
A sem aphore s is an integer variable which can take on only non-zero
values. Once s has been given its initial value, the only perm issible opera*
tions on s are to call the procedures wail(s) and signal(s) which are primitive
operations (the original notation is P(s) for wait(s) and K(j) for signal(s),
which are the first tetters of the corresponding w ords in D utch). T he defini
tion of these operations is as follows:
wait(s): U s > 0 t h e m := s - 1 else the execution o f the process that called
H'ait(f) is suspended.
signal(s): If som e process P has been suspended by a previous >v<m(;)on this
sem aphore s then wake up P else s : s + 1.
R em ark 1 If the sem aphore only assumes the values 0 and 1, it is called
a binary sem aphore. A sem aphore which can take arbitrary non-negative
integer values is called a general semaphore.
R emark 2 wail and signal are the only operations allowed. In particular,
assignm ents to s or tests of the value of s are prohibited except for an
assignment to s o f an initial non-negaiive value in the main program . (The
im plem entation kit does not enforce this restriction nor does it distinguish
binary from general sem aphores.)
Remark 3 We have defined the procedures as primitive operations.
This m eans that they exclude one a n o th er just as Load and Store to the same
50
SECT 4 i
M U TU AL EXCLUSION
$1
M U T U A L E X C LU S IO N
S3
CHAP 4
SEM A PH O RES
p ro c e d u re
p 2;
b e g in
re p e a t
wait(s);
cr/72;
signals);
re//i2
fo r e v e r
end;
Fig. 4.2.
'I
SECT. 4.2
M U TU AL EXCLUSION
53
another process can en ter even (hough (he first proccss has not actually
com pleted the execution of the wait. As an im plem entation detail, the
freezer ( queue o f suspended processes) must be large enough lo contain
the num ber of processes in the system o r at least the num ber o f processes
that may be wailing on (he sem aphore s.
U pon com pletion of the critical section, the signalling proccss enters the
igloo and releases a process from the freezer. If there are no such processes,
it simply chalks up a one to indicate that the critical section is free. In the case
of a binary sem aphore, a signalling process will always find a zero on the
board (why?). If (he blackboard o f a general sem aphore has any non-zero
number w ritten on it, ihe process can deducc th at the freezer is empty
(why?).
This solution to the m utual exclusion problem is very similar to one of
our earliest attem pts in the previous chapter in which we had the processes
pass the key to the critical section back and forth. We are saved from trouble
here by the fact that the testing of s and the selling of s to zero are
encapsulated in one primitive instruction. Thus if P, notes that s is I . it will
set 5 to 0 before P t has a chance to test the value of s.
M utual exclusion and absence of deadlock are easy to show from the
following property o f the program : s will have Ihe value zero if and only if
exactly one proccss is in its critical section. This can be formally proved as
follows. C onsider the value of the expression E ms + the num ber o f processes
in a critical section. C ertainly E m 1 at the start of the concurrent program
since j = 1 and no process is in a critical section.
Now use the following inductive argum ent. A ssum e that = 1 at any
point in any interleaved execution sequence. The execution sequence con
tinues by choosing to execute cither a step of P , or a step o f P ,. Wc argue by
inspecting the program that in any case the truth o f E - 1 is preserved. Hence
by induction, E - l is always true because any execution sequence is con*
structed starting from the initial state by successively choosing either a step
of P t or of P2. For exam ple, if E - 1 because there are no processes in the
critical scction and $ = l . P t can choose lo en te r the critical section by
executing wait(s). It leaves $ = 0 and num ber o f processes in the critical section
* 1, i.e. * 1 .
The form ula E m 1 is called an invariant of the com putation. Invariants
are proved by induction. The initial state of the com putation satisfies the
invariant and every transition between possible stales o f the com putation
preserves the truth o f the invariant. To prove this, wc assume the truth of Ihe
invariant as an induction hypothesis and Ihen chcck th at the invariant is still
true in the new state resulting from the transition.
Note that, even in this simple case, the full p roof is rath er tedious since
the induction step must be proved for every pair: (location o f P ,'s program
counter, location o f P 2*s program counter). O f course, most steps arc trivial.
54
SEMAPHORES
CHAP 4
The only ones needing any reasoning are executions of the sem aphore
instructions.
We are now in a position to prove the liveness of the solution.
Theorem (P , wishes to en ter crit 1) implies eventually (P , enters cm/1).
P roof
1. (P , wishes to en te r c rifl) implies eventually (P , enters c rifl) o r (P , is
indefinitely suspended because j * 0 ).
2. (P , is indefinitely suspended because x - 0 ) im plies (P 2 is in crit2).
This follows from the invariant E - 1 and the fact that tltere arc
only two processes P, and P 2.
3. (P 2 is in c ritl) implies eventually (P 2 executes *ig</($)).
Wc assum e that no process is term inated in its critical section.
4. (P j executes sig n a ls)) and (P t is indefinitely suspended because 4=0)
implies (P , en ters crirl).
See the definition of the signal operation.
5. (P , wishes to e n te r critX) implies eventually (P , enters cWfl).
The possibility that P, is indefinitely su sp e n d e d o n y = 0 has led to
a contradiction.
Remark N ote that in (4) we have tacitly used the fact that there are only
two processes. O therw ise we could not prove that P, enters its critical section
and not som e o th er process.
(A dvanced) Remark (4) of course does not hold under the busy-watl
definition of sem aphores. In fact lockout is possible under that definition if
the signalling process executes an o th er wait before the suspended process
notes t hat s > 0. H owever, fair sem aphores are sufficient to prove absence of
lockout though a proof such as o u rs would have to be invoked inductively so
that eventually some signal would in fact wake P,.
(E nd o f A dvanced Remark).
The niutal exclusion problem for processes is solved by the identical
program (Fig. 4.3).
procedure mutualexclusion;
const
num ber o f processes )
var x: (* binary *) sem aphore;
procedure process(i: integer);
begin
repeat
wait(s);
crit;
M U TU A L EXCLUSION
SKCT 4 2
55
sig n a ls);
rem
forever
end;
begin (* m ain program *)
s := J;
cobegin
process(l)',
proctss(2)\
process(n)
coend
end.
F ig. 4.3.
56
4.3
SEMAPHORES
CHAf. 4
produce record v\
b[in] := v ;
in := in f I
fo re v e r;
57
It. Many terminal system s require that com plete messages be transmilted
lead of individual characters. Even though both the producer and (he
insumcr may be working at (he sam e average rate, the artificial imbalance
used by blocking the data requires th at buffering be used.
For now, let usassum e that wc have an infinite buffer. In programming
Dotation (his can be expressed as an infinite array: fr[0],6(i].............The
producer can then simply pour his d ata into the buffer (Pig. 4.4) (m is a
global variable that counts Ihe num ber o f records produced). The consum er
on the other hand must assure that it is nol consuming from an empiy buffer
(Fig. 4.5) (out is a variable that counts th e num ber of records consumed).
Initially we set i r t - o u t - 0. Note that we have abstracted away many details
of the actual buffering process, in particular the structure of the records and
Ibc processing lo be d one with them. However, the m ain idea of buffering is
C aptured.
repeal
wail until in > our,
w : b{out],
out
out + 1;
consume record w
forever;
Fig. 4.5.
fe .
}; . >
OUT)
IN ]
Fig. 4.6.
Ix t s Min - o u t (Fig. 4.6). s is then the num ber o f records in the buffer.
What values can s lake? s is initially 0. s can increase and then decrease
arbitrarily except that if s reaches 0 ihen the consum er will refuse to reduce s
below 0. Instead it w aits until the producer places another value in the
buffer. If we arrange for the producer to force the consum er into immediate
consumption of this new value then 0 = w - o u / = ( m + l ) - ( o i + 1 ).
s behaves like a sem aphore. In fact the statem ent wait untii in > out in
the consum er can easily be im plem ented by waif(5) assuming th at signal(s) is
added to the producer to wake up the consum er. Thus a solution lo the
producer-consum er problem can be w ritten as show n in Fig. 4.7 (where we
have further abstracted the buffer m anipulations by append (to buffer) and
lake (from buffer)).
58
SEMAPHORES
p ro g ra m
var
p ro c e d u re
CHAP. 4
pruducerconsumer;
n: semaphore;
producer,
b e g in
re p e a t
produce;
append;
signal(n)
fo re v e r
end;
p ro c e d u re
consumer;
b e g in
re p e a t
waii(n);
take;
consum e
fo re v e r
end;
( main program )
n := 0;
b e g in
c o b e g in
producer; consum er
coend
end.
F t*. 4.7.
Thus the sem aphore can be viewed as counting the difference between
the num ber of signals sent by signal and the num ber of signals received by
wail. It is the m ere fact o f signalling that is being counted and not the contcnt
of the signal. A sem aphore can be im plem ented by a message passing system
though it is wasteful to use the fixed size message elem ent to transm it a null
message.
4 .4
M O RE O N THE P R O D U C E R -C O N S U M E R PROBLEM
ii
MORE ON H IE PRODUCER-CONSUMER PROBI liM
E C T 4.4
5V
producerconsumer;
n: semaphore,
p ro c e d u re
p ro g ra m
b e g in
re p e a t
produce;
waii(s);
append,
signal(s)\
signal(tt)
fo r e v e r
end;
p ro c e d u re
consum er,
b e g in
re p e a t
waii{n),
wail(s)\
take;
signal(s)\
consum e
fo re v e r
end;
b e g in * (*
m ain program *)
n := 0;
s := 1;
c o b c g in
producer, consum er
^
coend
end.
Fig. 4.9.
.
*
t
*.
1
60
SEMAPHORES
CHAP. 4
|C 1.4 4
61
procedure consumer;
var m: integer; ( a local variable )
begin
wait(delay);
repeat
wail(s);
take;
n := n - 1 ;
m : n \
sig n a ls);
consume;
if m = 0 then waii(delay)
forever
end;
begin (* m ain program )
n : 0;
s := 1;
delay
0;
cobegin
producer; consum er
coend
end.
H g . 4.9.
Nole the initial wait(delay) so that the consum er does not begin to
execute while the buffer is em pty. A lso, if the processes arc running at more
or less the sam e speed, n either is ever blocked on the sem aphore delay. This
is bccausc waii(delay) is executed only if the buffer is em ptied which need
not occur frequently. T he wait{delay) has been taken out of the M'ajy(j). . .
signal(s) bracket to avoid the previously discussed deadlock.
The new feature in the solution is the use of the local variable m to allow
the consum er to test the value of n as it was inside the criticial section, if the
statement in the consum er had read: if n = 0 then waii(delay) then the
following scenario shows that a superfluous signal can occur which leads to
consumption from an em pty buffer a flagrant breach o f safety. Define a
cycle of the producer (consum er) as execution o f the statem ents of the
producer (consum er) process from one occurrence o f the produce (consutne) to the next.
In the line m arked ( ) the consum er has skipped the wail in the state
ment if n s 0 then waii(delay) because even though it noted that n - 0 , the
producer has meanwhile increm ented n. The notation n - - 1 m eans that the
consumer has just consum ed an clem ent that is not there: - l * / ! = m - o u / s o
o u t- in + 1, i.e. the consum er has consum ed its (m + l)s t elem ent while the
producer has produced only in elem ents.
62
SEMAPHORES
A ction
Initially
Producer cycles
Consum er cxccutcs to consume
Producer cycles
C onsum er cycles
C onsum er cycles
CHAP. 4
n
0
1
0
I
0
-1
detay
0
1
0
1
If)
0
Using the local variable m , this bug will not occur (C heck!). Il is true
that (he consum er is m aking a decision based on stale inform ation: it could
be the case that, m eanw hile, the producer has produced a new element.
Then the consum er will execute waii{detay) and im m ediately pass it if the
producer has already signalled. The overhead of a superfluous wait is cer
tainly preferable to a violation of safety.
4 .6
TH E SLEEPING BARBER
There is another slight im provem ent that can be m ade lo this program . The
point of this discussion is not so much the im provem ent itself which may or
may not be significant. W hat is interesting is how a careful analysis o f the
synchronization requirem ent in a problem can lead to a different and better
solution. T he m oral of the story wilt be that before you decide to wait on a
sem aphore, you must clearly understand w hat you are waiting for.
Suppose we have the (com m on) case where the p ro d u cer and consum er
are running at roughly th e same speed. The scenario could be:
Producer: append-, signal; produce; . . . ; append; signal; produce; . . .
Consum er: consum e; . . . ; take; wait; consume; . . . ; take; wail; . . .
The producer always manages to append a new elem ent to the buffer and
signal during the consum ption o f the previous elem ent by the consumer.
This is not unreasonable since the processing to be done with the data is
assumed to be significant com pared with the buffer m anipulation and the
synchronization. The producer is always appending to an em pty buffer and
the consum er is always taking the last elem ent in the buffer; hence the
execution o fu g n a fa n d wait on every cycle. T hus even though the consum er
will never block o n the sem aphore, the processes nevertheless are executing
a large num ber o f calls to the sem aphore m echanism which does involve
non-negligible overhead.
In the program in Fig. 4.10, wc allow n to have the value - 1 which is lo
m ean that not only is Ihe buffer em piy but that the consum er has detected
this fact and is going to block until Ihe producer supplies fresh data.
SECT 4.S
63
program
var
sleepingbarber;
n\ integer,
j : ( binary ) sem aphore;
delay: ( binary ) sem aphore,
procedure producer;
begin
repeat
produce;
wait(s);
append;
n := + l ;
if n = 0 (hen signat(delay);
signal(s)
forever
end;
procedure consumer;
begin
repeat
H'Oif(j);
n :* / i - l ;
if n * - 1 then
begin
sig n a ls);
wait(delay);
W 'f l if ( j )
end;
take;
sig n a ls);
consum e
forever
end;
begin ( main program )
n := 0;
s := 1;
delay := 0;
cobegin
producer; consum er
coend
end.
F it- 4.10.
64
SEMAPHORES
CHAP 4
SECT 4 6
TH E SLEEPING B A K b L K
65
A lgorithm 4.1
B arber W hen you have finished w ith a cu sto m er, show him out and
check th e w aiting room . If th ere is a cu sto m er, escori him to the chair;
otherw ise, go to sleep in th e chair.
C ustom er W hen you e n te r the w aiting room : if (here arc o th e r custom
ers (hen join them . If not, o p en ihe d o o r to see if (he b a rb e r is busy; if so,
do se ih e d o o r and w ail your (urn. If th e b a rb e r is a sle ep th e n w ake him.
In A lgorithm 4 . 1. if the rale at w hich cu sto m ers e n te r m atches the rale
of (he b a rb e r's w ork th e n ev ery c u sto m er will find h im self alo n e in the
wailing room and will vainly o p e n th e d o o r only (o find th e b a rb e r at work.
This co rresp o n d s to th e m ore obv io u s so lu tio n to th e p ro d u cer-co n su m er
problem .
Algorithm 4.2
B arber A s b efo re, ex cep t fbai if th e w ailing room is em p iy ihen g o to
sleep on th e bench in Ihe w ailing room .
C ustom er If th e re are o lh c r cu sto m e rs o r if th e w ailing ro o m is em pty
then wait y our tu rn . If (he b a rb e r is sleeping in th e w ailing ro o m th en wake
him.
In A lgorithm 4 .2 . a cu sto m er will w ail w ith o u t o p en in g Ihe d o o r to no
avail. E ventually the b a rb e r will finish w iih th e p rev io u s cu sto m er a n d invile
ihe new o n e in. O nly if Ihe b a rb e r is actually w ailing (sleep in g ) will a
custom er have to w ake him.
4 .6
r
66
CHAP 4
SEMAPHORES
o ir rf
,1
<
-fife '*
IN |
OUT [
(b)
FI*. 4.13.
P roducer
C onsum er
FI*. 4.14.
SECT. 4.6
A7
boundedbu/fer,
sizeofbuffer * . . . ;
s: (* binary *) sem aphore;
rt: semaphore-,
e: sem aphore;
procedure producer;
begin
repeat
produce;
wait(e)\
wa'u{s)\
append;
'sig n a lly ,
signal(/t)
forever
end;
procedure consum er,
begin
repeat
wau(n);
watt(sy,
take-,
signals)-,
signal(e)i
consum e
forever
end;
68
S tM A H H O R E S
C IIA P 4
beg in ( m a in p ro g ra m )
s : 1;
0;
e : size o fb u ffe r ;
co begin
p r o d u c e ; c o n su m e
coend
en d .
F ig . 4 .1 5 .
4 .7
E X E R C IS E S
4.1
Write several lest* until you thoroughly urkkrstand the difference between
Figs. 4.9 and 4.10.
4.2
Conway's Problem: Write a program to read 80-column cards and write them
as 125-character lines with the following changes. A fter every card image an
extra blank is inserted. Every adjacent pair o f asterisks is replaced by A.
O f course Conwayi problem can b e solved by a single sequential progiarn. However, it difficult to be sure that you have taken care o f all o f the
special cases such as pairs of asterisks at the end of a card and so on.
The problem has an elegant solution as three concurrcnt processes. One
process read reads the cards and passes characters through a one character
buffer to a process squash, read also passes the extra blank at Ihe end o f every
card image; squash, which knows nothing about 80-column cards, simply
looks for double asterisks and passes a stream o f modified characters to a
process p rim /m 'n /iak esth e characters and prinislhcm as 125-character lines
4.3 Write a program to solve Conway's problem with the additional requirem ent
that there be a 10-charactcr buffer betw een each pair of processes: read and
squtiih; squash and prim . Use m utual exclusion on the bounded buffer as
shown in Fig. 4 .IS.
4.4 In Fig. 4.12, simplify the condition in the producer's wait until clause.
4.5 W rite a scenario that shows that signal must be a primitive instruction and not
simply s := j + 1.
4.6 Add a sem aphore to program increment (Fig. 1.5) so that it always prints 40.
4.7
4.8 Write a scenario showing lockout for the sem aphore solution to mutual
exclusion o f three processes.
EXERCISES
4.9
69
4.10 Why is the program in Fig. 4.16 not a solulion to the problem of allowing at
most k processes into a critical region (using binary sem aphores only)?
(a) Show that if k - 2 and u = 4 it is possible to have d e la y -2 contrary to the
requirem ent that delay is a binary sem aphore.
(b) 'S how this even for 4 - 2 and /t - 3 .
program
const
m uluaiexctusion;
( num ber o f processes )
k . . . ; ( num ber in critical section )
var
count: integer;
j: ( binary ) semaphore',
delay: ( binary ) sem aphore;
procedure process (i: integer);
vttr m: integer,
begin
repeat
tvair(f);
count
count - 1 ;
m : count;
signal(s);
If m < = - 1 then wait(detay)\
crir,
k'<ur(j);
c o u n t: count + 1 ;
if count < - 0 Ihen ,iignal(dclay);
signal(s)
forever
end,
begin ( m ain program )
count : k;
S i - 1;
delay : = 0;
cobegin
process^ 1);
process{2)]
process(n)
coend
end.
Fig. 4.16.
4.11 (Kessels and M artin) A split binary sem aphore is a pair of binary sem aphores
* and y such that the formula 0 < x + y < - 1 is always true (i.e.. is an
invariant). Study the simulation (Fig. 4.1 7 ) of general sem ap h o res by the split
binary sem aphore.
70 SEMAPHORES
CHAP. 4
wait(x);
while s < 0 do
begin
s := s - 1
If count0 th e n rignal(x) else signal(y)
end;
p ro c e d u re gensignal(\ a r s: integer):
begin
wait(x);
f
j + I;
if c o u n t* 0 th e n signal(x) else signal(y)
end;
F ig . 4 .1 7 .
4.12 (M anna and Pnueli) W rite a concurrent program to com pute the binomial
coefficient (n * ) ( - 1 ) . . (/ -* + 1 ) / 1 ( 2 ) .. . (A), forO < - k < - n. Let
process P , multiply n then n - 1 then n - 2 and so on into a global variable x
while process P* multiplies I and 2 and so o n into a local variable^. Synchron
ize P , and P j so that P3 executes* : x div y w h en ^ , in fact, divides Jr. (Hint
it always divides j( j+ 1) . . . ( > + /- ! ) .)
4.1 3 *(Roussel) Write a concurrent program lo test if tw o binary trees have the
same leaves. T here will be three processes: P4, i - l , 2, will find the next leaf of
tree i. W hen two "n ex t leaves have been found, Pi will test them for
equality. The trees can be declared in Pascai-S as follows:
const
lype
v r
m axnodes= 40;
leftson= 0;
rightson * 1;
nodevaluem2;
n o d e - array [0 . . 2 ] of integer;
treetypea rra y f . . m uxnodes\ o f node;
tree: a rra y f 1 . . 2) o f trcetype.
EXERCISES
71
4.14 Study the im plem entation kit and describe the changes that must be made so
that the kit will catch misuse o f a sem aphore: tests and assignments (except in
the main program ). What changes must be made to differentiate general from
binary sem aphore?
4.15 (Parnas) Figure 4.18 is a solution to a pioblem called the Cigarette Smoker's
problem . Each one of the three agenn supplies two o f three possible
resources. T here are three sm okers each o f which needs exactly the pair of
resources supplied by one o f the agents. Study (and test) the solution and
answer the following questions.
(a) W hat is the function o f the helper processes?
(b) Explain how term ination o f the tasks is accomplished. What is the
purpose of t :*= 0 in procedure forcelerminaiion?
(c) Even though the program term inates, there arc certain bugs that may
occur on the final execution o f each process. Write examples for these
bugs and a b etter program that term inates correctly.
(d) Do you see a problem that might occur with the sem aphores 5(1). $(2),
j|4 f ? How can this problem be solved?
program cigarette-,
const trips 20;
var resource: array[ 1 . . 3] o f ( binary ) semaphore,
s: a rra y fl . . 6] of sem aphore;
m utex, sem : ( binary ) sem aphore;
/: integer,
finished: a rra y (l . . 3] o f boolean;
procedure forceierminaiion;
v ar i: integer;
begin
0;
for i : - 1 to 3 do signal(resource[i})\
for i : 1 to 6 do signal(s{i])
end;
procedure agent(n, res I, res2: integer);
var i: integer;
begin
for / :=* 1 to trips do
begin
H'a/r(frm);
signat(rcsourcc\resl]);
signal(resource[res2))\
w nteln( ' a g e n t' . /i)
end;
finisheti[n] : true
end;
procedure helper(n, increment: integer);
begin
repeat
wait(resource[n]);
wait(mutex);
t : / + increm ent;
signal(m utex)
72
SEMAPHORES
CHAP 4
repeat
wait{s[index]);
i : 0;
writeln ('smoker',
signal(sem)
until finished[n J
n );
end,
begin ( main program )
for f : = I to 3 do resottrceii] 0;
for / : 1 to 6 do iff] : 0;
for t
I to 3 do fintshed[i) : false;
0;
mutex :
son : I ;
1;
cobcgln
ag<n(l.2.3); helper( 1.1); smoker(\,b);
ag</(2,l,3); helper{2,2); smokeri2.5);
gf/i(3.1.2); hetper[i.4)', smoker(3,3)
coend;
tvriiebi('smoking is dangerous)
ead
M g . 4.18.
MONITORS
5 .1
IN T R O D U C T IO N
74
MONITORS
CHAP. 5
SbCI J 2
D E F IN IT IO N O r M O N II OKS
7S
76
MONITORS
CHAP 5
begin (* m onitor b o d y )
in := 0;
out
0;
n := 0
end;
( end o f m onitor boundedbuffer )
procedure producer,
var
v: integer;
begin
repeat
produce (v);
append (v)
forever
end;
procedure consumer',
var
v. integer;
begin
repeat
take (v);
consum e (v)
forever
end;
begin ( main program )
cobegin
producer; consum er
coend
end
Fig. S.l.
SE C f. 5 2
DEFINITION O f MONITORS
77
outside interference and (he structuring of Ihe acccsscs. Since the mutual
exclusion is autom atically guaranteed by the m onitor, there is no counter
part to a bug caused by om itting a signal to release m utual exclusion. If you
forget the end statem ent of m onitor procedure, lhal is a compilation error
just as it would be in an ordinary program . In addition, the wailing and
signalling is program m ed within the m onitor. T he users o f the m onitor need
only call a procedure. Thus once a m onitor is correct, it will be correct for
every instance used by every set o f processes. In the case o f the unstructured
sem aphore, the correctness depends upon sem aphore o perations that must
be explicitly program m ed into every process.
For synchronization we need some so n o f w ail-signal commands.
The sem aphore com m ands served two purposes. One is to provide a
bfock-wakeup facility and the o th e r to maintain a count. Since (he counts
can now be explicitly contained as integer variables in the protected monitor
data, it is sufficient to provide a block-w akeup facility. Just as several
sem aphores may be needed in one program , so one m onitor may need
several w ait-signal pairs. We define a new type o f variable called a condition
variable. If c is a condition variable then there are two com m ands that can be
applied to c: wuit(c) and sigrtal(c) (these will now be defined for monitors;
they are nol to be confused with the com m ands of the sam e name for
sem aphoresalternatively call the sem aphore com m ands P and V):
wait(c)
78
MONITORS
C H A f. 5
In the m eantim e wc make ihe restriction that there be at most one signal
per procedure and that it be the last statem ent in Ihe procedure. T hus (he
signalling process leaves the m onitor immediately after the signal. This
evades the question raised in ihe last paragraph; we shall return to it in the
last section.
Im mediate Resum ption Requirement Let a process execute signat(c)
and suppose that there are processes in the queue fo re as well as processes
waiting to en ter the m onitor by a norm al procedure call. T hen the process on
the head o f the queue for c is the next process to e n te r the m onitor; in
particular it has priority over the processes which are trying to e n te r the
m onitor by procedure call,
Lei us see why this requirem ent is needed. Suppose that process P x has
noted that the condition is fulfilled and signals. If a proccss P j is allowed to
en ter the m onitor (by a procedure call) before a proccss P2 (which is waiting
on condition c), then conceivably
could cause c to become false. For
example, if Pt is a producer signalling buffer*not*empty and b o th P2 and Pt
arc consum ers, ihen it would be fatal if the interloper consum ed the single
d ata elem ent before the aw akened process Pt is allowed to proceed. Under
the Im m ediate Resum ption R equirem ent, how ever. P2 can assume that
w hatever P t checked im mediately before issuing the signal is still irue
because no interloper could falsify it betw een the signal and the resum ption
o f the first blocked process.
Finally, to com plete the bounded buffer exam ple, we must declare two
conditions in the variable declaration part of the monitor:
notem pty, notfull: condition',
and replace the phrases in quotes by th e comm ands:
wail(noifull)
signal(notempty)
wait(notempty)
stgnal(notfuH),
respectively.
5 .3
S IM U L A T IO N OF TH E S E M A P H O R E
sen j j
i
s im u la t io n
of me
sem ap h o re
79
The m onitor (Fig. 5.2) will use a boolcun variable busy which will
i indicate w heiher or not a wail o peration has been com pleted on ihe
' semaphore (and hence that the critical section is busy ). If the sem aphore is
busy, we must wait until it is not busy so according lo ihe wording of the
! monitor operations we might as well call the condition noibusy. The iwo
j procedures will be called P and V to avoid confusion here with the monitor
j operations.
program
nutiualexclusion;
m onitor semaphoresimulation\
var
busy: boolean;
notbusy: condition',
procedure P\
begin
if busy then wait(noibusy)\
busy : true
end;
procedure V\
begin
busy : * fa lse ;
signal(notbusy)
end;
begin ( m onitor )
busy :m false
end,
procedure
begin
repeat
P.
crit 1;
V',
rem \
forever
end;
procedure p }\
begin
repeat
P.
crii2;
V\
re m l
forever
end;
80
CHAP 5
MONITORS
Let us check that ihe various requirem ents are fulfilled. T here is at most
one signal in every procedure and when it docs occur, il is the last statement
in V. If a signal is executed when there are blockcd processes then it is
executed when busy is false; hence, a blocked proccss which is awakened
need not check that fcujy is now false and can proceed to set it true. Note how
Ihc m utual exclusion of the m onitor entry prevents the bugs we once had
when two processes simultaneously checked a variable such as J>usy and then
set it.
T his im plem entation of a sem aphore is the strongest implementation
possible because o f the FIFO assum ption on the queue o f processes blockcd
o n u condition. T he sem aphore definition does not require FIFO but it
certainly does not forbid il as a scheduling strategy. Thus any semaphore
algorithm proved correct under a w eaker assumption is still correctA condition variable does not have a value in the usual sense of the word
and hence no initialization is needed. To be more precise. every condition
variable is implicitly initialized to the empty queue of processes blockcd on
it.
It seems that we need a different m onitor for each sem aphore In
practice, systems using m onitors allow one to declare m ultiple instances and
even param eterized sets o f m onitors. If the m onitor procedures are written
as re-entrant* procedures (Pascal procedures are autom atically re-entrant),
it is sufficient lo allocate new instances o f the global variables for each
instance o f a monitor. In the case of the sem aphore m onitor, this means a
new boolean variable busy and a new queue for the condition noibusy. But
that is exactly the am ount of storage needed for a sem aphore under ihe
direct definition!
5 .4
SECT 3 4
81
program
reudersandwriters;
monitor readwrite,
var
readers', integer,
writing: boolean',
o kf oread, oktowrite: condition,
procedure startreud;
begin
If writing o r nonem pty (oktow rite)
then wait(ok(oread)\
readers :* readers+ 1;
signal(oktoread)
end;
procedure endread;
begin
readers : r e a d e r s -1;
if readers 0 then signal(oktowrite)
end;
procedure startwrite;
begin
if readers < > 0 o r writing
then wail(t>ktowrite)',
writing : true
end;
procedure endwrite;
begin
writing : false;
if nonem pty{oktoread)
then signal(oktoread)
else signal(oktowrite)
end,
begin (* m onitor *)
readers := 0;
writing : = false
end;
8-1
CHAP J
MONITORS
R readers-,
W > 0 if and only if writing * irue;
nonem pty(oktoread) only if (writing or nonem ply(ok to write)) ',
nonem piy(oktow rite) only if (readers * 0 o r writing);
Each of these statem ents is initially true and it must be checked (Excrcise 5.7
(a)) that, if a statem ent is true upon entry into a m onitor procedure, it is still
true when the process exits the procedure.
Points to rem em ber are: execution o f a wait is also u way of exiting a
m onitor procedure; if a statem ent is true im mediately before the execution
of a signal then, by the im m ediate resum ption of an aw akened proccss, the
truth o f ihc statem ent is Irunsfered lo the resum ed process.
The basic safety property required of a solution to the problem o f the
readers and the w riters will be proven if we can show that the following
formula I is invariant:
If R > 0 then VK= 0 and if W
> 0
then
I and R = 0).
In words: if there arc (active) readers then there are no writers, and if there
are (active) writers (hen there is only one
w riter and no readers.
I is initially true since R * W = 0. We show th at I is always true by
showing that any attem pt to describe an execution sequence which falsifies I
is unsuccessful.
1. Suppose R > 0 and ^ = 0 (so that I is true) jtnd then I is falsified by some
proccss starting to write (so W will becom e 1).
By (a), R > 0 implies readers > 0 so the process that wishes to write will
watt in procedure startwrite. The only way (his scenaiio could falsify I is if a
signal(oktowriic) occurs. T he signal in ertdread is executed only if re a d e rs-0,
contrary to assumption. The signal in endwrite will also not be executed sincc
there are no w riters by the assumption
2. Suppose R**Q and W > 0 and then som e process starts reading so that
I,
falsifying I.
W > 0 im plies writing true by (b), so any proccss executing startread
will wait on oktoread. Since R - 0, there arc no readcrs so signal(uktoread) is
not executed in endread. Now I is assumed true so W > 0 implies W= I . Thus
executing signal(oktoread) in endwrite upon term ination of writing occurs
when ^ = 0 contradicting the assum ption of this scenario.
3. IV= I . R - 0 and then some process starts writing to falsify the second
clause of I.
SKCT. S 5
85
86
6.6
MONITORS
CHAP. 3
Wc now give an algorithm for transform ing a program using m onitors into i
program that uses sem aphores. This will show that m onitors are no more
powerful than sem aphores and hence (hat the decision to use m onitors can
be m ade solely on the basis of (heir contribution to the clarity and reliability
of the resulting system. This transform ation is conccrncd only with the
dynamic behavior o f the concurrent system. The static protection o f monitor
variables should still be im plem ented, if possible, by n facility such as the
Simula 67 class o r the A da package.
The m utual exclusion o f the m onitor procedures is easily sim ulated by a
binary sem aphore. T h ere will be a sem aphore s (initially 1) for each different
m onitor and each procedure o f a m onitor will comm ence with wail(s) and
term inate with signal(s) just as wc solved the critical section problem with
sem aphores. For each condition cond wc need an integer variable condcount
to count the num ber o f waiting processes and a binary sem aphore condsem
to actually block the waiting processes. The iniiial value of condcount is 0.
T h at of condsem is also 0 because a proccss executing the m onitor wait
always blocks. Each com m and waii(cond) o f the m onitor is now coded:
c o n d c o u n t: condcount + 1 ;
sig n a ls);
w ait(condsem );
c o n d c o u n t: co n d co u n t- 1 ;
The signal on Ihc sem aphore s is to release the m utual exclusion on th e entry
to the m onitor in o rd er to allow o th e r processes to en ter, including (hope
fully) one which will eventually signal.
R em em ber that we have restricted the signal(cond) to be the last
com m and o f a procedure. H ence (he release o f a blockcd proccss from tlte
sem aphore condsem can be com bined with the release of the m utual exclu
sion in the following code:
if condcount > 0 then signal (condsem ) else signal(s)
This im plem ents o u r restriction th at, if there are processes waiting on a
condition, they have priority over processes waiting at the m onitor entry
points. T he blocked processes are waiting on condsem ; the processes wishing
(o en te r are wailing on s. So only if there are no blockcd processes (condcount~Q ) is th e m onitor entry freed. N ote that the signalling proccss must
have passed a wait(s) sem aphore upon entry, H iu s the aw akened process
inherits the outstanding m utual exclusion from the signalling process. The
debt is m ade good when (he aw akened process term inates and executes
signal(s). O f course it could avoid this by aw akening still a n o th er proccss.
SECT. S t.
87
Il
is interesting th at. according to o ur definition of sem aphores, the
value of the sem aphore condsem is never 1. It is initially 0 and signal(condsem) isonlycxccuted if some process is w aitingon cow/sem . Thus co/ufom is
never increm ented.
The only feature of the m onitor that we cannot im plem ent is Ihc FIFO
assumption on the queue because (he sem aphores are nol FIFO.
In Fig. 5.4, we show how this translation can be carried oul for the
producer-consum er program in Fig. S .l.
program producerconsumer;
const
sizeofbuffer . . .
var
b: arrayfO . . sizeofbuffer) of integer;
in, our. integer;
n: integer,;
5: ( binary ) sem aphore; ( fo r m utual exclusion )
notem ptysem , noifullsem: ( binary ) semaphore;
notem plycount, notfullcount: integer;
procedure append (y; integer);
begin
H'ajf(i);
If n sizeofbuffer+ 1 then
begin
notem plycount := notemplycount-* I;
signal(s),
n>aii(noiemptyseniy,
notem plycount := notem plycount 1
end;
if notfullcount > 0 then signal(noifullsem)
else sig n a ls)
end;
procedure take(va r v: integer);
begin
if n = 0 then
begin
n o tfu llc o u n t: * noifullcount+ I ;
signal(s)
w aii(noifuthem )\
notfullcount : = n o tfu llc o u n t-\ \
end;
if notem ptycount > 0 then signai(notem ptysem )
else sig n a ls)
end;
88
MONITORS
CHAP J
procedure producer',
procedure consumer\
begin ( m ain program )
in : * 0; o u l 0; n : 0;
s : I;
n o te m p ty c o u n t: 0 ; nolfulicounl : * 0;
noiem ptysem
0; noifullsem : = 0;
cobegin
producer, consum er
coend
5 .7
U N R E STR IC TE D S IG N A L S
s e c t 3 .7
UNRESTRICTED SfGNAI.S
89
<1
'9 0
MONITORS
CHAP. $
(* i f so m eo n e is wailing )
( lei h im in )
( su sp en d y o u rs e lf *)
(* i f a waiting signaller )
( fre e a signaller )
( let in a n ew process )
r i g . 5.6.
5 .8
E X E R C IS E S
5.1
Suppose that signals are not restricted but that some particular signal is in fact
the last statement in its procedure. Code a simplification to simulation of
monitors by semaphores for this case.
5.2
Show that even if ihc implementation of the semaphore is FIFO, the simula
tion of the monitor by semaphores is not.
5.3
Translate the monitor solution to the problem of the readers and the writcre
(Fig. 5.3) to a semaphore solution.
5.4
(Couitois et at.) Fig 5.7 is a solution to the problem of (he readers and the
writers using semaphores- It iscasy to see that/-counts the number of readers,
s guarantees mutual exclusion to variable r and wsem guarantees mutual
exclusion to writing.
(a) Discuss the priority scheme of this solution.
(b) Suppose that you have a FIFO implementation o f semaphores. How
would that uffcci the answer?
program
var
readersandwriters;
r. integer;
S,
wsem: ( binary ) semaphore;
procedure readprocess;
b tti
repeat
r :* r + 1 ; if r - l then wait(wsem)\
signals);
readthedata-,
wait{s)\
r
r - 1 ; if /-() then stghal(wsem);
signal(s)
fortver
end;
#
EXERCISES
91
procedure writeprocess;
begin
repeat
wair(tvsem);
writethedata;
signal(wsem)
forever
end;
begin (* main program )
r := 0;
t : 1;
wsem : * 1;
cobegin
readprocess; ( . . . )
wnteprocess; ( . . . )
coend
end.
Fig. 5.7.
5.5 (C burtoisera/.JThe solution in Fig. 5.8 usesa somewhat symmetrical codc for
both the readers and Ihe writers except that in the writer, wsem is used to
guarantee mutual exclusion m the execution of the write itself while, in the
reader, rsem is used only by the writer to prevent readers from entering the
critical section bracketed by J |.
(a) Discuss (he priority scheme of this solution.
(b) How would the solution change if ihe semaphores were FIFO?
(c) What would happen if s 3 were omitted? (//mi/ Show that ensures that
rsem -0 implies that there is cxacily one process waiting tor signal(rsem)).
program readertandwriters;
var
r,w. integer;
5,, j j , fj: ( binary ) semaphore;
wsem, rsem: ( binary ) semaphore;
procedure readprocess;
begin
repeal
woit(rsem);
wait(s,);
r :* r+ I;
I f r * I ihen waii(w$em);
signat(s,)\
signat{rstm)\
signal(s3y,
readihedaia;
wu'r(s,);
r .* r - i ;
if r=Q then signal(wsem);
signals t)
forever
end;
92
MONITORS
CM A^
procedure wriieprocw,
.j
b tg in
i]
repeat
*wV(f2);
h> : w v J ; |f >tej then tvail(rsem);
signaUst);
wu(*vsem);
wriiethedata-,
signal(wsem);
w := m>- ); if *v= 0 then signal(r$em)i
Signal(s2)
forever
end;
begin ( main program )
r :* 0 ; k- ;= 0 ;
jj : I; *i :* I;
:* I;
rsem : = ]; wsem : I ,
cobegi*
readprocesf, ( * . . . )
wrueproccsi, ( . . . )
coend
end
Pis . .<-8.
5.6
For each of the priority schemes (Section S.4 and Exercises 5-4 and 5 5) try lo
think of an application in which (hat schcme is Ihc reasonable one 10 requirt.
5.7
Complete llic semi-formal proof of the solution to Ihc problem of the readers
and the writers.
(a ) Prove the invariants (a)-(d).
(b) Prove the liveness of writing.
(c) 'Prove tlte following statement 5 which expresses the priority scheme
claimed for the solution.
S: If {Q enters uartvtrite before P enters uariread) then (Q writes before P
reads).
Hint How to piove precedences:
Let p and q be any two properties of programs. Then (p before q) is equivalent
lo (p is now true) or lq is now false and after executing a slep o f ihe program
Ihen (p before q)). Similarly, the negation of (/> before q) is equivalent to (p is
now false) and (4 is now true or after a step then ip before q) is false).
Show (haI the negation of S is inductive, that is, if S is assumed false then after
executing b step of the program 5 must still be false- Deduce that (Q enters
stanwr'tte) but never (Q writes) (hus contradicting Ihe liveness of writing
shown in (b).
t
I
e .l
IN T R O D U C T IO N
The sem aphore and the m onitor arc centralized facilities. A process cxcculing a m onitor procedure has access to the single copy of the monitor
Jvariables and thus there must be an arb iter to enforce m utual exclusion.
While these requirem ents arc natural in a single com puter (o r any common
memory system ), they are difficult to im plem ent in a distributed system. By a
distributed system we m ean a set of totally independent com puters whose
only connection is by sending and receiving messages. T h ere may be no
synchronization betw een sending and receiving a message. Messages may
"pass cach oilier in transit. W hat we need is som e sort of self-enforcing
protocol. A proccss will decide to wait on its own initiative as in the busy wait
algorithms of C hapter 3.
In those algorithm s, each process agrees to enter a while loop if it needs
to block itself. Each proccss decides by ilself w hen to leave. This contrasts
with Ihe sem aphore and the m onitor signals which are req u ired lo wake
another process.
L am port's bakery algorithm s discussed in the exercises of C hapter 3 are
designed for distributed systems. Each process writes only into a single local
variable. I he lesl n, > 2 in proccss Pt can be interpreted as follows. Send a
request to process
to read the value of
Wait until P 2 replies. Compare
ihe received value with (he cu rrcn t value o f (he local variable
Each process needs 10 be augm ented with polling statem ents (hal
periodically search for requests for data values from o th er processes. A lter
natively (his can be done by interrupts. T he receipt o f a message from the
communica(ion line will trigger an interrupt in the receiving process. This
process will then identify (he message and route it for appropriate action.
If wc exam ine (he protocol suggested in the Iasi paragraph we find that
the essential idea is (he transfer o f inform ation at a predeterm ined point in
each process. We call (his a rendezvous of the two processes. T he essencc of
93
94
THE A D A RENDEZVOUS
C H A P .*.
any rendezvous is th at the parly which arrives earlier is required to wait. The
alternative to a rendezvous is a buffered message system but aside from
questions as to the size and num ber o f buffers, we now have (he question of
who ow ns the buffers.
In classical system s the buffers belong to the "sy stem ", but in a distri
buted system, we do not want to single out any process as th e boss. If that is
what we want th en the m onitor formalism is sufficient. Since message
passing systems are an obvious task for concurrent program m ing, we prefer
to base the program s o n an independent primitive such as a rendezvous.
T he rendezvous was suggested by H oare in a paper which is entitled
Com m unicating sequential processes to contrast with D ijk stra's Co
operating sequential processes" on which C hapters 3 and 4 are based.
Instead of presenting H o ares original work we choosc (o discuss the version
that is used in the A da program m ing language. A da was designed specify
cally for real-tim e systems program m ing which inherently uses concurrency.
T he A da facilities will probably become the dom inant style for concurrent
programming.
The exam ples will be writ(en as executable A da program s. However,
we will try to use only Pascal-like features when possible and we will note the
essential differences w here neccssary. This chapter is not a tutorial o n Ada
nor even on the full range o f concurrent program m ing facilities it) A da. It is
intended as an introduction to ihe rendezvous concept as used in A da. Ada
program m ers can regard the previous chapters as a description o f the scien
tific clim ate under which the A da concurrent program m ing prim itives were
developed.
6 .2
The m onitor has no life of its own. It is simply a collection o f da(a and
procedures that sit waiting to be invoked. In o ur model, the m onitor is an
igloo which is accessible to all processes that need it but which is just a
building that docs nothing on its own. Let us now imagine a story that will
give us a feel for the rendezvous.
Several processes, P arc riding around in the snow o n their dog sleds
(Fig. 6.1). Proccss Q owns a lodge A das Place which happens to be
strategically placed at an intersection of all Ihe tracks followed by the Pt.
Periodically, the P, reach th e lodge and wish to e n te r for a snack. If P t arrives
before Q has arrived to open the lodge then P x crawls into his sleeping bag to
wait for Q. W hen Q arrives they open the lodge, go inside and P t exchanges
the fresh m eat he has bagged for ready-to-eat meat sandwiches that Q
prepares.
U nfortunately, Q 's investm ent capital was too small and the lodge can
only hold two processes and one load of m eat and bread. Thus, if several
SECT-1>.2
95
Fig. A.I.
96
l i l t A D A RENDEZVOUS
CHAP. 6
Rem ark To run this program , you will have lo supply the value of
numberofprocesses; a representation for fo o d ; subprogram s for huntwalrus,
SECT. 6.2
97
eat, visitbakery, cook, and finally, the loop should be term inating and some
trace should be printed. (E nd o f rem ark.)
The rendezvous is considered to be in force during the execution o f the
statem ents betw een the do of the accept statem ent and the corresponding
end In particular, the calling process is blocked for the duration of the
rendezvous to prevent it from changing the values of the param eters until the
exchange of inform ation is com plete. T hus the body o f the accept acts like a
critical section. O nce the accept statem ent has term inated, the rendezvous
has been com pleted and a fresh accept statem ent must be issuedduring the
next cycle o f the loopto effect a n o th er rendezvous (with the same process
or with another). O f the two p aram eters, one is used to pass a value from the
calling process and the o ther to return a value to the calling process. This is
the two-way exchange o f inform ation betw een the processes.
T hat the rendezvous is suitable for distributed systems can be seen by
the following sketch o f how it might be im plem ented. P, executes lodge by
sending a signal to Q that il requests a rendezvous. P, then suspends itself
pending a reply from Q. The processor running Q registers the signal from P,
by an in te rru p te r by polling. Q eventually executes the accept statem ent and
notes that P, has registered a signal. Q replies to P, that rendezvous has
occurred and rem ains blocked until P, acknow ledges the reply with a mes
sage containing Ihe param eters o f the call. Q receives the param eters,
executes the statem ents following the do and then returns the result para
meters. U pon receiving the results, P, can unblock and continue com puta
tion. The program can even be im plem ented in a distributed m anner because
once the num ber and type of the param eters are agreed upon, the processes
can be independently designed and program m ed.
Let us now see how the binary sem aphore can be sim ulated by a
rendezvous (Fig. 6.3). H ere it is im portant to note that while the mutual
exclusion problem for two processes was solved by invoking passive
sem aphore procedures, with the rendezvous wc need lo create a new
sem aphore process to m ediate between P , and P ,. On Ihe o th er hand. P, and
Pj no longer need to acccss the same variable o r queue.
procedure mutualcxclusion is
task sem aphore is
entry wait;
entry signal;
end semaphore;
task body semaphore is
begin
loop
accept wait;
accept signal;
end loop;
end semaphore;
90
1HC A D A RENDEZVOUS
CHAP. 6
(ask P ,;
task body P, is
begin
loop
rem 1;
wait;
critl;
signal;
cod loop;
end P ,;
task P2;
task body P2 b
begin
loop
re m l;
wait;
c r itl;
signal;
end loop;
end P 2;
begin
null;
end m utualexclusion;
Fig. 4.3.
W hen a process P, executes the call to wait, it must block until the
sem aphore process executes its accept statem ent and the rendezvous is
achieved. T h ere are no param eters to be passed and no statem ents to be
executed within the critical section of th e accept statem ent. Once P , has
term inated the rendezvous, it is free lo e n te r its critical scction.
P 2 how ever will block when it (ries lo call wait because the sem aphore
proccss is w ailing for a rendezvous with a signal call. T hus until som e proccss
(i.e. P t ) executes a call \o signal, the sem aphore proccss is blocked and hencc
so is P 2. W hen P , com pletes its critical section, il accomplishes a rendezvous
with the sem aphore process at accept signal. T hen the sem aphore process
can com m encc its next cycle and accom plish a rendezvous with P 2.
Since ih e q u e u e s for th e accept state m e n ts a re req u ired to be
im plem ented as F IF O queues, this im plem ents a FIFO sem aphore: even if
P, overtakes P 2 after com pleting the critical section, ii will be placed after P2
on the queue of the sam e accept wait statem ent. N ote th at ihe q ueues are
FIFO in term s o f time of arrival at th e processor executing th e accept
statem ent. T hus, in a physically distributed system, closer processes may be
able to overtake m ore rem ote ones. Lockout is not a problem , however,
SECT. 6.2
99
because once a proccss does e n te r Ihe q ueue, it need only wait for the finite
number of processes ahead of it to com plete.
We have shown how lo im plem ent a single sem aphore. If Ihe system is
to have several sem aphores wc will need multiple copies o f Ihc sem aphore
process so lhal calls to wait and signal can be param eterized to indicate which
semaphore process lo call. In Ada a (ask type can be defined and multiple
instances created by ordinary variable declarations. T hus an array of
sem aphore lasks can be declared and accessed by a simple array index.
Ada la n g u a g e n o tes
1.
2.
3.
4.
6 .3
TH E "S E L E C T " S T A T E M E N T
Turning to the bounded buffer problem , we find that the accept statem enl
is insufficient. Wc might uttem pi a solution with (he program fragm ents of
Fig. 6.4, using a buffer proccss betw een the producer and (he consumer.
Producer:
loop
append(v)\
end loop;
Consum er:
loop
take(v)\
end loop;
100
n i b AO A RENDEZVOUS
CHAP. 6
Buffer:
loop
acccpt appcnd(v: in integer);
accept take(v: out integer);
end loop;
r
F it. 6.4.
The only execution sequence possible is append, take, append, take. This is
Ihe vame as no buffer at all and wc could just as well make the rendezvous
directly between the producer and the consum er.
Producer-.
loop append(v); end loop;
Consum er:
loop
accept appertdiy: in integer);
end loop;
If you exam ine the bounded buffer solutions by sem aphores and
m onitors you find that what is needed is some way of conditionally achieving
a rendezvous. If the buffer is full, the rendezvous must only be with the
consum er; if em pty, only with the producer. If the buffer is neither full nor
em pty then Ihe rendezvous can be wilh w hichever of the processes is cur
rently waiting for the rendezvous. If both are waiting then we do not really
carc with whom the rendezvous is m ade as long as the buffer proccss is not
unfair. W ilh this background it should be possible to follow the A da solution
to the bounded buffer (Fig. 6.5). The program shows just the buffer task; the
producer and consum er are straightforw ard loops,
task b oundedbuffer is
entry append(v: In integer)-,
entry take(v: out integer);
end boundedbuffer;
task body boundedbuffer is
size: constant
b: arra y (0 . . size) o f integer;
inptr, outptr: integer;
n: integer;
begin
n :** 0; inptr : = 0; outptr :* 0;
loop
select
when n < * size >
accept append(v: in integer) do
b(inptr) : v;
end append;
n : + | ;
inptr :=* (inptr + 1) mod
s c c r.t)
101
or
when n > 0 >
accept take(v: out integer) do
v : * b(ouipir);
end ta ke;
n := /* 1;
outptr :* (ouip tr+ 1) mod size,
end select;
end loop;
end boundedbuffer,
^^
Before wc discuss the new features o f the select com m and, note th at the
critical section of the accept com m and do es not encom pass the entire buffer
processing but only (he physical exchange o f da(a. The updadng o f Ihe
internal pointers need not block (he producer nor the consum er who have no
access to these local variables.
T he select statem ent allows one to select betw een several alternatives
separated by or. The alternatives are prefixed by w hen-dauses called guards.
The guards are boolean expressions which establish what conditions m ust be
(rue for an alterna(ive to be a candidate for execution.
T he execution o f a select statem ent begins b y evaluating aU the guards.
T hen one of the open alternatives altern ativ es wi(h true g uards is
selected for execution. In the bounded buffer if one o f (he guards is no( (rue
then the o th er must be (n < = 0 implies n < = size and conversely, n > size
implies n > 0) so there is always an open alternative. If (he buffer is em pty,
only the first alternative can be selected. This is th e alternative that receives
data from the producer. Similarly if th e buffer is full, only the second
alternative is open to allow (he consum er to rem ove d ata from th e buffer. In
either ease, of course, the buffer proccss will block waiting for the relevant
rendezvous. N othing is lost by not rechecking a closed alternative since the
only way to em pty a full buffer is by consum ing.
T he difference betw een th e select statem ent and an If statem ent is seen
in the case that both guards are open. T hen if b o th Ihe consum er and the
producer are wailing for a rendezvous, we d o n 'l care which rendezvous is
accomplished. An if statem ent must specify which statem ent is to be
executed in this case.
B ut the select statem en t is even sm arter than tha(. Suppose (ha( (he
buffer is neither em pty nor full, but th at only the consum er is w aiting for a
rendezvous. If a choice is made betw een both o pen alternatives then we
could blunder into blocking on an accept append statem ent for which no
producer process is wailing. Thus if both alternatives are open but only one
accept statem ent has a process blocked o n it waiting for a rendezvous, the
select will choose (o execu(e the alternative th a t leads to an im mediate
rendezvous.
T here is an o th er possibility, nam ely th a t both alternatives are open but
102
THE A D A RENDEZVOUS
CHAP 6
(hat n either process is ready. R ath er than endlessly checking the guards
(whose truth will not change) o r arbitrarily blocking on one o f the accept
statem ents, the select statem ent will block sim ultaneously o n both accept
statem ents and cxecutc the first rendezvous to be accom plished.
This is the essence of the guarded com m ands" style o f programming:
avoid over-specification (as in an if statem ent) by allowing the com puter as
much freedom of choice as possible consistent wilh the correctness require
m ents of the program .
We now give a m ore formal description o f the general select statem ent.
select
when condition I = > accept entry 1 do statements end;
other statements
or
when condition! > accept en try! do statements end;
other statements
else statements
end select;
Remark 1 The else clause is optional (see below).
Remark 2 A guard may be identically true in which case the when
true > can be om itted.
Sem antics o f the select statem ent:
1. Evaluate all the guards to determ ine which alternatives are open.
2. If there arc o pen alternatives, determ ine which accept statem ents in
open alternatives have processes currently waiting for rendezvous.
3. If there are such processes, execute one of these alternatives. If there
are several open alternatives with processes waiting for rendezvous, the
selection am ong them is done arbitrarily.
4. If there are no o pen alternatives o r no waiting processes, execute the
else d a u sc if there is one.
5. If there are no wailing processes and no else clause, wait for (he first
process lo attem pt a rendezvous with an accept clause in one of the open
alternatives.
6. In the absencc o f an else clause, it is an e rro r for there to be no open
alternative.
We can dem onstrate the general select statem ent by assuming in our
story thal the ow ner o f "A d a's Place" has independent suppliers of both
bread and m eat and th at his only task is to m ake sandwiches. I hen if there
are no processes waiting at the lodge, he can profitably use the tim e to
prepare sandwiches (Fig. 6.6).
The guards are exhaustive (at all times at least one is true) and disjoint
(no two are ever simultaneously true) so exactly one iso p en . T he else clause
SECT 6 4
IU3
is used to do some useful work if the second accept statem ent is open but
does not have a process waiting for the rendezvous. If the /*, are fast eaters,
they will have to wait but if they are often held up in blizzards, they can count
on fast service when they do return to the lodge.
procedure A dalodge is
fade type process;
task hunter;
task bakery;
task Q is
entry delivenneat(mt: In fo od);
entry deliverbread(br. in fo od);
entry lodge(snack: out fo o d );
end Q;
task body process is
victuals: food;
begin
loop
explore;
lodge(viciuab);
eat(victuals);
end loop;
end process;
task body hunter is
walrus: food;
begin
loop
hunt(walrus);
delivenneai(walrus);
end loop;
end hunter;
task body bakery is
roils: fo o d ;
begin
loop
bake(ro!ls);
deliverbread(rolls);
end loop;
end bakery;
task body Q is
bread, meat, sandwiches: fo o d ;
104
THE AD A RENDEZVOUS
CHAP t
procedure makesandwiches is
begin
cook(m eat);
sandwiches ;= bread+meai;
bread :m 0;
meal : 0;
end m ake sandwiches',
begin
bread :* 0;
m e a t: 0;
sandwiches
0;
loop
select
when bread 0 = >
accept deUverbread{br. in fo o d ) do
bread : = br
end deliverbread;
or
when meal = 0 = >
accept delivermeat(mi: in fo o d ) do
m e a t: = ml;
end delivermeat;
or
when ((bread < > 0) and (m eat < > 0)) or
(sandwiches < > 0) = >
accept lodge(snack: out fo o d ) do
if sandwiches=Q then
makesandwiches; end if;
snack : sandwiches;
sandwiches
0;
end lodge;
else
if (bread < > 0) and (m eal < > 0)
and (sartdw iches-0)
then makesandwiches; end if;
end select;
end loop;
end Q;
P: a rra y (l . . num berofprocesses) of process;
begin
null;
end Adalodge;
Fig. 6.6.
EXERCISES
6 .4
10S
P R O V IN G PROPERTIES OF TH E R E N D E Z V O U S
6.1
EXER CISES
6.2
6.3
6.4
106
T ilt: A D A RENDEZVO US
C HAP.
6.5
In Fig. 6.7 are two possibilities for a monitor-like wait/signal facility. Specify
the behavior o f these solutions. Which is more like a monitor?
6.6
Discuss the priority scheme of the solutions to (he problem o f the readers
and the writers shown in Fig. 6.8 and com pare them with the solutions in
C hapter 5.
6.7
6.8
task moiuiorfacilny 1 b
entry waif,
en try signal;
end m oniiorfacilityl;
task body monitorfaciluy I is
received: boolean-,
begin
received : = false;
loop
select
accept signal;
received (rue;
or
when received * >
accept m'ail;
received : false;
end select;
end loop;
end m onitorfaciluy 1;
(ask m onuorfacililyi is
entry wait;
entry signal;
end m on itor facility 2;
task body monitorfacility2 b
begin
loop
accept signal,
select
accept wait;
els* null;
end selecl;
end loop;
end monitorfucility2;
F ig . 6 . 7 .
tX tR C iy s
Usk readersandwrxters I it
entry startread;
entry endread;
entry sianw riie,
entry endw rite:
end re a d e n a n d w /ite r sl;
task body readersandwriiers 1, 1$
readers: integer,
begin
readers : 0;
loop
select
accept stanread,
readers := readers + 1,
or
accept e n d rea d;
readers := re a d e rs- 1;
or
when readers 0 = >
accept n a r iw ite :
accept e n d w rite;
end *elccl;
end loop;
end readersandw riiers 1;
talk readersandw riiers! Is
entry jfartrcoc/;
entry en d re a d ;
entry fror/tvnte;
entry endw rite;
end re a d ersa n d w rilerl;
task body rea d e rsa n d w n te ri Is
readers: integer;
begin
readers :=* 0;
loop
select
w hen ia/tHrt/eVtun = 0 " >
accept startread;
readers : rea d ers* I ;
or
accept e n d re a d ;
readers : = re a d e rs- 1,
or
when readers * 0 = >
accept narfHrrte;
accept rnc/tm /e;
loop
select
accept startread;
readers i r ea ifcr j+ l;
else goto I;
end select;
107
ID #
TH E A D A RENDEZVOUS
CHAP. 6
e n d lo o p ;
(( /# e n d s e le c l;
e n d lo o p ;
readersantlwriiers2\
e nd
F ig . 6.1.
A d a L a n g u a g e N o te s
1.
startwrite'count is
tower
la s k
is
e n t r y sendmax(xx: In
e n d lower;
ta s k upper Is
integer)-,
e n t r y sendmin(yy: in
e n d upper ;
integer);
lower is
x, mx: integer;
ta s k b o d y
b e g in
mx
:=
j;
lo o p
sendmax{mx);
rem ove m x from S;
a c c e p t sendm in(xx: In integer) d o
x : xx;
e a d sendmin;
add x to S\
m x : the m axim um value in S;
e x it w h e n x s m x;
e n d lo o p ;
e n d lower;
upper
mn: integer;
la s k b o d y
is
b e g in
lo o p
e n d lo o p ;
e n d upper;
F ig . 6.9.
7.1
THE D IN IN G PHILOSOPHERS
INTRODUCTION
P ig .
7. 1.
10 9
110
CHAP 7
FIRST ATTEMPT
program diningphihsophers;
var
fork: array [0 . 4] of ( binary *) semaphore;
i: integer;
procedure philosopher(i: integer);
begin
repeat
think-,
wait( fork[i) );
wait( fork[(i+ I ) mod 5] );
eat;
sinal( furk[i] );
signal( fork[(i+ 1) mod 5] )
forever
end;
begin ( main program *)
for / : * 0 to 4 do fork[i) : * 1;
cobegin
ph ilo so p h er^);
philosopher^ 1);
philosopher(2)\
philosopher( 3);
philosopher{A)
coend
end.
SECT 7 3
SECOND A I I I MTI
III
The idea of the program in Fig. 7.2 is very simple. The binary
semaphores ensure mutual exclusion in accessing the forks. The safety
property is satisfied because eating is done onty after two fork-scnuiphores
have been successfully completed.
Unfortunately the solution deadlocks. Under pcrfcct sychronization if
the philosophers enter the protocol simultaneously and take the left forks
then the state of the program is that all forks are 0 and all the philosophers
are trying to complete wait(fork[i+1]). Since there is no proccss that can
signal, the program is deadlocked.
program
dinmgphitosophers;
monitor forkmonitor;
var
fo rk: array[0 . . 4] of integer,
oktoeat: array[0 . . 4] of condition ',
i: integer]
procedure takeforkij: integer);
begin
If fork[i] <> 2 then wait(pktoeat[i])\
fork[(i+ I) mod S] := fork[(i+ 1) mod 5 ]- 1;
fo r k \(i-} ) mod 5) := fo rk[(i- I) mod 5}J
end;
procedure releasefork(i: integer)-,
begin
fork[(i+ 1) mod 5] := fork[{i+1) mod 5 )+ l;
fork[(i~ 1) mod 5] := fo r k [ (i-1) mod 5 ]+ l;
Iffork[(i+ l) mod 5]=2 then signal(oktoeat[(t+1) mod 5]);
If fo r k [(i-1) mod 5)" 2 then signal(oktoeat[(i- 1) mod 5})
end;
begin ( m onitor *)
for i := 0 to 4 dofork[i] : 2
end;
procedure philosopher(i: integer);
begin
repeat
think;
takefork(i);
eat;
re/easefork(i)
forever
end;
1)2
CHAP.?
/ - ( f o r k [ i] - \Q - 2 * eating)
I:I
is in v a r ia n t .
|CT 7 4
A CORRECT SOLUTION
113
Critical scction. However, we cun assume lhat two philosophers think very
fc l and cat very slowly.
Action
fark[0]
Initially
i$kefork[ 1]
1
1
k tfo r k [ i)
mif/ork{2)
and wait
relctueforkH]
Uktfork[\)
rtUasefork[y\
u k e fo r k [ 3 )
1
2
t
1
fork{ I)
fork(2]
1
0
2
2
2
2
fork[3]
2
2
2
2
2
0
1
0
(
1
1
1
2
Fig. 7.4.
7.4 A CORRECT SOLUTION
program
var
/ork{4]
diningp/ufosop/iers;
fo rk: a rray {0 . . 4) of ( binary ) sem aphore;
room: sem aphore;
i: integer;
procedure philosopher#: integer);
begin
repeat
think;
wait{room);
wait( fork[i] );
wait( fork{(i+ \ ) mod 5 ] ) ;
eat;
signal( fork[i) );
signal( fork[(i+ 1) mod 5) );
sigrtal(room)
forever
end;
begin ( main program )
room := 4;
for i := 0 to 4 do fo rk[t\ : 1;
cobegin
p h ilo so p h e r^ );
philosopher^ I );
philosupher(2);
philosopher^ );
philosopher(A)
coend
end.
IH
CHAf!
The solution in Fig. 7.5 is similar to the first attem pted solution cxccfl
for the additional enclosing sem aphore room . The safety properties hold*
before. D eadlock is not a problem since room ensures that at most f
philosophers are attem pting to access forks. By a simple application of the
pigeon-hole principle any attem pt to distribute the five forks in the circl^
am ong the 4 philosophers must result in at least one philosopher having twf
forks. The sem aphore invariant for the room is: room -I-(num ber o f process#
between w ait(room ) and signal(room ) )= 4 .
!
Iuit us now prove a series of lem mas that imply that this solution il
starvation-free.
"
l-cmma 7.1 If P, executes wait(fork[i}), eventually it will com plete the
P roof
|
If P, docs not com plete the wait it is only because fo rk[i]m0 which implies
that P_, is eating (since this is /V i's right-hand fork which was taken just
before ear). Eventually P,., finishes eating and cxccuies jjg/iu/(/brA;[/)) allow*
ing Pi to procecd.
Only P, and P4t, "co m p ete for the sem aphore fork[i+ 1]. If P,4t is termi
nated in think th en fork[i+ 1] cannot block P,. Similarly. P, and PlM cannot
be sim ultaneously blocked on the same sem aphore fork[i+ I] (think of the
sem aphore invariant). Thus if P, is blocked on fo r k [ i+ 1] and P,,., is assumed
never to signal th at sem aphore, the only possibility left is for P,, to be
blocked indefinitely on the o th er sem aphore: fork[i+ 2].
Lemma 7.3 If Pt executes w ait{fo rk[i+ \))t eventually it will com plete the
wait (and eat).
P roof
By four successivc applications of Lem m a 7.2 wc have that if P, waits
indefinitely o n fo r k [ i+ 1] th en P ,+y w aits indefinitely on fo r k [ i+ j+ 1],
/ = ! ..........4 but this contradicts the sem aphore invariant for room.
7.5
.0
IIS
C O N D IT IO N A L C R IT IC A L REG IO NS
program mutualexctusion\
procedure ;>t ;
begin
repeat
rem 1;
region r begin crit 1 end
forever
end;
procedure p 3\
begin
repeat
rem 2;
region r begin crii2 end
forever
end;
begin ( m ain program *)
cobegin
P tlP t
coend
end.
Fig. 7..
116
TH E D IN IN G PillLOSOPHLRS
CHAP. 7
repeat
think;
await fo r k s[i]-2
region r begin
forks[(i+ 1) mod 5] := forks[(i+ 1) mod 5 ) - I ;
fo rks[(i- 1) mod 5) : * fo r k s [ ( i- 1) mod 5 ] - 1
end;
EXERCISES
117
ear,
region r begin
fo r k s [ (i+ \) mod 5] := fo r k s[(i+ l) mod 5 ] + 1;
fo rks[(i~ I ) mod 5 ) : - fo rks[(i~ 1) mod 5]+ 1
end
forever
end;
begin ( main program *)
for / := 0 to 4 do f o r k s { i ] 2;
cobegin
philosopher^ 0);
philosopher(\y,
philosopher^ 2);
philosopher(3)\
philosopher(4)
coend
<
*
j
i
1
I 7.6 EXERCISES
I
' 7.1 Prove in greater detail ihe safety properties of the various algorithms.
7.2 Write one (or several) of the solutions in the chapter using the Ada rendez
vous.
7.3 Program 'he following algorithm (in any formulism): a philosopher wishing lo
cat picks up his lefi fork; if his right fork is available, lie picks it up and
commences eaiing else he releases his left fork and repeals this cycle. Discuss
the correctness of this algorithm.
i 7.4
!
|
All ihe solutions in this chapter are symmetrical, that is, all the philosophers
execute the same codc parameterized by the process number and furthermore
no process explicitly uses its process number in Ihe code. Try to find asymmet
rical solutions: program them and discuss correctness. Kor example: change
the first attem pted solution so thai one of Ihe processes executes
tvait(fork[i-i 1]) and then watt(fork[f\) instead of conversely.
7.5 Discuss ihe solution sketched in Fig. 7.8. We have deviated from Ada by
allowing a selecl statement wilh no accept clause. The cffecl is that of a
non-dctcrministic choice between the two possibilities.
118
A.1
INTRODUCTION
Soon, perhaps, every stu d en t of com puter science will have his own
minicomputer and sufficient tim e to team its hardw are thoroughly so th at he
may exercise concepts o f concurrent program m ing by building a real-tim e or
operating system from scratch. Until then, the accepted solution to class
exercise o f concurrent program m ing is to sim ulate concurrent execution.
T here arc several serious im plem entations which are noted in the
references. This appendix contains the listing and docum entation o f a very
simple system which can exercise concurrent execution with synchronization
by sem aphores. T his system can thus be used by any instructor who docs not
have access to one of the m ore serious systems. The system is not efficient
and is not intended to be used for extensive concurrent program m ing but it
has been successfully used to dem onstrate (the hard way) to students the
difficulties o f concurrent program m ing. Note th at even though the system is
written in Pascal, it uses only a subset o f the language th at could easily be
translated into any block structured language. Similarly, th e machine
dependencies (such as record packing to save space) are clearly noted and
easily changcd. This appendix, how ever, presum es a knowledge of Pascal.
The program in the listing (Section A .8) is a simplification and modifi
cation o f the Pascal-S interpreter originally w ritten by N. W irth. Pascal-S
com piles a subset o f Pascal into pseudo-code (P-code) for a hypothetical
m achine and then proceeds to in terp ret (sim ulate the execution of) this
code. The general structure of Pascal-S is shown in Fig. A. I .
program pascals;
v ar code: a rray [1 . . codem ax] of instructions',
procedure block;
119
120
IMPLEMENTATION K IT
APPENDIX
begin
Compile the Pascal-S program and store the com pded instructions in
the array code.
end;
procedure interpret;
var stack: array [1 . . stackm axJ of integer;
begin
Sim ulate the instructions in code.
The array stack serves as the m em ory o f the simulated computer.
end;
begin (* m ain program )
initialize;
b lo ck;
interpret;
end.
Fig. A.i.
The object language P codc is for a stack m achine. By this is m eant lhat
there are no registers or accum ulators as on most com puters. Instead, all
operands arc contained on a stack. A com m and such as A dd needs no
further specification since it autom atically refers to the operands on Ihc
stack: A dd the to p two elem ents and replace them with the result as the top
elem ent in the stack. This architecture has actually been used on real
com puters (such as Ihc Burroughs 6 700) and even on pocket calculators (of
(he IIP series).
In a slack machine A := B + C is com piled into the following sequence
of instructions:
1.
2.
3.
4.
5.
A .2
THE C O M PILE R
2.
3.
4.
O perators: integer ( + ,
i
?
SECT- A.J
5.
THE P-COOE
R elations:
6.
7.
Statem ents:
assignm ent;
if b then s\
i f b then j , e ls e
while b do 5;
re p e a t
121
5 2>
; J* u n t il
b\
for / := e t to e 2 do j;
8.
9.
10.
wait(s) and sig n a ls) are predefined sem aphore o perations looking for
integer variables. The initial value o f the sem aphore should be set by
an assignm ent statem ent in the m ain program . F o r pedagogical
reasons, a sem aphore type is provided. H owever, it is synonym ous with
iniegcr and provides no protection.
The com pilation is by top-down recursive descent. A sim ilar com piler is
extensively described in the book Structured System Programming by Welsh
and M cKcag (1 980) and thus wc d o not discuss it further except as needed to
understand the concurrent interpreter. The only point we feel obliged to
note is the use of a sim pler data structure for the identifiers. T hey are kept in
an array tab: the entry for an identifier contains a link fictd which contains
the index o f the previous identifier in th e same level o f block nesting.
A .3
TH E P-CO O E
12 2
--------------------------------------------
APPENDIX
SECT A J
THE P-CODE
123
31: Hall
32: R eturn from procedure
33: R eturn from function
34: j ( i ] is an address; replace il by its value
38: Store if i) at address i f f - 1]
35-36, 45-59: A rithm etic and boolean operations
62, 63: R eadln, W riteln
O thers: om itted in the simplification from W irths Pascal-S
In a block-structured language the address of a variable is d enoted by a pair
(Level, A ddress) w here Level is the dep th of nesting of blocks when the
variable was declared and A ddress is the offset of this variable within the
memory segm ent associated with this level. N ote th at the rules o f block
structuring require (hai blocks be nested. Thus the mem ory segm ents can be
stacked. To access a non-local variable, one simply follows the links which
define the nesting until the proper level is reached (Fig. A .2, w here s is a
local procedure of r which in turn is local to main program p). These links are
called static links.
I
i
i
t
i
i
Fit. A.2.
If, however, we are going to execute the P-code, we need some faster
way o f accessing a variable. T his is done by using a display which is an array
indexed by levels whose elem ents point to the m em ory segm ents represent
ing the current situation o f block nesting. T his is the sam e as saying that Ihe
12 4
IMPLEMENTATION KIT
APPENDIX
A .4
PR O CEDURE CALLS
During the normal execution o f a program by the in terp reter, the two main
pieces of dynamic inform ation that must be m aintained are p c (program
counter) which points lo the next instruction to be executed, and t which
points to Ihe current top of the slack. In addition, we m aintain b which points
to the bottom of the currcni stack segment and stacksizc which points to the
limit of the area allocated for the stack. Finally display keeps track of the
addressing by nesting level.
Each time a procedure o r function is called we need to allocate memory
for the local variables as well as for ccrtain additional inform ation, such as
the return address to jum p lo upon com pletion o f the procedure. It is
convenient to allocate this mem ory on Ihe same stack th at is used for the
operands and to d o the nccessary adjustm ents upon the procedure call and
return. The mem ory allocated upon procedure call is called an activation
record.
In Pascal-S an activation record has a fixed part of five words:
a/fO J^Function result;
flr[l] R eturn address;
flr[2)*S tatic link;
fl/,[3 ]D ynam ic link;
<v{4)=Tablc pointer.
W hen a function call is com pleted, the value of the function is left in
place o f the entire activation record. C onveniently, Ihen, the effect of a
function call is to push its result onto the stack just as if it were a normal
operand. The return address contains the address of th e instruction to be
executed upon procedure exit. T he table pointer contains the index into (he
identifier table tab for the procedure nam e. T he tab field adr contains the
index into the code (able o f the procedure code and re f contains the index
into the block table to be described shortly.
PROCEDURE CALLS
SECT A 4
125
H g . a .3
126
IMPLEMENTATION KIT
APPENDIX
PROCEDURE CALLS
SECT. A .4
127
Parameters
Index
+4
+ 3 fcfeJ>( J .v s iz e 1
+2
+1
+0
btab\ ) psize
/(before M arkstack)
Local variables
of
m ain program
4 ~FtabJTj~JSsT
3
2
I
b -*-
i^ T m r .- s a
128
IMPLEMENTATION KIT
a p p e n d ix
otdb : * fc;
b :* t - y;
inx : 4 ^ + 4 ] ;
/ := 4fc + 3]+6;
/eve/ ;* <a6{m.x]./v,
4 ^ + 2] := display[lcvel],
display[tevel+ \] : b;
4/> + 3] ;= o td b;
4 * + 1]
pc\
p c :* iab[inx}.adr,
.s .
stacksize
LocaJ
variables
Parameters
+4
+3
Index
Dynamic link
+2
Static link
+1
Return address
for function result
psize
vslze
F ir
a .*.
CONCURRENCY
SECT. A.S
I := b -
I;
pc
s[b + 1];
b : = s[b + 3];
129
T here is one m ore problem that must be solved. If the procedure call is
(o a procedure on a lower static level than (hat o f the calling procedure, the
display will not be corrcct upon exit. In Fig. A .3 w hen the execution of q
term inates, only d is p la y 0) pointing to the activation record of the main
program will be correct, displayi 1] and display[2] m ust be m ade to point to
the activation records o f r and s, respectively. T his is d one by th e interpreter
instruction (3): U pdate display(x, y ) which updates display{y] down to
display[x\ by following the static links. In this case, the com piler must insert
U pdate d isp la yi), 2 ) which will cause 6currently pointing to the bottom of
the activation record of s to be stored in display{2] and then obtain from the
static link the index of the bottom of the activation record of r to store in
displayi 1].
This com pletes o u r discussion o f Pascal-S as applied to sequential
programs. Before reading fu rther you might want to think of the problems
that will be encountered in extending the system to concurrent execution.
A .5
CONCURRENCY
130
IMPLEMENTATION KIT
APPENDIX
F ig . A . t .
For simplicity, the slacks are pre-allocated. The use of dynamic alloca
tion does not involve any conceptual difficulties but for our purposes it
seems unnecessary. Various versions of this system can be tailored to suit
each assigned exercise.
program p\
procedure q;
begin . . . end;
procedure r,;
begin . . . q . . . end;
procedure r2;
procedure i;
begin . . . q . . . end;
begin . . . s . .. end;
begin (* p )
cobegin
r3 coend
end.
Hg. A. 10.
IMPLEMENTATION KIT
APPENDIX
SECT. A.a
PROGRAM LISTING
135
(* indices to tables*)
(*identifier table*)
(array-table*)
(block-table*)
end;
(*string table*)
procedure errormsg;
var k: er;
msg: array [er] of alfa;
begin
msg[erid] := # identifier#; m s^ertyp]
fftype
tt;
ms&erkey] := ttkeyw ord t t ; msg[erpun) :* ttpunctuatio#;
msg[erpar] : # parameter tt; msg[ernf\ : ft not fo u n d #;
msg[erdup] := ttduplicatett; msg[erch] :* # character # ;
msg[ersh]
ttioo short tt; msg[erln} : ttioo long #;
mcssage(# compilation errors#);
writeln; writeln(# key wordsft);
for ft := erid to erln do if k in errs then
wruetn(ord(k), tt #>msg[k])
end (errormsg*);
procedure endskip;
begin (underline skipped part o f input*)
while errpos < cc do
begin w riie(tt-tt); errpos : errpos+1
end;
skipflag :** false
end (endskip*);
136
IMPLEMENTATION KM
APPENDIX
SECT. AS
PROGRAM LISTING
138
IMPLEMENTATION KIT
APPENDIX
SECT A S
PROGRAM MSHNG
13V
APPENDIX
block *)
SECT. A 8
P R O G R A M L IS T IN G
141
1-12
IM P L E M E N T A T IO N
KIT
A P P E N D IX
procedure typ(fsys: symset; var tp: types', var rf, sz: integer)',
var j:: integer,,
eltp: types; elrf. integer;
els2, offset, t0,
integer;
procedure arraytypiyar arefarsz: integer);
var eltp: types;
tow, high: conrec;
elrf, elsz: integer;
begin constantdcohn, rbrack, ofsy\+fsys> low);
i f sy * colon then insymbol else error(erpun);
constantdrbrack, comma, ofsy)+fsys, high);
i f high, tp <> low. tp then
begin error(enyp); high, i :* low. i
end;
end;
with atab{aref) do
begin arsz
(high-low+l)*elsz; size : arsz;
eltyp : eltp; elref : elrf; elsize := elsz
end;
end
(*arraytyp*);
begin (*typ) tp
notyp; r f :* 0; sz :* 0;
test{typebegsys, fsys, <);
I f j y In typebegsys then
begin
i f sy
then
SECT. A .8
P R O G R A M L IST IN G
begin x : loc(id)]
if x <> 0 then
with tab{x] do
If obj <> typel then crror(crtyp) else
begin tp : = typ; r f :* ref; sz ;= adr;
If tp notyp then error(ertyp)
end;
insymbol
end else
if sy * arraysy then
begin insymbol\
i t sy * Ibrack then insymbol else error(erpun);
tp : arrays', arraytyp(rf, )
end else
test(fsys, ( ], erkey);
end
end (*typ*);
procedure parameterlist; (formal parameter list*)
var tp: types;
rf, sz, x, t0: integer;
valpar: boolean;
begin insymbol; tp :- notyp; r f := 0, sz := 0;
test([ident, varsy], fsys+[rparent), erpar);
while sy in [idem, varsy] do
begin if sy <> varsy then valpar := true else
begin insymbol; valpar : false
end;
;= t; entervariable;
while sy m comma do
begin insymbol; entervariable;
end;
if sy m colon then
begin insymbol;
if sy <> idem then error{erid) else
begin x := loc(id); insymbol;
if x < > 0 then
with tab[xJ do
if obj <> type 1 then error(ertyp) else
begin tp ;= typ; r f :* ref;
if valpar then sz :m adr else sz : 1
end;
*
144
IM P L E M E N T A T IO N K IT
APPJ-N
end;
te st([sern ic o lo n , rp a re n t), [ c o m m a , id e n t] + fs y s , e r p u n )
end
else e r r o r(e rp u n );
w hile t0 < t do
begin t0 := f0+ I ;
w ith
do
begin ty p := tp ; r e f r f ;
n o r m a l : = valpar; a d r : = d x ; le v : level;
d x := d x + sz
end
end;
i f s y < > rp a re n t (hen
begin I f s y s e m ic o lo n (hen in s y m b o l ebe e r r o r(e rp u n );
te st([id e n t, va rsy], [rp a r e n t]+ fsy s, e r k e y );
end
end (w h ile * );
i f s y = r p a re n t then
begin in s y m b o l;
te st([s e m ic o lo n , co lo n ], f s y s , e r k e y );
end
else er r o r(e rp u n )
end (p a r a m e te r list* );
procedure co n sta n td ecla ra tio n ;
v a r c: co n rec;
begin in s y m b o l;
te st([id en t], b lo c k b e g s y s , erid );
w hile s y - i d e m do
begin e n te r (id , k o n s ta n t); in s y m b o l;
I f s y ^ e q l (hen in s y m b o l else e r r v r (e r p u n );
c o n s ta m ([ s e m ic o lo n , c o m m a , id e n t] + fs y s , c );
tab[t]. ty p
c. tp ; tab[t]. r e f : * 0;
ta b [t). a d r : = c . i;
te stse m ic o lo n
end
end ( c o n s ta n td e c la ra tio n );
procedure ty p ed ecla ru tio n ;
v a r tp : ty p es; r f, s z ,
integer;
begin in s y m b o l;
te st([id e n t), b lo c k b e g s y s , erid );
w hile s y = id e n t do
SEC T . A .S
P R O G R A M L IST IN G
146
IM PL E M E N T A T IO N K IT
APPEN D IX
P R O C R A M L ISTIN G
SECT. A .8
147
end else
begin (va ria b le p a ra m e ter )
I f s y < > id e m Ihen erro r(e rid ) else
begin k := lo c (id ); in s y m b o i,
I f k < > 0 then
begin i f ia t[ k ). o b j < > variable then error(erpar),
x . ty p := tub[k]. ty p ; x . r e f : - tab[k]. ref;
i f ta b { k \ n o r m a l then em it2(Q , ta b [k]. le v , tab[k].
ad r)
else e m if2 ( \, iab{k]. le v , lab[k}. adr);
i t s y mlb ra ck then
se le c to r (fs y s + [ c o m m a , c o lo n , rparenl], * ) ;
i f (jt. ty p < > ta b [c p ], ty p ) o r (x. r e f< > ta b [c p ). ref)
then error(ertyp)
end
end
end
end;
te st([c o m m a , rparent], f s y s , e r key );
u n til s y < > co m m a ;
If 5y - rparenl then in s y m b o i else erro r(erp u n )
end;
i f c p < la s tp then e r r o r ( e r p a r ) ; ( * to o f e w aclt4al p a r a m e te r s * )
c m i t l ( \ 9 , b ta b [ta b [ i] . r e f] , p s i z e - 1) ;
if
end ( * c a ll ) ;
< le v e l then e m i t 2 ( 5 ,
le v , le v e l)
P R O C R A M LISTIN G
IM P L M liN T A T IO N K IT
APPEN D IX
end else
i f sy * n o ts y Ihen
begin in sy m b o i, fa c t or (fs y s , *);
i f x . ty p m b o o ls then *m if(3 5 ) else
i f x . t y p O n o t y p then erro r(ertyp )
begin (fa c to r* ) x . ty p
n o ty p ; x . r e f := 0;
tesi(facbegsys, fs y s , er p u n );
w hile s y in fu c b eg sys do
begin
i f s y id e m then
end;
te st(fsys, fa c b e g sy s, erkey );
begin i l o c ( i d ) ; in sy m b o i,
w ilh tab[i) do
case o b j o f
end (* w hile*)
end (*factor*);
1 else / : = 2
i f n o r m a l Ihen / :
e m it2 (f, le v, adr)
end
0 e l s c / : = 1;
end;
<>pe\, p ro ze d u re : erro r(e rtyp ),
fu n k tio n : begin x . ty p := ty p ;
i f le v < > 0 Ihen caU (fsys, i)
else em it 1(8. a d r)
end
end (*case, w ith*)
end else
i f s y in [charcon, in ico n ] then
begin i f s y charcon then x . typ : = chars
else x . ty p
e m itl (24, in u m );
* r e f : = 0; in s y m b o i
end else
I f s y = Iparent then
inis;
14 9
A.B
begin in sym b o i; exp ressio n (fsys+ [rp a ren t], x);
i f s y * rp a ren t then in sy m b o i else erro r(erp u n )
SECT.
begin (* ierm * )
fa c to r (fs y s + [tim e s , id iv , im o d , a n d s y ], x );
w hile sy in
id iv , im o d , a n d s y } do
begin o p ;= s y \ in s y m b o i,
fa c to r ifs y s + [ tim e s , id iv , im o d , a n d sy], y ) ;
i f o p tim e s then
begin x . ty p : resu lttyp e(x. ty p , y . ty p )i
i f jr. ty p in ts then e m it ( S l)
end else
i f o p * a n d sy then
begin i f (x . ty p ^ b o o l s ) and (y . ty p - b o o ls ) Ihen
em it{5 6 ) else
begin I f (x. t y p O n o t y p ) and (y. t y p O n o t y p )
then e rro r(ertyp );
x . typ : * n o ty p
end
end else
begin (* o p in [ id iv , im o d ]* )
i f (*. ty p o in ts ) and (y. ty p i n i s ) Ihen
i f o p ^ i d i v then e m if(58)
else e m it( 59) else
begin i f (jr. t y p O n o t y p ) and (y. t y p O n o t y p ) then
e rro r(ertyp );
x . ty p : n o ty p
end
end
end
end (*term *);
begin (sim p lee xp re ssio n * )
i f s y in [p lu s, m in u s] then
1 50
IMPLEMENTATION KIT
begin (expression*);
sim pleexpression(fsys+[eql, neq, Iss, leq, gtr, geq], x);
i f sy In [eql, neq, Iss, leq, gtr, geq] then
begin op := sy; insymbol] sim pleexpression(fsys, y);
If (x. typ in [notyp, ints, bools, chars])
and (x. typ y. typ) (hen
case op of
eql: emit(A5);
neq: em it(A6);
Iss: emit(A7);
leq: emit(AS);
gtr: emit(A9);
geq: em it(50);
end
else error(ertyp);
x. typ := boots
end
end ( expression);
PROGRAM LISTING
152
IM PLEM EN TA T IO N K IT
A PPEN D IX
begin h i ; Ic;
insym boi-, statem ent([sem icoIon, u n tilsy]+ fsys);
while s y in [sem icolon)+ statbegsys do
begin {( s y sem ico lo n (hen in s y m b o i else errorierpun)sta te m e n t(\sem ico lo n , u n tilsy]+ fsys)
end;
i f s y * u n titsy then
begin in sym b o i; exp ressio n (fsys, x);
i f not (x. ty p in [b o o ls, n o ty p J) (hen error(ertyp)e tn it\ ( \ 1, Ic,)
v
end
else erro r(erkey)
end (repeatstatem etu*);
procedure w hile sta tem en t,
var x: item ; lc lc2: integer;
begin in s y m b o i, Ic, := Ic;
expression(Jsys+ [dosy], x );
i f not ( j r . ty p in [bools, n o ty p }) then erro rU rty p );
Icj : /c ;e m /7 ( ll) ;
i f sy d o s y (hen in s y m b o i else erro rierkey)sta te m e n t(fsys); e m i(l(1 0 , Ic,); code[lc2l y : /c
end (w h d esta tem en t* );
procedure fo rsta te m e n t;
var cvt: types; x: item ;
i> lc Ic,: integer;
begin in s y m b o i,
i f s y id e m then
begin i := lo c (id ); in sy m b o i,
i f i 0 then c v t : - in ts else
i f tab[i], o b j variable (hen
begin cv t := tab[i). typ;
i f s y * lo sy then
begin
in s y m b o i, expressionQdosy]-*- f s y s , * ) ;
i f jr. ty p < > cv t then erro r(ertyp )
end else sk ip ([ d o s y ] + fs y s , erkey );
lc t := Ic; em it( 14);
i f sy = d o s y then in s y m b o i else erro r(erkey);
lc2 := Ic; sta tem en t(fsys);
tm tflQ S , /c ,); code[lc,]. y
Ic
end (fo rsta te m e n t* );
procedure statidproc(n: integer);
v a r i, f: in teg er;
jr, y: item ;
begin
case n o f
1, 2: begin (*read)
i f s y = /pa ren t then
begin
repeat in s y m b o i,
i f s y < > id e m then erro r(erid ) else
begin i : lo c (id ); in sy m b o i,
i f i < > 0 then
i f lab[i]. o b j < > variable then e rro r(e rtyp ) else
begin x . ty p : tab[i]. ty p ; x . r e f := tab[i]. ref;
i f tab[i]. n o r m a l then / : = 0 else f : \ ;
e m it2 (f, tab[i]. le v, tab[i]. adr);
i f s y - Ibrack then
se le c lo r(fsy s+ [c o m m a , rparent], jr);
i f jr. ty p in [ms, ch a rs, n o ty p ] then
em it 1(27, o r d (x . ty p )) else erro r(ertyp )
P R O G R A M LISTIN G
SECT. A .8
end
end;
lest ([co m m a , rparent], fs y s , erk e y )
u n til s y < > co m m a ;
j f Sy = rp a ren t then in s y m b o i else erro r(e rp u n )
end;
i f n 2 then em 'tt(62)
end;
3, 4: begin (w rite * )
i f sy Iparetu then
begin
repeat in s y m b o i,
i f s y m strin g then
I S3
#
154
IM W .6 M tN T A T .0 N K IT
PR O G R A M LISTIN G
APPEN DIX
I 55
end;
beg in sy: i f id # co b eg in # then
begin em i't(4); co m p o u n d sta te m en t; em (5) end
else co m p o u n d sta te m en t;
ifsy: ifsta tem en t;
w hilesy: w hilestatem ent;
rep ea tsy: repeatstatem ent;
fo r s y : fo rsta tem en i;
end;
te st(fsys, [ J, erp u n )
end (*sta tem en t* );
begin ( b lo c k * ) d x : 5; p rt : *
i f level > Im a x then fa ta l(5 );
te st(ilp a ren t, c o lo n , se m ic o lo n ], fs y s , erp u n );
e n terb lo ck; display[level)
b ; p r b := b;
tab{prt]. ty p :m n o ty p ; tab[prt]. r e f : = p rb ;
ir (sy - Ip a ren t) and (level > 1) then para m eterlist;
b tab{prb). la stp a r := I; btab[prb]. p s iz e
d x;
i f isfu n then
i f i y - c o lo n then
begin in sy m b o l; (fu n c tio n ty p e* )
i f s y id e n t then
begin x
lo c (id )\ in sym b o l;
i f x < > 0 then
i f tab[x]. o b j < > ty p e 1 then e rro r(e rtyp ) else
i f tab[x]. ty p in s ta n typ s then tab{prt). ty p := iab{x]. typ
else erro r(ertyp )
end else sk ip ([se m ic o lo n ]+ fsy s, erid )
end else erro r(e rp u n );
i f s y - sem ico lo n then in s y m b o l else erro r(erp u n );
repeat
i f s y - co n stsy then co n sta n td ecla ra tio n;
i f Sy - ty p e sy then typedeclaration;
i f s y - va rsy then variabledeclaration;
b ta b {p rb ). vsize
d x;
w hile s y in [p ro c ed u resy, fu n c tio n sy ] do procd ecla ra tto n ;
test([b eg in sy), b lo ckb eg sys+ sta tb eg sys, e r k e y )
u n til s y in statbegsys;
tab[prt). a d r : Ic;
in sym b o l; sta te m e n t([se m ico lo n , e n d sy]+ fsys);
while s y in [se m ico lo n ]* sta tb e g sy s do
begin i f s y sem ico lo n then in s y m b o l else error(erpun);
sta te m e n td s e m ic o lo n , en d sy] + fsys)
156
IMPLEMENTATION KIT
APPENDIX
SECT. A.8
PROGRAM LISTING
begin d :*= p m a x + l;
curpr :* (curpr+trunc(ran*pmax)) mod (pmax + 1);
while ((not ptab[curpr]. active)
or (ptab[curpr\ s u s p e n d o ))
and (d > 0) do
begin d : d - 1; curpr :* (curpr* I ) mod (pmax-H ) end;
if d < 0 then
begin ps : deadlock; goto 98 end
else rtepcou/tl := trunc(ran stepmax)
end;
(functions lo convert integers to booleans and conversely*)
repeat
if p/afr[0]. active then curpr : = 0
else if stepcount 0 then chooseproc
else f tepcount := x/epcounr - 1;
with p/a6[curpr] do begin ir : code[pc]; pc
pc + 1 end;
if pflug then
begin if ir. / 18 (marfatacA;*) then Apr : /tpr + 1;
curpr : = /ipr
end;
with ptab[curpr] do
case *>. / of
IMPLEMENTATION KIT
APPENDIX
A,
s[<);I: f - 1;
P R O C R A M U S TING
SECT. A.*
end,
19: begin active := true; h x
t - i r . y;
h t :m j(A, + 4J; (*hi points to tab*)
A, :** to6{A3]. lev; dup/ay(Aj+l] : A,;
h t :* 4 * i + 3] + *ii
4*1+1]
pc; 4 *1 + 2]
dispfayihj;
if pflag then 4*i+ 3) :* ptab[0]. b else sf./** + 3] : b;
for A3 := r + 1 to h 4 do 4A>)
0;
b
A,; i :* h4; pc : /ab{Aj]. adr
end;
21: begin ()</) ht :* ir. y; (*A, points to atab*)
A* := Qtab[hx). low; A, :* 40;
if /ij < A2 then ps :* mxcAA else
i f fts > afafi[hx]. high then p s : inxchk else
begin t : / - I ; 40 := 40 + (A>-A2)flMA{A,).
end
end;
22: begin (Wood block*) h x
4 0 ; t * 1;
A, : ** ir. y + t; it h 2 > stacksize then ps : stkchk else
while / < />3 do
b e g in f : *
/+1;40 := 4*tl; * i
*+*
end
end;
23: begin (*copy block*) A,
4* I];
Ai
4 0 : *j
*i + ir- y\
while At < A} do
begin 4*i] * 4**1; *i :* * i+ l; *i :* *+1
end;
f := t - 2
end;
ISV
160
A PPE N D IX
36: sfrj :=
38: begin (*store*) 4 4 / - ] ] ] := j [ / ] ; i
t - 2 end;
S E C . A .8
P R O G R A M LISTIN G
161
45: begin / := f - 1 ; 4 0
*'< ( 4 0 4 '+ ! ] ) ndi
46: begin t := < -1 ; 4 0 : = *> M 4 0 < > 4 + l] ) n d .
47: begin t := i - l ; 4 0
i>fo(40 < 4 * + l))
48: begin t
/ - l ; 4 0 : fcw(40
4 < + U ) e nd>
49: begin / : - < -1 ; 4 0
&m<4 0 > 4 ' + U) end:
50: begin / := f - 1 ; 4 0 135 & (40 > 4 * + !]) nd;
51: begin t :* / - l ; 4 0
btoi(itob(s[t]) o r Uob(s[t+1]) ) end;
52: begin t :m f - 1 ; 4 0
4 0 + 4 '+ l ] e ndi
53: begin t
/ - l ; 4 0 := 4 0
4*+ 1 l t n d >
56: begin / := f - 1 ; 4 0 := btoi(iiob(s[i]) and itob(s[l+ 1])) end;
57: begin t := f - 1 ; 4 0 := 4 0
* 4 ' + l] e n d *
58: begin t i
f-1 ;
if 4 r + l ] 0 then ps := divchk ebe
4 0 := 4 0 div 4 < + l]
end;
59: begin t : / - l ;
If 4 r + l ] 0 then ps
divchk else
4 0 := 4 0 mod 4#+ )
end;
62: if eoJ\inpui) then p s : redchk else readln;
63: begin writeln; In c n t: Incnt + 1; chrcnt :** 0;
if Incnt > linelimtt then ps := linchk
end
end (*c<w**);
until ps < > rim ;
98: writeln;
if ps < > fin then
begin
with ptab{curpr\ do
write(ffOhah a t# ,p c : 5 ,# in process# , curpr: 4, tt because o f # ) ;
case ps of
deadlock: writeln(# deadlock#);
divchk: w riteln(# division by 0 0 ) ;
inxchk: write!n(# invalid index#);
stkchk: writeln(#storage overflow #);
linchk: w riteln(#too m uch output#);
Ingchk: writeln(#line too long#);
redchk: w riteln(# reading past end o f file # );
end;
writeln(#Qprocess active suspend p c # );
for h t := 0 to pm ax do with piab[ht] do
w riteln (# 0 # , h t : 4, active, suspend, pc);
writeln(#0global variables#);
162
IM P l E M bN T A T IO N K IT
fo r /,
btab{ 1). last + 1 to (m ax do
w ith ta t^ h ,] do I f le v < > 1 (hen goto 97
else I f o b j m variable then i f typ in sta n ty p s then
case ty p o f
ints: w rite ln (n a m ettt tt j[ a d r \) ;
bools: w riteln(nam e tt f ~ ft , itob(s[adr]));
chars: w r ite ln (n a m e ,# = f t , c h r (^ a d r ) mod 6 4 ));
end;
97: writeln
end (*interpret*);
m a m *
begin (* m a in )
n ie ssa g e(tt - co n cu rren t
key{ 1] : # a n d
key[ 3} := tt begin
key[ 5] : ft c o e n d
key{ 7]
tt d iv
key[ 9] : = ft else
ttfo r
k 'A n ]
k e y [ 13J : - t t i f
M 13J :*= ttn o t
k e y [l7 )
Hot
k e y [ 19] := tt pro g ra m
# then
*^21]
k e y f23] := # ty p e
key{2 5 ] ; = tt var
1] : andsy;
3] := b e g in sy ;
k s y [ 5] : endsy;
7] : *
ksy[ 9 ] : *
A^>{11] :
* J > {!3 ]
fa y { l5 ] :
As>( 17} :
Auyf 19J :
**>{21} : =
ksy{2 3 ]
ksy[2$] :=
idiv;
elsesy ;
fo r s y ;
ifsy;
noisy;
orsy;
pro g ra m sy,
thensy;
lypesy;
varsy;
p a sca l-stt);
tt
tt
tt
it
ft
ke y{ 2 ] :=e tta rr a y
it
ke y[ 4 ) :- * tt co b eg in tt
tt
k*A 6] : # co n st
ke y[ 8] :* *
tt
key[lO ) := c tt e n d
tt
k e y [ 12]: 1 tt fu n c tio n tt
ke y[ 1 4 ]:* ft m o d
tt
key[ 16] : t t o f
tt
*<>>[18]:- t t p ro ced u re tt
ke y[20] :* tt rep ea t
tt
tt
* 0 * 2 2 ] := f t to
*0*24] : tt u n til
tt
key[2 6 ]: tt w h ile
tt
ksy[ 2)
arraysy;
4]
beginsy;
ksy[ 6]
constsy;
ksy[ 8] :* d o sy;
k s y [ 10)
endsy;
ksy{ 12]
fu n c tio n s y ;
k s A 14]
im o d ;
Jb>{16) : o fsy;
*f*{18] p ro ced u resy;
repeatsy;
A*>{20]
k s r f2 2 \ : tosy;
ksy{2*\
untilsy;
ksy[26] : = whUesy;
SECT. A l
PR O G R AM LISTING
sp s[# + # ) p l u s \
s p s {tt-tt]\ =
s p s{# (# )
ip ij# )# )
Ip a re n t;
sp s{# = # ]
e q l;
s p s [ t t [ # ) to ra c *;
sp s{# ,# ] :=
com m a;
s p s{# }# \ :=
rbrack\
n eq ;
s p s{# & # ]
s p s { U ;t i) :
s e m ic o lo n ;
s p s[# * # ]
c o n stb eg sys : m
typ eb eg sy s :
b lo c k b e g s y s
m in u s ;
rp a ren t;
:=
163
: *
andsy;
lim e s ;
{ p lu s , m in u s , in t c o n , c h a r c o n , id e n t];
[ i d e n t , a r r a y s y J;
[c o /u tty , t y p e s y , v a r s y , p r o c e d u r e s y , fu n c t io n s y ,
: *
b e g in s y ];
fa c b e g s y s : =
[ w /c o /i, c h a r c o n , id e n t , Ip a r e n t , n o t s y ];
sta tb eg sys
[b e g m s y , i /j y , w h ile s y , r e p e a t s y , f o r s y ] ;
sta n ty p s
[ n o t y p , in t s , b o o ls , c h a r s ];
0 ; I
errp o s
:=
0 ;
t :=
I; a
Ic
0 ; cc : =
:=
c //s p /a y { 0 ] :
s k ip fla g
Ifs y
:
0 ; 6
0 ; ch
[ ); in s y m b o l;
:=
I ;
: 0 ; c2 :=
0 ;
1;
/in to ;
< >
p r o g r a m s y t h e n e,r / -t > r ( e r J t y ) e l s e
b e g in i n s y m b o l ;
ifs y
< >
id e m
I h e n e r r o r ( e r i d ) e ls e
b e g in p r o g n a m e
id ; in s y m b o l; end
end:
en te r{#
tt.
v a r ia b le , n o t y p , 0 ); ( s e n t in e l* )
e n te r (fffa b e
tt.
k o n s t a n t , b o o ls , 0 );
en ter(# tru e
tt.
k o n s ta n t, b o o ls ,
en ter(# c h a r
tt.
ty p e 1 , c h a rs,
1 );
e n t e i i # b o o le a n
tt.
ty p e 1 , b o o b ,
1 );
e n t e r ( ff in t e g e r
tt.
ty p e 1 , in is ,
en ter(# eo f
# ,
fu n k t io n , b o o b ,
1 7 );
en ter(tteo U \
tt.
fu n k t io n , b o o b ,
1 8 );
en te r(# re a d
tt,
p r o z e d u r e , n o t y p , 1);
e n te r (tf r e a d ln
tt,
p r o z e d u r e , n o t y p , 2 );
e n t e r ( # w r it e
tt.
p r o z e d u r e , n o t y p , 3 );
e n t e r ( # w r it e ln
tt.
p r o z e d u r e , n o t y p , 4 );
e n te r {# w a it
#>
e n te r (ffs ig n a l
tt.
p r o z e d u r e , n o t y p , 6 );
e n ter(#
tt.
p r o z e d u r e , n o t y p , 0 );
w ith
1 );
1 );
p r o z e d u r e , n o t y p , 5 );
6 ra 6 [ l ] d o
b e g i n l a s t ::
end;
t ; l a s t p a r ;: =
1 ; p s iz e
:=
0 ; v s iz e : =
ff
164
IM KLKM EN TATIO N K IT
AP]