Copyright (C) 1994, Digital Equipment Corp. UNSAFE MODULE--------------------------------------------------- process termination ---; IMPORT WinBase, WinNT, WinCon, WinDef; RTOS
PROCEDURE------------------------------------------------------------- allocator ---Exit (n: INTEGER) = BEGIN WinBase.ExitProcess (n); END Exit; PROCEDURECrash () = VAR ptr := LOOPHOLE(-99, UNTRACED REF INTEGER); BEGIN ptr^ := 99; (* try to get to the debugger... *) WinBase.FatalExit (-1); END Crash;
PROCEDURE------------------------------------------------------------- collector --- These procedures provide synchronization primitives for the allocator and collector. This is the Windows/NT version, and depends on the NT thread implementation.GetMemory (size: INTEGER): ADDRESS = (* Return the address of "size" bytes of unused storage *) BEGIN RETURN LOOPHOLE(WinBase.LocalAlloc(WinBase.LMEM_FIXED, 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.
VAR cs: WinBase.LPCRITICAL_SECTION := NIL; csstorage: WinNT.RTL_CRITICAL_SECTION; PROCEDUREUnlockHeap() leaves the critical section. It could be written at user level as:LockHeap () = BEGIN IF (cs = NIL) THEN cs := ADR(csstorage); WinBase.InitializeCriticalSection(cs); END; WinBase.EnterCriticalSection(cs); END LockHeap;
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.
PROCEDURE------------------------------------------------------------------- I/O ---UnlockHeap () = BEGIN WinBase.LeaveCriticalSection(cs); END UnlockHeap;
VAR
ready := FALSE;
stderr : WinDef.HANDLE;
(* Perhaps we should explicitly open CONERR$ et al,
in case of redirection by parent? *)
PROCEDURE Write (a: ADDRESS; n: INTEGER) =
VAR nWritten: INTEGER;
BEGIN
IF NOT ready THEN
EVAL WinCon.AllocConsole(); (* make sure we've got one! *)
stderr := WinBase.GetStdHandle(WinBase.STD_ERROR_HANDLE);
ready := TRUE;
END;
EVAL WinBase.WriteFile(stderr, a, n, ADR(nWritten), NIL);
END Write;
BEGIN
END RTOS.