ReadInBootFile.mesa
last edited by Levin on May 26, 1983 4:07 pm
DIRECTORY
BootStartList USING [
EntryPointer, Enumerate, IndexToEntryPointer, IndexToSpaceEntryPointer, Proc, SpaceEntryPointer],
File USING [Handle, PageCount, PageNumber, Read],
Process USING [Detach],
VM USING [Interval, MakeReadOnly, PageNumberToAddress];
ReadInBootFile: MONITOR
IMPORTS BootStartList, File, Process, VM =
BEGIN
maxProcesses: NAT = 2;
processesInUse: NAT ← 0;
processAvailable: CONDITION ← [timeout: 0];
bootFileHandle: File.Handle;
ForkedRead: PROC [from: File.PageNumber, nPages: File.PageCount, to: LONG POINTER] = {
File.Read[file: bootFileHandle, from: from, nPages: nPages, to: to];
NotifyProcessAvailable[];
};
WaitForAProcess: ENTRY PROC = {
WHILE processesInUse = maxProcesses DO WAIT processAvailable ENDLOOP;
processesInUse ← processesInUse + 1;
};
NotifyProcessAvailable: ENTRY PROC = {
processesInUse ← processesInUse - 1;
NOTIFY processAvailable;
};
WaitUntilDone: ENTRY PROC = {
UNTIL processesInUse = 0 DO WAIT processAvailable ENDLOOP;
};
SwapIn: BootStartList.Proc = {
OPEN BootStartList;
entry: EntryPointer = IndexToEntryPointer[index];
WITH e: entry SELECT FROM
space =>
IF ~e.bootLoaded THEN {
WaitForAProcess[];
Process.Detach[FORK ForkedRead[
from: [e.backingPage.LONG],
nPages: e.pages,
to: VM.PageNumberToAddress[e.vmpage.LONG]
]];
};
swapUnit => NULL;
ENDCASE => ERROR;
};
MakeReadOnly: BootStartList.Proc = {
OPEN BootStartList;
entry: EntryPointer = IndexToEntryPointer[index];
WITH e: entry SELECT FROM
swapUnit => {
parent: SpaceEntryPointer = IndexToSpaceEntryPointer[e.parent];
IF ~parent.bootLoaded AND e.info.readOnly THEN
VM.MakeReadOnly[VM.Interval[parent.vmpage.LONG+e.base, e.pages]];
};
space => NULL;
ENDCASE => ERROR;
};
BootStartList.Enumerate[SwapIn];
BootStartList.Enumerate[MakeReadOnly];
WaitUntilDone[];
END.