DIRECTORY Allocator USING[NHeaderP], Collector 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, 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 Copyright c 1985 by Xerox Corporation. All rights reserved. Implementation of the control of the Cedar incremental collector Paul Rovner, January 18, 1984 9:33:14 am PST Russ Atkinson, February 1, 1985 1:12:34 pm PST 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 ΚC˜codešœ™Kšœ Οmœ1™Kšžœžœžœžœ˜7Kšœ˜—K˜š  œžœžœžœžœžœ˜.Kšœžœ˜šœ˜Kšœ>˜>—šœ˜KšœB˜B—Kšœ˜Kšœ)˜)Kšž œ˜Kšž œ˜Kšœ˜—K™Kšœ<™<š œžœžœ˜$Kšœ2˜2šž˜Kšœ˜šœ0˜0Kšœc™c—šžœ)žœ ž˜>Kšžœ ˜šžœ˜Kšžœ˜Kšžœ˜Kšžœžœ˜Kšžœ˜Kšžœ˜Kšœ˜——Kšžœžœ2žœ˜PKšœ ˜ —Kšžœ˜Kšœ˜—K˜K™Kšœ ™ K˜šžœžœ˜4K˜——Kšžœ˜K˜K˜—…—Π±