CountedVMImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Taft, December 10, 1983 3:03 pm
Plass, December 21, 1983 1:33 pm
Russ Atkinson (RRA) August 22, 1985 5:31:08 pm PDT
Doug Wyatt, February 26, 1985 10:20:58 am PST
DIRECTORY
CountedVM USING [Handle, Object],
Process USING [Detach, MsecToTicks, Pause],
SafeStorage USING [CantEstablishFinalization, EnableFinalization, EstablishFinalization, FinalizationQueue, FQNext, NewFQ, ReclaimCollectibleObjects, ReEstablishFinalization],
VM USING [AddressForPageNumber, Allocate, CantAllocate, Free, Interval, LogPageCount, nullInterval, PageCount, PagesForWords, PageNumber, VMPartition];
CountedVMImpl: CEDAR MONITOR
IMPORTS Process, SafeStorage, VM
EXPORTS CountedVM
~ BEGIN
Handle: TYPE ~ CountedVM.Handle;
Object: TYPE ~ CountedVM.Object;
tries: NAT ← 4;
# of times to try to collect extra garbage before giving up
Allocate: PUBLIC PROC [words: INT,
partition: VM.VMPartition ← normalVM, subRange: VM.Interval ← [0, 0],
start: VM.PageNumber ← 0, alignment: VM.LogPageCount ← 0, in64K: BOOLFALSE] RETURNS [h: Handle ← NIL] = {
IF words > 0 THEN TRUSTED {
count: VM.PageCount ~ VM.PagesForWords[words];
FOR i: NAT IN [0..tries] DO
interval: VM.Interval ~ VM.Allocate[count: count, partition: partition, subRange: subRange, start: start, alignment: alignment, in64K: in64K
! VM.CantAllocate => {
There is a possibility that if we could collect some outstanding goodies that we could get enough VM to make all of this work out OK. If we have performed enough GCs, though, we allow the signal to percolate upwards.
IF i = tries THEN REJECT;
SafeStorage.ReclaimCollectibleObjects[suspendMe: TRUE, traceAndSweep: FALSE];
Process.Pause[Process.MsecToTicks[200]];
LOOP;
}];
h ← NEW[Object ← [interval: interval, pointer: VM.AddressForPageNumber[interval.page], words: words]];
SafeStorage.EnableFinalization[h];
EXIT;
ENDLOOP;
};
};
SimpleAllocate: PUBLIC PROC [words: INT] RETURNS [Handle] = {
RETURN[Allocate[words: words]];
};
Free: PUBLIC ENTRY UNSAFE PROC [handle: Handle] = {
ENABLE UNWIND => NULL;
IF handle # NIL AND handle.pointer # NIL AND handle.words # 0 THEN {
We can try to free this interval
interval: VM.Interval ← handle.interval;
handle.pointer ← NIL;
handle.words ← 0;
handle.interval ← VM.nullInterval;
TRUSTED {VM.Free[interval]};
};
};
finalizationQueue: SafeStorage.FinalizationQueue ← SafeStorage.NewFQ[];
FinalizationProcess: PROC ~ {
DO
h: Handle ← NARROW[SafeStorage.FQNext[finalizationQueue]];
TRUSTED {Free[h]};
h ← NIL;
ENDLOOP;
};
SafeStorage.EstablishFinalization[Object.CODE, 0, finalizationQueue
! SafeStorage.CantEstablishFinalization => {
SafeStorage.ReEstablishFinalization[Object.CODE, 0, finalizationQueue];
CONTINUE;
}];
TRUSTED {Process.Detach[FORK FinalizationProcess]};
END.