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:
BOOL ←
FALSE]
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.