UNSAFE MODULE--------------------------------------------------- process termination ---; IMPORT Unix, Uuio, Cstdlib, RT0u, Thread; RTOS
PROCEDURE------------------------------------------------------------- allocator ---Exit (n: INTEGER) = BEGIN Unix.exit (n); END Exit; PROCEDURECrash () = BEGIN Cstdlib.abort (); LOOP END; (* wait *) END Crash;
PROCEDURE------------------------------------------------------------- collector --- These procedures provide synchronization primitives for the allocator and collector. This is the Ultrix version, and depends on the Ultrix user-level thread implementation.GetMemory (size: INTEGER): ADDRESS = (* Return the address of "size" bytes of unused storage *) BEGIN RETURN LOOPHOLE(Unix.sbrk(size), ADDRESS); END GetMemory;
LockHeap() enters a critical section; the same thread may enter the critical section multiple times. It could be written at user level as:
VAR
mutex : MUTEX := NEW(MUTEX);
condition: Thread.Condition := NEW(Thread.Condition);
thread : Thread.T := NIL;
count : CARDINAL := 0;
PROCEDURE LockHeap () =
BEGIN
LOCK mutex DO
IF count = 0 THEN
thread := Thread.Self();
INC(count);
ELSIF thread = Thread.Self() THEN
INC(count);
ELSE
Thread.Wait(mutex, condition);
END;
END;
END LockHeap;
However, it must be possible to call it from anywhere in the
collector.
UnlockHeap() leaves the critical section. It could be written at user level as:
PROCEDURE UnlockHeap () =
BEGIN
LOCK mutex DO DEC(count); END;
IF count = 0 THEN Thread.Signal(condition); END;
END UnlockHeap;
However, it must be possible to call it from anywhere inside the
collector.
VAR lock_cnt := 0; (* LL = RT0u.inCritical *) do_signal := FALSE; (* LL = RT0u.inCritical *) mutex := NEW(MUTEX); condition := NEW(Thread.Condition); PROCEDURE------------------------------------------------------------------- I/O ---LockHeap () = BEGIN INC(RT0u.inCritical); INC(lock_cnt); END LockHeap; PROCEDUREUnlockHeap () = VAR sig := FALSE; BEGIN DEC(lock_cnt); IF (lock_cnt = 0) AND (do_signal) THEN sig := TRUE; do_signal := FALSE; END; DEC(RT0u.inCritical); IF (sig) THEN Thread.Broadcast(condition); END; END UnlockHeap; PROCEDUREWaitHeap () = (* LL = 0 *) BEGIN LOCK mutex DO Thread.Wait(mutex, condition); END; END WaitHeap; PROCEDUREBroadcastHeap () = (* LL = RT0u.inCritical *) BEGIN do_signal := TRUE; END BroadcastHeap;
PROCEDUREWrite (a: ADDRESS; n: INTEGER) = BEGIN EVAL Uuio.write (2, a, n); END Write; BEGIN END RTOS.