DIRECTORY Allocator USING[NHeaderP], Collector USING[], CollectorWatchdog USING [], Process USING[Detach, SetPriority, priorityBackground, GetCurrent], 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 Process, SafeStorage, StorageAccounting, ZCT EXPORTS Collector, CollectorWatchdog, 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; backgroundCollectorProcess: PUBLIC PROCESS _ NIL; -- EXPORT to CollectorWatchdog 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] ELSE IF reason = clientTAndSRequest THEN { WHILE collectorRunning DO WAIT CollectorFinished ENDLOOP; -- await completion 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; StorageAccounting.ResetNWordsAllocated[]; BROADCAST CollectorFinished; BROADCAST TrimZonesFinished; }; BackgroundCollector: PROC = TRUSTED{ backgroundCollectorProcess _ Process.GetCurrent[]; DO BackgroundCollectorInner[]; Process.SetPriority[Process.priorityBackground]; IF currentInfo.reason = clientTAndSRequest AND tAndSProc # NIL THEN tAndSProc[] ELSE { ZCT.StartMarkingDecrements[]; ZCT.ScanTheFrameHeap[]; ZCT.MapReclaimableObjects[NIL]; ZCT.StopMarkingDecrements[]; ZCT.ResetStackBits[]; }; 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, January 18, 1984 9:33:14 am PST Russ Atkinson, May 2, 1984 7:20:26 pm PDT Bob Hagmann, May 10, 1984 3:17:53 pm PDT 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 The next line has been commented out because there is a potential deadlock when you suspend the collector waiting for the collector to finish. suspendMe _ suspendMe OR (collectorRunning AND currentInfo.reason # allocationInterval AND backgroundCollectorProcess # Process.GetCurrent[]); client interface This guy is fired up as a detached process by the start code RRA: do this here to keep priority normally low. CollectorHelperImpl will bump it up if necessary. START HERE ÊL˜šœ™Jšœ@™@Jšœ,™,J™)J™(—J˜šÏk ˜ Jšœ œ ˜Jšœ œ˜Jšœœ˜Jšœœ6˜CJšœ œ5˜Fšœœ˜Jšœj˜j—šœœ˜ Jšœh˜h—J˜—šœœÏc˜1Jšœ(œ˜5Jšœ+˜2Jšœ˜—˜šœœœ˜Jšœ œ˜Jšœ;˜;Jšœœ˜Jšœœ˜Jšœœž˜9Jšœœ˜Jšœœ˜Jšœœ˜Jšœ˜—J˜Jšœœœ˜Jšœœœ˜J˜Jšœ œ˜Jšœ œ˜Jšœ œ˜Jšœ œ˜J˜Jšœœ˜Jšœ!˜!Jšœ ˜ Jšœœ˜#Jšœœ˜!Jšœœœœž˜QJšœ œœ˜J™Jšœ)™)J˜JšÏnœœœœ˜BJ˜šŸœœœ˜#Jšœ œœœ˜:Jšœ)˜/Jšœ˜—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šœ<™<šŸœœœ˜$Jšœ2˜2š˜Jšœ˜šœ0˜0Jšœc™c—šœ)œ ˜>Jšœ ˜šœ˜Jšœ˜Jšœ˜Jšœœ˜Jšœ˜Jšœ˜Jšœ˜——Jšœœ2œ˜PJšœ ˜ —Jšœ˜Jšœ˜—J˜J™Jšœ ™ J˜šœœ˜4J˜——Jšœ˜J˜J˜—…—¨