DIRECTORY YggDummyFile USING[Error, Handle, RC, Read, Reason, Write], YggDummyProcess USING[Detach], YggFilePageMgrIO USING[IORequest, IOType, Who]; YggFilePageMgrIOImpl: CEDAR MONITOR IMPORTS YggDummyFile, YggDummyProcess EXPORTS YggFilePageMgrIO = BEGIN requests: LIST OF IOMasterRequests _ NIL; nRequests: NAT _ 0; maxRequests: NAT _ 4; IOMasterRequests: TYPE = RECORD[controllingProcess: PROCESS, IOThreadAssigned: BOOLEAN, error: YggDummyFile.RC, errorIORequest: YggFilePageMgrIO.IORequest, nIOsInProgress: NAT, io: YggFilePageMgrIO.IOType, file: YggDummyFile.Handle, list: LIST OF YggFilePageMgrIO.IORequest]; IOControllerAvail: CONDITION; IOThreadFinished: CONDITION; IOThreadNeeded: CONDITION; RegisterRequest: PUBLIC ENTRY PROCEDURE[controllingProcess: PROCESS, io: YggFilePageMgrIO.IOType, file: YggDummyFile.Handle, list: LIST OF YggFilePageMgrIO.IORequest] RETURNS[iORequest: YggFilePageMgrIO.IORequest] = BEGIN -- non system fatal errors: none. DO IF nRequests < maxRequests THEN EXIT; WAIT IOControllerAvail; ENDLOOP; nRequests _ nRequests + 1; requests _ CONS[[controllingProcess: controllingProcess, IOThreadAssigned: FALSE, error: ok, errorIORequest: , nIOsInProgress: 1, io: io, file: file, list: list.rest], requests]; IF list.rest # NIL THEN NOTIFY IOThreadNeeded; RETURN[list.first]; END; RegisterIOThread: ENTRY PROCEDURE RETURNS[workToDo: BOOLEAN, controllingProcess: PROCESS, io: YggFilePageMgrIO.IOType, file: YggDummyFile.Handle, iORequest: YggFilePageMgrIO.IORequest] = BEGIN -- non system fatal errors: none. FOR req: LIST OF IOMasterRequests _ requests, req.rest UNTIL req = NIL DO IF ((NOT req.first.IOThreadAssigned) AND (req.first.list # NIL)) THEN BEGIN workToDo _ TRUE; controllingProcess _ req.first.controllingProcess; io _ req.first.io; file _ req.first.file; iORequest _ req.first.list.first; req.first.list _ req.first.list.rest; req.first.IOThreadAssigned _ TRUE; IF (req.first.nIOsInProgress _ req.first.nIOsInProgress + 1) # 2 THEN ERROR; RETURN; END; ENDLOOP; workToDo _ FALSE; END; GetNext: PUBLIC ENTRY PROCEDURE[controllingProcess: PROCESS, who: YggFilePageMgrIO.Who] RETURNS[error: YggDummyFile.RC, errorIORequest: YggFilePageMgrIO.IORequest, workToDo: BOOLEAN, iORequest: YggFilePageMgrIO.IORequest] = BEGIN -- non system fatal errors: none. prevReq, req: LIST OF IOMasterRequests; [prevReq, req] _ FindReqAndPrev[controllingProcess]; IF (((error _ req.first.error) # ok) OR ((workToDo _ (req.first.list # NIL)) = FALSE)) THEN BEGIN workToDo _ FALSE; [error, errorIORequest] _ FinishUp[controllingProcess, prevReq, req, who]; END ELSE BEGIN iORequest _ req.first.list.first; req.first.list _ req.first.list.rest; END; END; LogError: PUBLIC ENTRY PROCEDURE[controllingProcess: PROCESS, who: YggFilePageMgrIO.Who, why: YggDummyFile.Reason, errorIORequest: YggFilePageMgrIO.IORequest] = BEGIN -- non system fatal errors: none. prevReq, req: LIST OF IOMasterRequests; [prevReq, req] _ FindReqAndPrev[controllingProcess]; req.first.error _ why; req.first.errorIORequest _ errorIORequest; [] _ FinishUp[controllingProcess, prevReq, req, who]; END; FindReqAndPrev: INTERNAL PROCEDURE[controllingProcess: PROCESS] RETURNS[prevReq, req: LIST OF IOMasterRequests] = BEGIN -- non system fatal errors: none. prevReq _ NIL; req _ requests; DO IF req.first.controllingProcess = controllingProcess THEN RETURN; prevReq _ req; IF (req _ req.rest) = NIL THEN ERROR; ENDLOOP; END; FinishUp: INTERNAL PROCEDURE[controllingProcess: PROCESS, prevReq, req: LIST OF IOMasterRequests, who: YggFilePageMgrIO.Who] RETURNS[error: YggDummyFile.RC, errorIORequest: YggFilePageMgrIO.IORequest] = BEGIN -- non system fatal errors: none. req.first.nIOsInProgress _ req.first.nIOsInProgress - 1; IF who = IOThread THEN BEGIN IF req.first.nIOsInProgress = 0 THEN BROADCAST IOThreadFinished; END ELSE BEGIN IF req.first.nIOsInProgress # 0 THEN BEGIN DO WAIT IOThreadFinished; IF req.first.nIOsInProgress = 0 THEN EXIT; ENDLOOP; [prevReq, req] _ FindReqAndPrev[controllingProcess]; END; IF prevReq = NIL THEN requests _ req.rest ELSE prevReq.rest _ req.rest; nRequests _ nRequests - 1; NOTIFY IOControllerAvail; END; error _ req.first.error; errorIORequest _ req.first.errorIORequest; END; IOThread: PROCEDURE = BEGIN -- non system fatal errors: MonitoredIOThread: ENTRY PROCEDURE = BEGIN -- non system fatal errors: none. WAIT IOThreadNeeded; END; DoWork: PROCEDURE = BEGIN -- non system fatal errors: none. workToDo: BOOLEAN; controllingProcess: PROCESS; io: YggFilePageMgrIO.IOType; file: YggDummyFile.Handle; iORequest: YggFilePageMgrIO.IORequest; [workToDo, controllingProcess, io, file, iORequest] _ RegisterIOThread[]; DO IF (NOT workToDo) THEN RETURN; DoIO[io, file, iORequest ! YggDummyFile.Error => BEGIN LogError[controllingProcess, IOThread, why, iORequest]; GOTO errorSeen; END]; [, , workToDo, iORequest] _ GetNext[controllingProcess: controllingProcess, who: IOThread]; REPEAT errorSeen => NULL; ENDLOOP; END; DO MonitoredIOThread[]; DoWork[]; ENDLOOP; END; DoIO: PUBLIC PROCEDURE[io: YggFilePageMgrIO.IOType, file: YggDummyFile.Handle, iORequest: YggFilePageMgrIO.IORequest] = BEGIN -- non system fatal errors: none. tiny: INT _ iORequest.filePageNumber; SELECT io FROM write => BEGIN file.Write[[iORequest.filePageNumber], iORequest.nPages, iORequest.vM]; END; read => TRUSTED BEGIN file.Read[[iORequest.filePageNumber], iORequest.nPages, iORequest.vM]; END; ENDCASE => ERROR; END; GenerateIOThread: PROCEDURE = BEGIN -- non system fatal errors: none. TRUSTED BEGIN YggDummyProcess.Detach[FORK IOThread[]]; END; END; THROUGH [0..maxRequests) DO GenerateIOThread[]; ENDLOOP; END. Edit Log Initial: Kolling: August 25, 1983 3:12 pm: impl module for FilePageManager io. Nodified: Hauser: February 20, 1985 3:05:56 pm PST ÐYggFilePageMgrIOImpl.mesa Copyright c 1985, 1988 by Xerox Corporation. All rights reserved. Last edited by Kolling on January 27, 1984 2:30:52 pm PST MBrown on January 31, 1984 9:02:38 pm PST Bob Hagmann March 23, 1988 11:14:41 am PST debugLog: LIST OF DebugEntries _ NIL; restDebugLog: LIST OF DebugEntries _ NIL; DebugEntries: TYPE = RECORD[proc: {RegReq, RegIOThread, GetNext, FinishUp, IO}, process: PROCESS, who: YggFilePageMgrIO.Who, number: INT, timeOrDeltaTime1, timeOrDeltaTime2, timeOrDeltaTime3: BasicTime.Pulses]; AddToDebugLog[proc: RegReq, process: controllingProcess, who: controller, number: list.first.filePageNumber, timeOrDeltaTime1: BasicTime.GetClockPulses[], timeOrDeltaTime2: 0, timeOrDeltaTime3: 0]; AddToDebugLog: PROCEDURE[proc: {RegReq, RegIOThread, GetNext, FinishUp, IO}, process: PROCESS, who: YggFilePageMgrIO.Who, number: INT, timeOrDeltaTime1, timeOrDeltaTime2, timeOrDeltaTime3: BasicTime.Pulses] = INLINE BEGIN debugLog _ CONS[[proc: proc, process: process, who: who, number: number, timeOrDeltaTime1: BasicTime.PulsesToMicroseconds[timeOrDeltaTime1], timeOrDeltaTime2: BasicTime.PulsesToMicroseconds[timeOrDeltaTime2], timeOrDeltaTime3: BasicTime.PulsesToMicroseconds[timeOrDeltaTime3]], debugLog]; IF restDebugLog = NIL THEN BEGIN restDebugLog _ debugLog; END ELSE BEGIN saveDebugLog: LIST OF DebugEntries _ debugLog.rest; restDebugLog.rest _ debugLog; debugLog.rest _ NIL; debugLog _ saveDebugLog; restDebugLog _ restDebugLog.rest; END; END; AddToDebugLog[proc: RegIOThread, process: controllingProcess, who: IOThread, number: iORequest.filePageNumber, timeOrDeltaTime1: BasicTime.GetClockPulses[], timeOrDeltaTime2: 0, timeOrDeltaTime3: 0]; AddToDebugLog[proc: GetNext, process: controllingProcess, who: who, number: 0, timeOrDeltaTime1: BasicTime.GetClockPulses[], timeOrDeltaTime2: 0, timeOrDeltaTime3: 0]; AddToDebugLog[proc: GetNext, process: controllingProcess, who: who, number: iORequest.filePageNumber, timeOrDeltaTime1: BasicTime.GetClockPulses[], timeOrDeltaTime2: 0, timeOrDeltaTime3: 0]; AddToDebugLog[proc: FinishUp, process: controllingProcess, who: who, number: 0, timeOrDeltaTime1: BasicTime.GetClockPulses[], timeOrDeltaTime2: 0, timeOrDeltaTime3: 0]; AddToDebugLog[proc: FinishUp, process: controllingProcess, who: who, number: 0, timeOrDeltaTime1: BasicTime.GetClockPulses[], timeOrDeltaTime2: 0, timeOrDeltaTime3: 0]; deltaTime1: LONG CARDINAL _ BasicTime.GetClockPulses[]; deltaTime2: LONG CARDINAL; deltaTime2 _ BasicTime.GetClockPulses[]; AddToDebugLog[proc: IO, process: LOOPHOLE[0], who: IOThread, number: LOOPHOLE[tiny], timeOrDeltaTime1: deltaTime1, timeOrDeltaTime2: deltaTime2, timeOrDeltaTime3: deltaTime2 - deltaTime1]; main line code: Hauser, March 7, 1985 3:00:51 pm PST Added copyright. ʼ˜šœ™Icodešœ Ïmœ7™B—šœ™Jšœ*™*Jšœ)™)K™*—J˜JšÏk ˜ ˜Jšœ žœžœ˜;Jšœžœ ˜šœžœ˜/J˜J˜——šÏnœžœž˜#Jšžœ˜%Jšžœ˜J˜J˜—Jšž˜J˜J˜Jšœ žœžœžœ˜)Jšœ žœ˜Jšœ žœ˜J˜š œžœžœžœžœ˜WJšœžœ>žœ˜uJšœ!žœžœ˜EJ˜—Jšœž œ˜Jšœž œ˜Jšœž œ˜J˜Jšœ%™%Jšœ)™)JšœÒ™ÒJ˜š Ÿœžœžœž œžœ˜aJšœ!žœžœžœ)˜ušžœÏc"˜(šžœ˜Jšžœžœžœ˜%Jšžœ˜Jšžœ˜—J˜šœ žœ<žœ˜QJ˜`—Jšžœ žœžœžœ˜.šœI™IJšœ{™{—Jšžœ ˜—šžœ˜J˜——šœU™UJšœ™šœ™šœ8™8šœÜ™ÜJšœ ™ ——šœ™Jšœ'™'šœ>™>Jšœ™Jšœ™Jšœ™Jšœ!™!Jšœ™———šœ™J˜J˜——š Ÿœžœž œžœ žœ˜PJšžœb˜išžœ "˜(š žœžœžœ&žœž˜Iš žœžœžœžœžœžœ˜LJšœ žœ˜Jšœ2˜2J˜J˜J˜!J˜%Jšœžœ˜"Jšžœ?žœžœ˜LJšœÇ™ÇJšžœ˜Jšžœ˜——Jšžœ˜Jšœ žœ˜—šžœ˜J˜J˜——š Ÿœžœžœž œžœ˜WJšžœžœ8žœ ˜iJšœ˜šžœ "˜(Jšœžœžœ˜'Jšœ4˜4šžœ#žœ žœžœ˜Všžœžœ˜ Jšœ žœ˜šœC™CJšœc™c—JšœJ˜JJšž˜—šžœžœ˜ Jšœ!˜!šœC™CJšœz™z—J˜%Jšžœ˜———šžœ˜J˜J˜——š Ÿœžœžœž œžœ!˜]JšœB˜Bšžœ "˜(Jšœžœžœ˜'Jšœ4˜4J˜J˜*Jšœ5˜5—šžœ˜J˜J˜——š Ÿœžœž œžœžœ ˜PJšœžœžœ˜ šžœ "˜(Jšœ žœ˜J˜Jšžœžœ3žœžœ˜DJ˜Jšžœžœžœžœ˜%Jšžœ˜—šžœ˜J˜J˜——š Ÿœžœž œžœžœž˜OJšœ-žœžœ/˜zšžœ "˜(J˜8Jšœ¨™¨šžœ˜Jš žœžœžœžœž œž˜Ošžœž˜ šžœžœž˜+šžœ˜Jšžœ˜Jšžœžœžœ˜*—Jšžœ˜Jšœ4˜4Jšžœ˜—šžœ ž˜Jšžœ˜Jšžœ˜—J˜Jšžœ˜Jšžœ˜——J˜J˜*Jšœ¨™¨—šžœ˜˜J˜———šŸœž œ˜šžœ ˜#šŸœžœž œ˜$šžœ "˜(Jšžœ˜—Jšžœ˜—šŸœž œ˜šžœ !˜'Jšœ žœ˜Jšœžœ˜Jšœ˜Jšœ˜Jšœ&˜&JšœI˜Išž˜Jšžœžœ žœžœ˜˜šœžœ8˜SJšžœ ˜Jšžœ˜——Jšœ[˜[Jšžœžœ˜—Jšžœ˜—Jšžœ˜—šž˜J˜J˜ —Jšžœ˜—Jšžœ˜J˜J˜—šŸœžœž œa˜wšžœ !˜'Jšœ žœžœ™7Jšœ žœžœ™Jšœžœ˜%šžœž˜šœ ž˜JšœG˜GJšžœ˜—šœ ž ˜šœ7˜7Jšœ˜—Jšžœ˜——Jšžœžœ˜J™(Jšœ¼™¼—Jšžœ˜J˜J˜J˜—šŸœž œ˜šžœ !˜'Jšžœžœžœžœ˜;—Jšžœ˜J˜J˜J˜—Jšœ™J˜šžœž˜J˜—šžœ˜J˜J˜J˜—Jšžœ˜˜J˜J˜—J˜NJ˜2J˜J˜™$K™—K™—…—²*>