DIRECTORY Allocator USING[NHeaderP], Collector USING[Reclaim], Process USING[Detach, SetPriority, priorityBackground], SafeStorage USING[ReclamationReason, NWordsAllocated, TrimSystemZone], StorageAccounting USING[ResetNWordsAllocated, ResetTotalNWordsAllocatedOnly, nObjectsCreated, nObjectsReclaimed, nWordsReclaimed], ZCT USING[ScanTheFrameHeap, MapReclaimableObjects, ResetStackBits, StartMarkingDecrements, StopMarkingDecrements]; CollectorImpl: MONITOR -- protects the collector IMPORTS Collector, Process, SafeStorage, StorageAccounting, ZCT EXPORTS Collector, SafeStorage = BEGIN CollectorInfo: TYPE = RECORD[ incarnation: INT _ 0, reason: SafeStorage.ReclamationReason _ allocationInterval, wordsAllocated: INT _ 0, objectsAllocated: INT _ 0, totalWordsAllocated: INT _ 0, -- when collection started totalObjectsAllocated: INT _ 0, wordsReclaimed: INT _ 0, objectsReclaimed: INT _ 0 ]; collectorRunning: BOOL _ FALSE; trimZonesNeeded: BOOL _ FALSE; CollectorNeeded: CONDITION; CollectionInitiated: CONDITION; CollectorFinished: CONDITION; TrimZonesFinished: CONDITION; collectorIncarnation: INT _ 0; previousInfo: CollectorInfo _ []; currentInfo: CollectorInfo _ []; nObjectsReclaimedAsOfThen: INT _ 0; nWordsReclaimedAsOfThen: INT _ 0; tAndSProc: PROC _ NIL; EstablishTAndSProc: PUBLIC PROC [proc: PROC] = {tAndSProc _ proc}; IsCollectorActive: PUBLIC SAFE PROC RETURNS[active: BOOL, previousIncarnation: INT] = TRUSTED{RETURN[collectorRunning, collectorIncarnation]}; WaitForCollectorStart: PUBLIC ENTRY SAFE PROC RETURNS[ incarnation: INT, reason: SafeStorage.ReclamationReason, wordsAllocated: INT, -- since previous collection was initiated objectsAllocated: INT] = TRUSTED{ UNTIL collectorRunning DO WAIT CollectionInitiated ENDLOOP; RETURN[ incarnation _ currentInfo.incarnation, reason _ currentInfo.reason, wordsAllocated _ currentInfo.wordsAllocated, objectsAllocated _ currentInfo.objectsAllocated ]; }; WaitForCollectorDone: PUBLIC ENTRY SAFE PROC RETURNS[ incarnation: INT, reason: SafeStorage.ReclamationReason, wordsReclaimed: INT, objectsReclaimed: INT] = TRUSTED{ WHILE collectorRunning DO WAIT CollectorFinished ENDLOOP; RETURN[ incarnation _ previousInfo.incarnation, reason _ previousInfo.reason, wordsReclaimed _ previousInfo.wordsReclaimed, objectsReclaimed _ previousInfo.objectsReclaimed ]; }; InternalReclaim: PUBLIC ENTRY PROC [reason: SafeStorage.ReclamationReason, suspendMe: BOOL] = { ENABLE UNWIND => ERROR; IF reason = quantaNeeded THEN trimZonesNeeded _ TRUE; TRUSTED{StorageAccounting.ResetTotalNWordsAllocatedOnly[]}; IF NOT collectorRunning THEN InitiateCollection[reason]; WHILE trimZonesNeeded AND collectorRunning DO WAIT TrimZonesFinished ENDLOOP; WHILE suspendMe AND collectorRunning DO WAIT CollectorFinished ENDLOOP; -- await completion }; ReclaimCollectibleObjects: PUBLIC SAFE PROC [suspendMe: BOOL _ TRUE, traceAndSweep: BOOL] = TRUSTED { InternalReclaim [reason: IF traceAndSweep THEN clientTAndSRequest ELSE clientRequest, suspendMe: suspendMe]; }; InitiateCollection: INTERNAL PROC[reason: SafeStorage.ReclamationReason] = { first: BOOLEAN = (collectorIncarnation = 0); nw: INT = SafeStorage.NWordsAllocated[]; nob: INT = StorageAccounting.nObjectsCreated; currentInfo _ [ incarnation: (collectorIncarnation _ collectorIncarnation + 1), reason: reason, wordsAllocated: (IF first THEN nw ELSE nw - previousInfo.totalWordsAllocated), objectsAllocated: (IF first THEN nob ELSE nob - previousInfo.totalObjectsAllocated), totalWordsAllocated: nw, totalObjectsAllocated: nob ]; nObjectsReclaimedAsOfThen _ StorageAccounting.nObjectsReclaimed; nWordsReclaimedAsOfThen _ StorageAccounting.nWordsReclaimed; collectorRunning _ TRUE; BROADCAST CollectionInitiated; NOTIFY CollectorNeeded; }; BackgroundCollectorInner: ENTRY PROC = {ENABLE UNWIND => NULL; UNTIL collectorRunning DO WAIT CollectorNeeded ENDLOOP; }; FinishBC: ENTRY PROC = {ENABLE UNWIND => NULL; collectorRunning _ FALSE; currentInfo.wordsReclaimed _ StorageAccounting.nWordsReclaimed - nWordsReclaimedAsOfThen; currentInfo.objectsReclaimed _ StorageAccounting.nObjectsReclaimed - nObjectsReclaimedAsOfThen; previousInfo _ currentInfo; BROADCAST CollectorFinished; BROADCAST TrimZonesFinished; }; BackgroundCollector: PROC = TRUSTED{ Process.SetPriority[Process.priorityBackground]; DO BackgroundCollectorInner[]; IF currentInfo.reason = clientTAndSRequest AND tAndSProc # NIL THEN tAndSProc[] ELSE { ZCT.StartMarkingDecrements[]; ZCT.ScanTheFrameHeap[]; ZCT.MapReclaimableObjects[Collector.Reclaim]; ZCT.StopMarkingDecrements[]; ZCT.ResetStackBits[]; }; StorageAccounting.ResetNWordsAllocated[]; IF trimZonesNeeded THEN {SafeStorage.TrimSystemZone[]; trimZonesNeeded _ FALSE}; FinishBC[]; ENDLOOP; }; TRUSTED{Process.Detach[FORK BackgroundCollector[]]}; END. €CollectorImpl.mesa Implementation of the control of the Cedar incremental collector Paul Rovner, December 6, 1983 11:27 am procedures for dealing with the collector obviate decisions to collect while the collector is running, but allow allocator hogs to be suspended during this time client interface This guy is fired up as a detached process by the start code START HERE Ê‹˜Jšœ™Jšœ@™@Jšœ&™&J˜šÏk ˜ Jšœ œ ˜Jšœ œ ˜Jšœœ*˜7Jšœ œ5˜FJšœœk˜‚Jšœœi˜rJ˜—JšœœÏc˜1Jšœ3œ˜@Jšœ˜J˜Jšœ˜˜šœœœ˜Jšœ œ˜Jšœ;˜;Jšœœ˜Jšœœ˜Jšœœž˜9Jšœœ˜Jšœœ˜Jšœœ˜Jšœ˜—J˜Jšœœœ˜Jšœœœ˜J˜Jšœ œ˜Jšœ œ˜Jšœ œ˜Jšœ œ˜J˜Jšœœ˜Jšœ!˜!Jšœ ˜ Jšœœ˜#Jšœœ˜!J™Jšœ œœ˜J™Jšœ)™)J˜JšÏnœœœœ˜BJ˜š Ÿœœ œœ œœ˜UJšœœ*˜8—J˜šŸœœœ ˜-šœ˜Jšœ œ˜Jšœ&˜&Jšœœž*˜@Jšœœ˜šœ˜Jšœœœœ˜;šœ˜Jšœ&˜&Jšœ˜Jšœ,˜,Jšœ/˜/Jšœ˜——Jšœ˜——J˜šŸœœœ ˜,šœ˜Jšœ œ˜Jšœ&˜&Jšœœ˜Jšœœ˜šœ˜Jšœœœœ˜9šœ˜Jšœ'˜'Jšœ˜Jšœ-˜-Jšœ0˜0Jšœ˜——Jšœ˜——J˜šŸœœœ˜"Jšœ3œ˜Jšœœœœ˜7Jšœ˜—J˜š Ÿœœœœœœ˜.Jšœœ˜šœ˜Jšœ>˜>—šœ˜JšœB˜B—Jšœ˜Jš œ˜Jš œ˜Jšœ˜—J™Jšœ<™<šŸœœœ˜$Jšœ0˜0š˜Jšœ˜šœ)œ ˜>Jšœ ˜šœ˜Jšœ˜Jšœ˜Jšœ*˜-Jšœ˜Jšœ˜Jšœ˜——Jšœ)˜)Jšœœ2œ˜PJšœ ˜ —Jšœ˜Jšœ˜—J˜J™Jšœ ™ J˜šœœ˜4J˜——Jšœ˜J˜J˜—…—ÄÏ