YggFilePageMgrIOImpl.mesa
Copyright © 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
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;
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];
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;
AddToDebugLog[proc: RegReq, process: controllingProcess, who: controller,
number: list.first.filePageNumber, timeOrDeltaTime1: BasicTime.GetClockPulses[], timeOrDeltaTime2: 0, timeOrDeltaTime3: 0];
RETURN[list.first];
END;
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;
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;
AddToDebugLog[proc: RegIOThread, process: controllingProcess, who: IOThread, number: iORequest.filePageNumber, timeOrDeltaTime1: BasicTime.GetClockPulses[], timeOrDeltaTime2: 0, timeOrDeltaTime3: 0];
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;
AddToDebugLog[proc: GetNext, process: controllingProcess, who: who,
number: 0, timeOrDeltaTime1: BasicTime.GetClockPulses[], timeOrDeltaTime2: 0, timeOrDeltaTime3: 0];
[error, errorIORequest] ← FinishUp[controllingProcess, prevReq, req, who];
END
ELSE BEGIN
iORequest ← req.first.list.first;
AddToDebugLog[proc: GetNext, process: controllingProcess, who: who,
number: iORequest.filePageNumber, timeOrDeltaTime1: BasicTime.GetClockPulses[], timeOrDeltaTime2: 0, timeOrDeltaTime3: 0];
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;
AddToDebugLog[proc: FinishUp, process: controllingProcess, who: who, number: 0, timeOrDeltaTime1: BasicTime.GetClockPulses[], timeOrDeltaTime2: 0, timeOrDeltaTime3: 0];
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;
AddToDebugLog[proc: FinishUp, process: controllingProcess, who: who, number: 0, timeOrDeltaTime1: BasicTime.GetClockPulses[], timeOrDeltaTime2: 0, timeOrDeltaTime3: 0];
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.
deltaTime1: LONG CARDINAL ← BasicTime.GetClockPulses[];
deltaTime2: LONG CARDINAL;
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;
deltaTime2 ← BasicTime.GetClockPulses[];
AddToDebugLog[proc: IO, process: LOOPHOLE[0], who: IOThread, number: LOOPHOLE[tiny], timeOrDeltaTime1: deltaTime1, timeOrDeltaTime2: deltaTime2, timeOrDeltaTime3: deltaTime2 - deltaTime1];
END;
GenerateIOThread: PROCEDURE =
BEGIN -- non system fatal errors: none.
TRUSTED BEGIN YggDummyProcess.Detach[FORK IOThread[]]; END;
END;
main line code:
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
Hauser, March 7, 1985 3:00:51 pm PST
Added copyright.