Initial revision
This commit is contained in:
337
doc/occam/p3
Normal file
337
doc/occam/p3
Normal file
@@ -0,0 +1,337 @@
|
||||
.NH
|
||||
Implementation
|
||||
.PP
|
||||
It is now time to describe the implementation of some of the occam-specific
|
||||
features such as channels and \fBNOW\fP. Also the way communication with
|
||||
UNIX\(dg is performed must be described.
|
||||
.FS
|
||||
\(dg UNIX is a trademark of Bell Laboratories
|
||||
.FE
|
||||
For a thorough description of the library routines to simulate parallelism,
|
||||
which are e.g. used by the channel routines and by the \fBPAR\fP construct
|
||||
in Appendix B, see [6].
|
||||
.NH 2
|
||||
Channels
|
||||
.PP
|
||||
There are currently two types of channels (see Figure 1.) indicated by the type
|
||||
field of a channel variable:
|
||||
.IP -
|
||||
An interprocess communication channel with two additional fields:
|
||||
.RS
|
||||
.IP -
|
||||
A synchronization field to hold the state of an interprocess communication
|
||||
channel.
|
||||
.IP -
|
||||
An integer variable to hold the value to be send.
|
||||
.RE
|
||||
.IP -
|
||||
An outside world communication channel. This is a member of an array of
|
||||
channels connected to UNIX files. Its additional fields are:
|
||||
.RS
|
||||
.IP -
|
||||
A flags field holding a readahead flag and a flag that tells if this channel
|
||||
variable is currently connected to a file.
|
||||
.IP -
|
||||
A preread character, if readahead is done.
|
||||
.IP -
|
||||
An index field to find the corresponding UNIX file.
|
||||
.RE
|
||||
.LP
|
||||
.PS
|
||||
box ht 3.0 wid 3.0
|
||||
box ht 0.75 wid 0.75 with .nw at 1st box.nw + (0.5, -0.5) "Process 1"
|
||||
box ht 0.75 wid 0.75 with .ne at 1st box.ne + (-0.5, -0.5) "Process 2"
|
||||
box ht 0.75 wid 0.75 with .sw at 1st box.sw + (0.5, 0.5) "Process 3"
|
||||
box ht 0.75 wid 0.75 with .se at 1st box.se + (-0.5, 0.5) "Process 4"
|
||||
line right from 5/12 <2nd box.ne, 2nd box.se> to 3rd box
|
||||
line right from 7/12 <2nd box.ne, 2nd box.se> to 3rd box
|
||||
line right from 5/12 <4th box.ne, 4th box.se> to 5th box
|
||||
line right from 7/12 <4th box.ne, 4th box.se> to 5th box
|
||||
line down from 5/12 <2nd box.sw, 2nd box.se> to 4th box
|
||||
line down from 7/12 <2nd box.sw, 2nd box.se> to 4th box
|
||||
line down from 5/12 <3rd box.sw, 3rd box.se> to 5th box
|
||||
line down from 7/12 <3rd box.sw, 3rd box.se> to 5th box
|
||||
line right 1.0 from 5/12 <5th box.ne, 5th box.se>
|
||||
line right 1.0 from 7/12 <5th box.ne, 5th box.se>
|
||||
line left 1.0 from 5/12 <2nd box.nw, 2nd box.sw>
|
||||
line left 1.0 from 7/12 <2nd box.nw, 2nd box.sw>
|
||||
.PE
|
||||
.DS C
|
||||
\fIFigure 1. Interprocess and outside world communication channels\fP
|
||||
.DE
|
||||
The basic channel handling is done by \f5chan_in\fP and \f5chan_out\fP. All
|
||||
other routines are based on them. The routine \f5chan_any\fP only checks if
|
||||
there's a value available on a given channel. (It does not read this value!)
|
||||
\f5C_init\fP initializes an array of interprocess communication channels.
|
||||
.LP
|
||||
The following table shows Occam statements paired with the routines used to
|
||||
execute them.
|
||||
.TS H
|
||||
center, box;
|
||||
c | c | c
|
||||
lf5 | lf5 | lf5.
|
||||
Occam statement Channel handling routine Called as
|
||||
=
|
||||
.sp 0.5
|
||||
.TH
|
||||
T{
|
||||
.nf
|
||||
CHAN c:
|
||||
CHAN c[z]:
|
||||
.fi
|
||||
T} T{
|
||||
.nf
|
||||
c_init(c, z)
|
||||
chan *c; unsigned z;
|
||||
.fi
|
||||
T} T{
|
||||
.nf
|
||||
c_init(&c, 1);
|
||||
c_init(&c, z);
|
||||
.fi
|
||||
T}
|
||||
.sp 0.5
|
||||
_
|
||||
.sp 0.5
|
||||
T{
|
||||
.nf
|
||||
c ? v
|
||||
.fi
|
||||
T} T{
|
||||
.nf
|
||||
chan_in(v, c)
|
||||
long *v; chan *c;
|
||||
.fi
|
||||
T} T{
|
||||
.nf
|
||||
chan_in(&v, &c);
|
||||
.fi
|
||||
T}
|
||||
.sp 0.5
|
||||
T{
|
||||
.nf
|
||||
c ? b[byte i]
|
||||
.fi
|
||||
T} T{
|
||||
.nf
|
||||
cbyte_in(b, c)
|
||||
char *b; chan *c;
|
||||
.fi
|
||||
T} T{
|
||||
.nf
|
||||
cbyte_in(&b[i], &c);
|
||||
.fi
|
||||
T}
|
||||
.sp 0.5
|
||||
T{
|
||||
.nf
|
||||
c ? a[i for z]
|
||||
.fi
|
||||
T} T{
|
||||
.nf
|
||||
c_wa_in(a, z, c)
|
||||
long *a; unsigned z; chan *c;
|
||||
.fi
|
||||
T} T{
|
||||
.nf
|
||||
c_wa_in(&a[i], z, &c);
|
||||
.fi
|
||||
T}
|
||||
.sp 0.5
|
||||
T{
|
||||
.nf
|
||||
c ? a[byte i for z]
|
||||
.fi
|
||||
T} T{
|
||||
.nf
|
||||
c_ba_in(a, z, c)
|
||||
long *a; unsigned z; chan *c;
|
||||
.fi
|
||||
T} T{
|
||||
.nf
|
||||
c_ba_in(&a[i], z, &c);
|
||||
.fi
|
||||
T}
|
||||
.sp 0.5
|
||||
_
|
||||
.sp 0.5
|
||||
T{
|
||||
.nf
|
||||
c ! v
|
||||
.fi
|
||||
T} T{
|
||||
.nf
|
||||
chan_out(v, c)
|
||||
long *v; chan *c;
|
||||
.fi
|
||||
T} T{
|
||||
.nf
|
||||
chan_out(&v, &c);
|
||||
.fi
|
||||
T}
|
||||
.sp 0.5
|
||||
T{
|
||||
.nf
|
||||
c ! a[i for z]
|
||||
.fi
|
||||
T} T{
|
||||
.nf
|
||||
c_wa_out(a, z, c)
|
||||
long *a; unsigned z; chan *c;
|
||||
.fi
|
||||
T} T{
|
||||
.nf
|
||||
c_wa_out(&a[i], z, &c);
|
||||
.fi
|
||||
T}
|
||||
.sp 0.5
|
||||
T{
|
||||
.nf
|
||||
c ! a[byte i for z]
|
||||
.fi
|
||||
T} T{
|
||||
.nf
|
||||
c_ba_out(a, z, c)
|
||||
long *a; unsigned z; chan *c;
|
||||
.fi
|
||||
T} T{
|
||||
.nf
|
||||
c_ba_out(&a[i], z, &c);
|
||||
.fi
|
||||
T}
|
||||
.sp 0.5
|
||||
_
|
||||
.sp 0.5
|
||||
T{
|
||||
.nf
|
||||
alt
|
||||
c ? ....
|
||||
....
|
||||
.fi
|
||||
T} T{
|
||||
.nf
|
||||
int chan_any(c)
|
||||
chan *c;
|
||||
.fi
|
||||
T} T{
|
||||
.nf
|
||||
deadlock=0;
|
||||
for(;;) {
|
||||
if (chan_any(&c)) {
|
||||
....
|
||||
....
|
||||
.fi
|
||||
T}
|
||||
.sp 0.5
|
||||
.TE
|
||||
The code of \f5c_init\fP, \f5chan_in\fP, \f5chan_out\fP and \f5chan_any\fP
|
||||
can be found in Appendix A.
|
||||
.NH 3
|
||||
Synchronization on interprocess communication channels
|
||||
.PP
|
||||
The synchronization field can hold three different values indicating the
|
||||
state the channel is in:
|
||||
.IP "- \fBC\(ulS\(ulFREE\fP:" 15
|
||||
Ground state, channel not in use.
|
||||
.IP "- \fBC\(ulS\(ulANY\fP:" 15
|
||||
Channel holds a value, the sending process is waiting for an acknowledgement
|
||||
about its receipt.
|
||||
.IP "- \fBC\(ulS\(ulACK\fP:" 15
|
||||
Channel data has been removed by a receiving process, the sending process can
|
||||
set the channel free now.
|
||||
.LP
|
||||
A sending process cannot simply wait until the channel changes state C\(ulS\(ulANY
|
||||
to state C\(ulS\(ulFREE before it continues. There is a third state needed to prevent
|
||||
a third process from using the channel before our sending process is
|
||||
acknowledged. Note, however that it is not allowed to use a channel for input
|
||||
or output in more than one parallel process. This is too difficult to check
|
||||
in practice, so we tried to smooth it a little.
|
||||
.NH 2
|
||||
NOW
|
||||
.PP
|
||||
\fBNOW\fP evaluates to the current time returned by the time(2) system call.
|
||||
The code is simply:
|
||||
.DS
|
||||
.ft 5
|
||||
.nf
|
||||
long now()
|
||||
{
|
||||
deadlock=0;
|
||||
return time((long *) 0);
|
||||
}
|
||||
.fi
|
||||
.ft
|
||||
.DE
|
||||
The ``deadlock=0'' prevents deadlocks while using the clock.
|
||||
.NH 2
|
||||
UNIX interface
|
||||
.PP
|
||||
To handle the communication with the outside world the following channels are
|
||||
defined:
|
||||
.IP -
|
||||
\fBinput\fP, that corresponds with the standard input file,
|
||||
.IP -
|
||||
\fBoutput\fP, that corresponds with the standard output file,
|
||||
.IP -
|
||||
\fBerror\fP, that corresponds with the standard error file.
|
||||
.IP -
|
||||
\fBfile\fP, an array of channels that can be subscripted with an index
|
||||
obtained by the builtin named process ``\f5open\fP''. Note that
|
||||
\fBinput\fP=\fBfile\fP[0], \fBoutput\fP=\fBfile\fP[1] and
|
||||
\fBerror\fP=\fBfile\fP[2].
|
||||
.LP
|
||||
Builtin named processes to open and close files are defined as
|
||||
.DS
|
||||
.nf
|
||||
.ft 5
|
||||
proc open(var index, value name[], mode[]) = ..... :
|
||||
proc close(value index) = ..... :
|
||||
.fi
|
||||
.ft
|
||||
.DE
|
||||
To open a file `junk', write nonsense onto it, and close it, goes as follows:
|
||||
.DS
|
||||
.ft 5
|
||||
.nf
|
||||
var i:
|
||||
seq
|
||||
open(i, "junk", "w")
|
||||
file[i] ! nonsense
|
||||
close(i)
|
||||
.fi
|
||||
.ft
|
||||
.DE
|
||||
Errors opening a file are reported by a negative index, which is the
|
||||
negative value of the error number (called \fIerrno\fP in UNIX).
|
||||
.LP
|
||||
Bytes read from or written onto these channels are taken from occam variables.
|
||||
As these variables can hold more than 256 values, some negative values are used
|
||||
to control channels. These values are:
|
||||
.IP "- \fBEOF\fP" 9
|
||||
(-1): Eof from file channel is read as -1.
|
||||
.IP "- \fBTEXT\fP" 9
|
||||
(-2): A -2 written onto any channel connected to a terminal puts this
|
||||
terminal in the normal line oriented mode (i.e. characters typed are echoed
|
||||
and lines are buffered before they are read).
|
||||
.IP "- \fBRAW\fP" 9
|
||||
(-3): A -3 written onto any channel connected to a terminal puts it in raw mode
|
||||
(i.e. no echoing of typed characters and no line buffering).
|
||||
.LP
|
||||
To exit an Occam program, e.g. after an error, a builtin named process
|
||||
\f5exit\fP is available that takes an exit code as its argument.
|
||||
.NH 2
|
||||
Replicators and slices
|
||||
.PP
|
||||
Both the base and the count of replicators like in
|
||||
.DS
|
||||
.ft 5
|
||||
par i = [ base for count ]
|
||||
.ft
|
||||
.DE
|
||||
may be arbitrary expressions. The count in array slices like in
|
||||
.DS
|
||||
.ft 5
|
||||
c ? A[ base for count ]
|
||||
.ft
|
||||
.DE
|
||||
must be a constant expression however, the base is again free.
|
||||
Reference in New Issue
Block a user