Professional Documents
Culture Documents
Monitors: An Operating System Structuring Concept: C.A.R. Hoare The Queen's University of Belfast
Monitors: An Operating System Structuring Concept: C.A.R. Hoare The Queen's University of Belfast
Weissman
Systems Editor
Monitors: An I. Introduction
This exhibits a pleasing symmetry with the rule for and two variables:
waiting. (1) l a s t p o i n t e r : O . . N - 1;
The introduction of condition variables makes it
possible to write monitors subject to the risk of deadly which points to the buffer position into which the next
embrace [7]. It is the responsibility of the p r o g r a m m e r append operation will put a new item, and
to avoid this risk, together with other scheduling disasters (2) count:O..N;
(thrashing, indefinitely repeated overtaking, etc. [11]).
which always holds the length of the sequence (initially
Assertion-oriented p r o o f methods cannot prove absence
0).
of such risks; perhaps it is better to use less formal
We define the function
methods for such proofs.
Finally, in m a n y cases an operating system monitor seq (b,l,c) =dS if C = 0 then empty
constructs some "virtual" resource which is used else seq(b,lOl,c- 1) n(b[lG1])
in place of actual resources by its " c u s t o m e r " pro- where the circled operations are taken modulo N. Note
grams. This virtual resource is an abstraction from that i f c ~ O,
the set of local variables of the monitor. The program
first(seq(b,l,c) ) = b[l~c]
prover should therefore define this abstraction in terms
of its concrete representation, and then express the in- and
tended effect of each of the procedure bodies in terms of rest(seq( b,l,c) ) = seq(b,l,c- 1)
the abstraction. This p r o o f method is described in detail
in [13]. The definition of the abstract sequence in terms of its
concrete representation m a y now be given:
sequence =as seq(buffer, lastpointer, count)
4. Example: Bounded Buffer
Less formally, this may be written
sequence =as (buffer[last pointerOcount ],
A bounded buffer is a concrete representation of the
buffer[lastpointerOcountQ1 ],
abstract idea of a sequence of portions. The sequence is
accessible to two programs running in parallel: the first buffe r[lastpointerO 1])
of these (the producer) updates the sequence by append-
Another way of conveying this information would be by
ing a new portion x at the end; and the second (the
an example and a picture, which would be even less
consumer) updates it by removing the first portion. The
formal.
initial value of the sequence is empty. We thus require
The invariant for the monitor is:
two operations:
0 <_ count < N & 0 <_ lastpointer < N -- 1
(1) append(x:portion) ;
There are two reasons for waiting, which must be
which should be equivalent to the abstract operation represented by condition variables:
sequence := sequence n (x);
nonem pty : condition;
where (x) is the sequence whose only item is x and n de- means that the count is greater than 0, and
notes concatenation of two sequences.
nonfull: condition;
(2) remove(result x: portion) ;
means that the count is less than N.
In the program given above, the next candidate for nonempty : condition
wakening is actually woken at every tick of the clock. which means that f r e e p o o l ~ empty. The code for the
This will not matter if the frequency of ticking is low allocator is:
enough, and the overhead of an accepted signal is not
buffer allocator: monitor
too high.
begin freepool: powerset bufferaddress;
I am grateful to A. Ballard and J. Horning for posing nonempty : condition;
this problem. procedure acquire (result b: bufferaddress) ;
begin if freepool = empty then nonempty.wait;
b := first(freepool) ;
comment Any one would do;
6. Further Examples freepool : = freepool -- {b } ;
comment Set subtraction;
end acquire;
In proposing a new feature for a high level language
procedure release(b :bufferaddress) ;
it is very difficult to make a convincing case that the begin freepool : = freepool -- {b } ;
feature will be both easy to use efficiently and easy to nonempty, signal
implement efficiently. Quality of implementation can be end release;
proved by a single good example, but ease and efficiency freepool := all buffer addresses
end buffer allocator
of use require a great number of realistic examples;
otherwise it can appear that the new feature has been The action of a producer and consumer m a y be
specially designed to suit the examples, or vice versa• summarized:
This section contains a number of additional examples producer: begin b :bufferaddress; . . .
of solutions of familiar problems• Further examples may while not finished do
be found in [14]. begin bufferallocator, acquire(b) ;
• . . fill buffer b . . . ;
bounded buffer, append(b)
6.1 Buffer Allocation end;...
end producer;
The bounded buffer described in Section 4 was
designed to be suitable only for seque.nces with small consumer: begin b: bufferaddress; . ..
while not finished do
portions, for example, message queues• If the buffers
begin bounded buffer, remove(b) ;
contain high volume information (for example, files for • . . empty buffer b . . . ;
pseudo offline input and output), the bounded buffer buffer allocator, release(b)
may still be used to store the a d d r e s s e s of the buffers end;...
which are being used to hold the information. In this end consumer;
way, the producer can be filling one buffer while the This buffer allocator would appear to be usable to
consumer is emptying another buffer of the same se- share the buffers a m o n g several streams, each with its
quence. But this requires an allocator for dynamic own producer and its own consumer, and its own in-
acquisition and relinquishment of b u f f e r a d d r e s s e s . stance of a bounded buffer monitor. Unfortunately,