DIRECTORY YggDummyProcess USING[Detach, MsecToTicks, SetTimeout, Ticks], YggEnvironment USING[PageNumber], YggFileMap USING[VerifyFilePageMgrHandle, Handle], YggFilePageMgrLru USING[LruListPlace, SweepItem], YggFilePageMgrPrivateChunk USING[Chunk, ChunkAllocator, ChunkIsDirty, ChunkType, ListChunkType, InternalFilePageMgrLogicError, RefChunk, Sweeper], YggFilePageMgrPrivateFile USING[FPMFileObject, FPMFileHandle], YggInternal; YggFilePageMgrLruImpl: CEDAR MONITOR IMPORTS YggFileMap, YggFilePageMgrPrivateChunk, YggDummyProcess EXPORTS YggInternal, YggFilePageMgrLru = BEGIN FPMFileObject: PUBLIC TYPE = YggFilePageMgrPrivateFile.FPMFileObject; FPMFileHandle: PUBLIC TYPE = YggFilePageMgrPrivateFile.FPMFileHandle; Chunk: PUBLIC TYPE = YggFilePageMgrPrivateChunk.Chunk; RefChunk: PUBLIC TYPE = YggFilePageMgrPrivateChunk.RefChunk; ListChunkType: TYPE = YggFilePageMgrPrivateChunk.ListChunkType; lruList: ARRAY ListChunkType OF RefChunk _ ALL[NIL]; nLruListChunks: ARRAY ListChunkType OF NAT _ ALL[0]; initialLruListChunks: ARRAY ListChunkType OF NAT _ ALL[0]; lruListLimit: NAT; LruListParamsTooSmall: ERROR = CODE; AddAsLru: INTERNAL PROCEDURE[refChunk: RefChunk] = BEGIN -- non system fatal errors: none. chunkType: ListChunkType = refChunk.chunkType; refHeaderChunk: RefChunk = lruList[chunkType]; IF ((refChunk.next # NIL) OR (refChunk.prev # NIL)) THEN ERROR YggFilePageMgrPrivateChunk.InternalFilePageMgrLogicError; nLruListChunks[chunkType] _ nLruListChunks[chunkType] + 1; refHeaderChunk.next.prev _ refChunk; refChunk.next _ refHeaderChunk.next; refChunk.prev _ refHeaderChunk; refHeaderChunk.next _ refChunk; END; AddAsMru: INTERNAL PROCEDURE[refChunk: RefChunk] = BEGIN -- non system fatal errors: none. chunkType: ListChunkType = refChunk.chunkType; refHeaderChunk: RefChunk = lruList[chunkType]; IF ((refChunk.next # NIL) OR (refChunk.prev # NIL)) THEN ERROR YggFilePageMgrPrivateChunk.InternalFilePageMgrLogicError; nLruListChunks[chunkType] _ nLruListChunks[chunkType] + 1; refHeaderChunk.prev.next _ refChunk; refChunk.next _ refHeaderChunk; refChunk.prev _ refHeaderChunk.prev; refHeaderChunk.prev _ refChunk; END; Unlink: INTERNAL PROCEDURE[refChunk: RefChunk] = BEGIN -- non system fatal errors: none. chunkType: ListChunkType = refChunk.chunkType; IF (nLruListChunks[chunkType] _ nLruListChunks[chunkType] - 1) < 0 THEN ERROR YggFilePageMgrPrivateChunk.InternalFilePageMgrLogicError; refChunk.prev.next _ refChunk.next; refChunk.next.prev _ refChunk.prev; refChunk.prev _ NIL; -- for refChunk.next _ NIL; -- debugging. END; UnexpectedHorror: ERROR = CODE; PutMappedChunkOnLruList: PUBLIC ENTRY PROCEDURE[refChunk: RefChunk, lruListPlace: YggFilePageMgrLru.LruListPlace] = BEGIN -- non system fatal errors: none. ErrorProc: PROCEDURE RETURNS[fpmFileHandle: FPMFileHandle] = BEGIN ERROR UnexpectedHorror; END; fPMFileHandle: FPMFileHandle _ YggFileMap.VerifyFilePageMgrHandle[refChunk.fileHandle, ErrorProc]; (IF lruListPlace = mru THEN AddAsMru ELSE AddAsLru)[refChunk]; fPMFileHandle.nLruListChunks _ fPMFileHandle.nLruListChunks + 1; END; PutUnmappedChunkOnLruList: PUBLIC ENTRY PROCEDURE[refChunk: RefChunk] = BEGIN -- non system fatal errors: none. AddAsLru[refChunk]; END; GetOurChunkFromLruList: PUBLIC ENTRY PROCEDURE [refChunk: RefChunk, tellSweeperToHurry: BOOLEAN] = BEGIN -- non system fatal errors: none. ErrorProc: PROCEDURE RETURNS[fpmFileHandle: FPMFileHandle] = BEGIN ERROR UnexpectedHorror; END; fPMFileHandle: FPMFileHandle _ YggFileMap.VerifyFilePageMgrHandle[refChunk.fileHandle, ErrorProc]; Unlink[refChunk]; fPMFileHandle.nLruListChunks _ fPMFileHandle.nLruListChunks - 1; IF tellSweeperToHurry THEN HurryUpSweeper[refChunk.chunkType]; END; NoMoreChunksAvailable: ERROR = CODE; -- all the chunks of a given type are in use when another is requested. GetOtherChunkFromLruList: PUBLIC ENTRY PROCEDURE [chunkType: ListChunkType] RETURNS [mapped: BOOLEAN, refChunk: RefChunk, fileHandle: YggFileMap.Handle, startFilePageNumber: YggEnvironment.PageNumber] = BEGIN -- non system fatal errors: none. IF (refChunk _ lruList[chunkType].next) = lruList[chunkType] THEN ERROR NoMoreChunksAvailable; -- fatal. Unlink[refChunk]; IF (mapped _ (refChunk.fileHandle # NIL)) THEN BEGIN AddAsMru[refChunk]; RETURN[mapped, refChunk, refChunk.fileHandle, refChunk.startFilePageNumber]; END; END; RelinkChunkAsLruOnLruList: PUBLIC ENTRY PROCEDURE[refChunk: RefChunk] = BEGIN -- non system fatal errors: none. Unlink[refChunk]; AddAsLru[refChunk]; END; checkDuringNotDebugging: BOOLEAN _ TRUE; UsingTooMuchOfCache: PUBLIC ENTRY PROCEDURE[fPMFileHandle: FPMFileHandle] RETURNS [yes: BOOLEAN] = BEGIN -- non system fatal errors: none. RETURN[(checkDuringNotDebugging) AND (nLruListChunks[normal] # 0) AND (fPMFileHandle.nLruListChunks > lruListLimit)]; END; CheckCacheInCleanState: PUBLIC ENTRY PROCEDURE RETURNS [clean: BOOLEAN] = BEGIN -- non system fatal errors: none. FOR chunkType: ListChunkType IN ListChunkType DO FOR refChunk: RefChunk _ lruList[chunkType].next, refChunk.next UNTIL refChunk = lruList[chunkType] DO IF refChunk.fileHandle # NIL THEN RETURN[FALSE]; ENDLOOP; IF initialLruListChunks[chunkType] # nLruListChunks[chunkType] THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE]; END; timeToSleepBetweenSweeps: ARRAY ListChunkType OF YggDummyProcess.Ticks _ ALL[YggDummyProcess.MsecToTicks[1000]]; MaxTimeToSleepBetweenSweeps: ARRAY ListChunkType OF YggDummyProcess.Ticks = ALL[YggDummyProcess.MsecToTicks[1000]]; MinTimeToSleepBetweenSweeps: ARRAY ListChunkType OF YggDummyProcess.Ticks = ALL[YggDummyProcess.MsecToTicks[100]]; SweepNeeded: ARRAY ListChunkType OF CONDITION; hurryUp: ARRAY ListChunkType OF BOOLEAN _ ALL[FALSE]; HurryUpSweeper: INTERNAL PROCEDURE[chunkType: ListChunkType] = BEGIN -- non system fatal errors: none. hurryUp[chunkType] _ TRUE; NOTIFY SweepNeeded[chunkType]; END; WaitToSweep: PUBLIC ENTRY PROCEDURE [oldNeedToHurry: BOOLEAN, currentEpoch: NAT, chunkType: ListChunkType] RETURNS[needToHurry: BOOLEAN, sweepList: LIST OF YggFilePageMgrLru.SweepItem] = BEGIN refChunk: RefChunk; timeToSleepBetweenSweeps[chunkType] _ IF oldNeedToHurry THEN MAX[timeToSleepBetweenSweeps[chunkType]/2, MinTimeToSleepBetweenSweeps[chunkType]] ELSE MIN[(timeToSleepBetweenSweeps[chunkType] + timeToSleepBetweenSweeps[chunkType]), MaxTimeToSleepBetweenSweeps[chunkType]]; hurryUp[chunkType] _ FALSE; TRUSTED BEGIN YggDummyProcess.SetTimeout[@SweepNeeded[chunkType], timeToSleepBetweenSweeps[chunkType]]; END; WAIT SweepNeeded[chunkType]; refChunk _ lruList[chunkType].prev; -- mru. sweepList _ NIL; DO IF refChunk = lruList[chunkType] THEN EXIT; IF ((refChunk.fileHandle # NIL) AND (YggFilePageMgrPrivateChunk.ChunkIsDirty[refChunk])) THEN sweepList _ CONS[[refChunk.fileHandle, refChunk.startFilePageNumber], sweepList]; refChunk _ refChunk.prev; ENDLOOP; needToHurry _ hurryUp[chunkType]; END; InitializeLruLists: PUBLIC ENTRY PROCEDURE[nChunks: ARRAY ListChunkType OF NAT] = BEGIN -- non system fatal errors: none. IF moduleInitialized THEN ERROR; FOR chunkType: ListChunkType IN ListChunkType DO IF nChunks[chunkType] = 0 THEN RETURN WITH ERROR LruListParamsTooSmall; lruList[chunkType] _ YggFilePageMgrPrivateChunk.ChunkAllocator[lruHeader, TRUE]; lruList[chunkType].prev _ lruList[chunkType].next _ lruList[chunkType]; THROUGH [0..nChunks[chunkType]) DO AddAsMru[YggFilePageMgrPrivateChunk.ChunkAllocator[chunkType, TRUE]]; ENDLOOP; initialLruListChunks[chunkType] _ nChunks[chunkType]; ENDLOOP; IF ((checkDuringNotDebugging) AND ((lruListLimit _ nLruListChunks[normal]/10) = 0)) THEN RETURN WITH ERROR LruListParamsTooSmall; FOR chunkType: ListChunkType IN ListChunkType DO TRUSTED BEGIN YggDummyProcess.Detach[FORK YggFilePageMgrPrivateChunk.Sweeper[chunkType]]; END; ENDLOOP; moduleInitialized _ TRUE; END; moduleInitialized: BOOLEAN _ FALSE; TRUSTED BEGIN YggDummyProcess.SetTimeout[@SweepNeeded[normal], timeToSleepBetweenSweeps[normal]]; YggDummyProcess.SetTimeout[@SweepNeeded[log], timeToSleepBetweenSweeps[log]]; END; END. Edit Log XYggFilePageMgrLruImpl.mesa Copyright c 1985, 1988 by Xerox Corporation. All rights reserved. Last edited by Kolling on January 24, 1984 12:59:22 pm PST Hauser, March 8, 1985 10:24:00 am PST Bob Hagmann March 23, 1988 12:50:39 pm PST we let system fatal errors keep the monitor locked up. Note, if the chunk is mapped, we can only hint that it's the one to get, and we have to return a lot of stuff because it may change out from under us; we move it to the mru end of the list however; this does no harm and it prevents some conflicts. non system fatal errors: none. module initialization. Κ X˜šœ™Icodešœ Οmœ7™B—šœ™Jšœ+™+K™%K™*—J˜JšΟk ˜ ˜Kšœžœ)˜>Kšœžœ ˜!Kšœ žœ"˜2Kšœžœ˜1Kšœžœr˜’Kšœžœ˜>šœ ˜ J˜J˜——šΟnœžœž˜$Jšžœ8˜?Jšžœ!˜(J˜J˜—Jšžœ˜J˜J˜Jšœžœžœ+˜EJšœžœžœ+˜EJ˜Jšœžœžœ$˜6Jšœ žœžœ'˜J˜@—šžœ˜J˜J˜——šŸœžœžœž œ˜Gšžœ "˜(J˜—Jšžœ˜J˜J˜—šŸœžœžœž œ˜CJšœžœ˜šžœ "˜(šŸ œž œžœ ˜<šžœ˜Jšžœ˜—Jšžœ˜—šœV˜VJ˜ —J˜J˜@Jšžœžœ$˜>Jšžœ˜J˜J˜——Jšœω™ωJ˜Jšœžœžœ G˜mJ˜šŸœžœžœž œ˜KJšžœ žœ4˜LJšœ1˜1šžœ "˜(šžœ:˜Jšžœžœžœ˜——Jšžœ˜Jšžœžœ˜ —Jšžœ˜J˜J˜J˜—šœžœžœ˜HJšžœ$˜'—šœžœžœ˜KJšžœ$˜'—šœžœžœ˜KJšžœ#˜&J˜—šœ žœžœž œ˜.J˜—Jš œ žœžœžœžœžœ˜5J˜šŸœžœž œž˜DJš "˜"Jšœžœ˜Jšžœ˜Jšžœ˜J˜J˜—šŸ œžœžœž œžœžœžœžœ žœžœ ž˜ΐJšœ™J˜šœ&žœ˜7šžœžœ'˜/J˜'—šžœžœ'˜/J˜N——Jšœžœ˜šžœžœ˜JšœZ˜ZJšžœ˜—Jšžœ˜Jšœ% ˜,Jšœ žœ˜šž˜Jšžœžœžœ˜+šžœžœžœ5˜XJšžœ žœA˜V—J˜—Jšžœ˜J˜!šžœ˜J˜J˜J˜——šŸœžœžœž œ žœžœžœž˜WJš "˜"Jšžœžœžœ˜ šžœžœž˜0Jš žœžœžœžœžœ˜GJšœJžœ˜PJ˜Gšžœžœ˜#Jšœ>žœ˜E—Jšžœ˜J˜5—Jšžœ˜šžœžœ,˜MJš œžœžœžœžœ˜3—šžœžœžœ˜1Jšžœžœžœ1žœ˜^—Jšžœ˜Jšœžœ˜Jšžœ˜J˜J˜—Jšœ™J˜Jšœžœžœ˜#J˜J˜J˜šžœžœ˜JšœS˜SJšœM˜MJšžœ˜—J˜Jšžœ˜˜J˜J˜—J˜—…—„+4