Last Modified 7th April 2002
On KRoC/Linux, use the `-d' flag to the `kroc' command to turn on debugging. You'll need to re-compile all the various bits of code used in order to get useful debug information. When the program crashes now, it will report where the error happened. If the program deadlocks, KRoC will print information about any processes which were blocked, either on channel I/O or an ALT.
A random number generator is provided in the course library. It's header (interface) reads:
INT, INT FUNCTION random (VAL INT upto, seed)This returns an integer in the range 0 to `(upto - 1)' inclusive as the first result and a new seed as the second result. One would normally use this in the following way:
INT v, seed: SEQ ... initialise seed correctly v, seed := random (20, seed) ... use v (in the range 0-19 inclusive)The seed must be initialised to an integer between 1 and `((MOSTPOS INT) - 1)' inclusive. A useful method is to get an initial seed from a TIMER then adjust to make it a valid seed.
A channel can be made shared in one of three ways:
#INCLUDE "semaphore.inc"Since standard occam doesn't permit automatic sharing of channel-ends, you need to make explicit the shared nature of channels and data (semaphores):
CHAN OF INT shared.chan: #PRAGMA SHARED shared.chan SEMAPHORE chan.sem: #PRAGMA SHARED chan.semThe `#PRAGMA SHARED' declaration must immediately follow the declaration. You can in a similar way share parameters and abbreviations:
PROC foo (CHAN OF INT to.harvester, SEMAPHORE harvester.sem) #PRAGMA SHARED to.harvester, harvester.sem ... :As a working example, the following code shows a simple multiplexing channel (of INTs), where multiple workers feed into a single harvester:
#USE "course.lib" #INCLUDE "semaphore.inc" PROC worker (VAL INT id, CHAN OF INT out, SEMAPHORE out.sem) SEQ i = 0 FOR 10 INT v: SEQ v := (id + 1) * i ... compute some more -- need to claim semaphore before using shared channel claim.semaphore (out.sem) out ! v -- and release again afterwards release.semaphore (out.sem) : PROC harvester (CHAN OF INT in, CHAN OF BYTE out) WHILE TRUE INT v: SEQ in ? v out.int (v, 0, out) out ! '*n' : PROC farm (CHAN OF BYTE keyboard, screen, error) CHAN OF INT work.done: #PRAGMA SHARED work.done SEMAPHORE work.sem: #PRAGMA SHARED work.sem: SEQ -- initialise the semaphore to 1 (binary semaphore/mutex) initialise.semaphore (work.sem, 1) -- do network PAR harvester (work.done, screen) PAR i = 0 FOR 20 worker (i, work.done, work.sem) :
Time in occam is absolute, ie, there is no direct way to say ``sleep for n micro-seconds''. The two things available are:
PROC udelay (VAL INT usecs) TIMER tim: INT t: SEQ tim ? t tim ? AFTER (t PLUS usecs) :The value of `usecs' can be any valid integer. Negative numbers cause no delay, since that time has already passed. The maximum delay is ``MOSTPOS INT'' (2,147,483,647), but using value this big is unlikely to work, due to the wrap-around caused by the very slight delay between reading the time and waiting for `t PLUS usecs'. The maximum delay turns out to be about 35 minutes.
This error happens when the system runs out of (system-V) style semaphores, which are used in the handling of blocking system-calls. Sometimes when programs exit they leave behind semaphores, usually if the program crashes in an unexpected way. KRoC sometimes leaves behind semaphores, but efforts are made to clean-up after itself. However, semaphores sometimes get left behind if KRoC exits without the opportunity to clean-up the blocking system calls (if sent a KILL signal or if it segfaults internally).
The fix is to delete the semaphores which are no longer needed. On most modern systems, /proc/sysvipc/sem exists which can be consulted for any specific offending semaphore identifiers. Care should be taken not to remove semaphores which are in use by other programs (sane programs should use the semaphore permission bits to stop others intefering, but some don't). A little utility to remove semaphore identifiers can be downloaded here (2.1k). To compile it, do:
gcc -o rmsem rmsem.cThis (rmsem) can be run without arguments in which case it will try and delete all semaphore identifiers, or with specific identifiers as arguments. Removing a semaphore which a program is using will probably cause the program to exit with an error.