<<>> <> <> <> <> <> <> <> <> <> <> <<>> DIRECTORY CountedVM USING [Handle, Object], CountedVMSidedoor USING [], FinalizeOps USING [CallQueue, CreateCallQueue, EnableFinalization, FinalizeProc], RegisterRefLiteral USING [Create], VM USING [AddressForPageNumber, Allocate, FalseBool, Free, Interval, LogPageCount, nullInterval, NullInterval, PageCount, PagesForWords, VMPartition, ZeroPageNumber]; CountedVMImpl: CEDAR MONITOR IMPORTS FinalizeOps, RegisterRefLiteral, VM EXPORTS CountedVM, CountedVMSidedoor ~ BEGIN Handle: TYPE ~ CountedVM.Handle; Object: TYPE ~ CountedVM.Object; allocatedPages: REF INT ¬ NEW[INT ¬ 0]; allocatedObjects: REF INT ¬ NEW[INT ¬ 0]; freedPages: REF INT ¬ NEW[INT ¬ 0]; freedObjects: REF INT ¬ NEW[INT ¬ 0]; <> <> statistics: PUBLIC --CountedVMSidedoor-- LIST OF REF ANY ¬ LIST[MakeAtom["allocatedPages"], allocatedPages, MakeAtom["allocatedObjects"], allocatedObjects, MakeAtom["freedPages"], freedPages, MakeAtom["freedObjects"], freedObjects]; tries: NAT ¬ 3; <<# of times to try to collect extra garbage before giving up>> AllocateStat: ENTRY PROC [pages: INT] = { allocatedObjects­ ¬ allocatedObjects­ + 1; allocatedPages­ ¬ allocatedPages­ + pages; }; Allocate: PUBLIC PROC [words: INT, partition: VM.VMPartition ¬ normalVM, subRange: VM.NullInterval ¬ [0, 0], start: VM.ZeroPageNumber ¬ 0, alignment: VM.LogPageCount ¬ 0, in64K: VM.FalseBool ¬ 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 << This doesn't make much sense in a pcr world.... ! VM.CantAllocate => { <> 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]]; [] ¬ FinalizeOps.EnableFinalization[h, fq]; AllocateStat[interval.count]; EXIT; ENDLOOP; }; }; SimpleAllocate: PUBLIC PROC [words: INT] RETURNS [Handle] = { RETURN[Allocate[words: words]]; }; Free: PUBLIC ENTRY UNSAFE PROC [handle: Handle] = { IF handle # NIL AND handle.pointer # NIL AND handle.words # 0 THEN { <> interval: VM.Interval ¬ handle.interval; handle.pointer ¬ NIL; handle.words ¬ 0; handle.interval ¬ VM.nullInterval; TRUSTED {VM.Free[interval]}; freedObjects­ ¬ freedObjects­ + 1; freedPages­ ¬ freedPages­ + interval.count; }; handle ¬ NIL; }; Finalize: FinalizeOps.FinalizeProc ~ { h: Handle ¬ NARROW[object]; TRUSTED { Free[h] }; }; MakeAtom: PROC [ s: STRING ] RETURNS [ATOM] ~ { RETURN[NARROW[RegisterRefLiteral.Create[CODE[ATOM], s]]]; }; fq: FinalizeOps.CallQueue ~ FinalizeOps.CreateCallQueue[Finalize]; END.