<> <> <> <> DIRECTORY Allocator USING [bsiEscape, ExtendedHeader, HeaderP, NHeaderP, pagesPerQuantum, QuantumIndex, wordsPerQuantum, LastAddress, NormalHeader], AllocatorOps USING [EnterAndCallBack, quantumMap, BlockSize], Process USING [Pause], SafeStorage USING [Type], SweepCollectableStorage USING [InfoProc], VM USING [Interval, SwapIn], ZCT USING [EnterAndCallBack, EnterRCOvAndCallBack]; SweepCollectableStorageImpl: PROGRAM IMPORTS AllocatorOps, Process, VM, ZCT EXPORTS SweepCollectableStorage = BEGIN OPEN Allocator, AllocatorOps, SafeStorage; <> currentQuantumStart: Allocator.QuantumIndex; <> LPToQuantumIndex: PROC[lp: LONG POINTER] RETURNS[QuantumIndex] = { RETURN[LOOPHOLE[lp, LONG CARDINAL]/wordsPerQuantum]; }; QuantumIndexToLP: PROC[qi: QuantumIndex] RETURNS[LONG POINTER] = { n: LONG CARDINAL _ qi; RETURN[LOOPHOLE[n*wordsPerQuantum, LONG POINTER]]; }; IsExtendedBlock: PROC[hp: HeaderP] RETURNS[BOOL] = { RETURN[LOOPHOLE[hp, NHeaderP].blockSizeIndex = bsiEscape]; }; EnumerateCollectableStorage: PUBLIC PROC [callersInfoProc: SweepCollectableStorage.InfoProc] = { done: BOOL _ FALSE; regionCount: INT _ 0 ; ActuallyDoIt: PROC[] RETURNS [userFinished: BOOL] = { <> <> hp: HeaderP; blockSize: INT _ 0; <> FOR hp _ QuantumIndexToLP[currentQuantumStart], hp + blockSize WHILE LOOPHOLE[hp, LONG CARDINAL] < LastAddress AND quantumMap[LPToQuantumIndex[hp]] DO continue: BOOL; nhp: NHeaderP = LOOPHOLE [ IF IsExtendedBlock[hp] THEN hp + SIZE[ExtendedHeader] - SIZE[NormalHeader] ELSE hp, NHeaderP ]; blockSize _ BlockSize[hp]; continue _ callersInfoProc[type: nhp.type, size: blockSize, object: hp, objectHP: nhp]; IF ~continue THEN RETURN[TRUE]; ENDLOOP; IF LOOPHOLE[hp, LONG CARDINAL] >= LastAddress THEN RETURN[FALSE]; RETURN[FALSE]; }; doSweepOfRegion: PROC RETURNS [endOfMemory: BOOL] = { ENABLE UNWIND => NULL; quantumEnd: Allocator.QuantumIndex; userDone: BOOL; haveAllocatorLocked: PROC = { -- here with the loader and allocator locked haveRCOvLocked: PROC = { <> haveZCTLocked: PROC = { <> userDone _ ActuallyDoIt[]; }; <> <> ZCT.EnterAndCallBack[haveZCTLocked]; }; <> <> ZCT.EnterRCOvAndCallBack[haveRCOvLocked]; }; -- end haveAllocatorLocked <<>> <> <> WHILE ~AllocatorOps.quantumMap[currentQuantumStart] DO IF currentQuantumStart = LAST[QuantumIndex] THEN RETURN[TRUE]; currentQuantumStart _ currentQuantumStart+1; ENDLOOP; quantumEnd _ currentQuantumStart; WHILE AllocatorOps.quantumMap[quantumEnd] AND quantumEnd < LAST[QuantumIndex] DO quantumEnd _ quantumEnd+1; ENDLOOP; VM.SwapIn[interval: [page: currentQuantumStart * Allocator.pagesPerQuantum, count: (quantumEnd - currentQuantumStart ) * Allocator.pagesPerQuantum ]]; <> AllocatorOps.EnterAndCallBack[haveAllocatorLocked ! UNWIND => {}]; currentQuantumStart _ quantumEnd+1; RETURN[ userDone OR quantumEnd >= LAST[QuantumIndex] ]; }; -- end doSweepOfRegion currentQuantumStart _ FIRST[QuantumIndex]; WHILE ~done DO Process.Pause[1]; done _ doSweepOfRegion[]; regionCount _ regionCount + 1 ; ENDLOOP; }; END. <> <> <<>>