<> <> <> <> DIRECTORY DeviceCleanup USING [Item, Linkage, Reason], MPCodes USING [cleaningUp], PrincOps USING [FrameHandle, Port], PrincOpsUtils USING [ GetReturnFrame, GetReturnLink, MyLocalFrame, SetReturnLink], Process USING [InitializeMonitor], ProcessorFace USING [SetMP]; DeviceCleanupImpl: MONITOR IMPORTS PrincOpsUtils, Process, ProcessorFace EXPORTS DeviceCleanup SHARES DeviceCleanup = { linkage: PUBLIC DeviceCleanup.Linkage; InitializeDeviceCleanup: PUBLIC PROC = { reason: DeviceCleanup.Reason; pItem: POINTER TO Item; Process.InitializeMonitor[@LOCK]; -- because our main program is never executed pItemFirst _ NIL; LOOPHOLE[AwaitPerform, PrincOps.Port].dest _ PrincOpsUtils.GetReturnLink[]; linkage.Perform _ LOOPHOLE[@AwaitPerform]; DO linkage.Await _ LOOPHOLE[Install]; reason _ AwaitPerform[]; ProcessorFace.SetMP[MPCodes.cleaningUp]; linkage.Await _ LOOPHOLE[PrincOpsUtils.MyLocalFrame[]]; FOR pItem _ pItemFirst, pItem.pItemNext WHILE pItem ~= NIL DO [] _ pItem.Procedure[reason] -- value should be pItem ENDLOOP ENDLOOP }; AwaitPerform: PORT RETURNS [reason: DeviceCleanup.Reason]; Install: ENTRY PROC [pItem: POINTER TO Item] = { fCaller: PrincOps.FrameHandle = PrincOpsUtils.GetReturnFrame[]; -- cleanup procedure pItem^ _ [pItemNext: pItemFirst, Procedure: LOOPHOLE[fCaller]]; pItemFirst _ pItem; PrincOpsUtils.SetReturnLink[fCaller.returnlink] }; Item: PUBLIC TYPE = RECORD [ pItemNext: POINTER TO Item, Procedure: PROC [DeviceCleanup.Reason] RETURNS [POINTER TO Item] _ NULL]; pItemFirst: POINTER TO Item; -- list of waiting cleanup procedures }.