FileInit.mesa - Files initialisation
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Andrew Birrell November 15, 1983 3:03 pm
Levin, September 20, 1983 4:03 pm
Russ Atkinson, February 20, 1985 3:06:14 pm PST
Bob Hagmann January 31, 1985 11:05:40 am PST
Russ Atkinson (RRA) May 15, 1985 8:30:32 pm PDT
DIRECTORY
BootFile USING [ Location ],
Booting USING [ CheckpointProc, RegisterProcs, RollbackProc ],
BootStartList USING [EntryPointer, Enumerate, IndexToEntryPointer, IndexToSpaceEntryPointer, Proc, SpaceEntryPointer],
DebuggerSwap USING [ CallDebugger, NoteDiskDebugger ],
Disk USING [ Channel, DriveAttributes, GetPageNumber, NextChannel, PageNumber ],
DiskFace USING [ Type ],
File USING [ Error, FindVolumeFromName, FP, Handle, NextVolume, nullFP, Open, PageCount, PageNumber, Read, Volume ],
FileBackdoor USING [ GetRoot],
FileInternal USING [ Commit, GetLogicalLocation, GetPhysicalLocation, LockAndCloseFiles, LockVolume, ReadRootPage, RegisterVMFile, UnlockFiles, VolumeObject ],
GermSwap USING [ bootedFrom, switches ],
MPCodes USING [ fileInitialized ],
PhysicalVolume USING [ GetPhysical, SubVolumeDetails ],
Process USING [Detach],
ProcessorFace USING [ SetMP ],
VM USING [AddressForPageNumber, Interval, MakeReadOnly],
VolumeFormat USING [ nullDiskFileID, RelID ];
FileInit: CEDAR MONITOR
IMPORTS Booting, BootStartList, DebuggerSwap, Disk, File, FileBackdoor, FileInternal, GermSwap, PhysicalVolume, Process, ProcessorFace, VM
EXPORTS DiskFace--RelID--, File = {
Operations on the system volume: finding it, finding debugger, finding VM backing file
Volume: TYPE = REF VolumeObject;
VolumeObject: PUBLIC TYPE = FileInternal.VolumeObject;
FindVolumeFromLocation: PROC [loc: BootFile.Location] RETURNS [File.Volume] = {
First, check there is a suitable device (otherwise, don't touch the volumes).
FOR channel: Disk.Channel ← Disk.NextChannel[NIL], Disk.NextChannel[channel] UNTIL channel = NIL DO
IF Disk.DriveAttributes[channel].type = loc.deviceType THEN EXIT
REPEAT FINISHED => RETURN[NIL]
ENDLOOP;
Then, search for an appropriate logical volume
FOR v: Volume ← File.NextVolume[NIL,FALSE], File.NextVolume[v,FALSE] UNTIL v = NIL DO
FOR sv: LIST OF PhysicalVolume.SubVolumeDetails ← v.subVolumes, sv.rest UNTIL sv = NIL DO
type: DiskFace.Type;
ordinal: CARDINAL;
[type: type, ordinal: ordinal] ← Disk.DriveAttributes[sv.first.channel];
IF type = loc.deviceType AND ordinal = loc.deviceOrdinal THEN {
page: Disk.PageNumber = Disk.GetPageNumber[sv.first.channel, loc.diskFileID.firstLink];
IF page >= sv.first.address AND page < (sv.first.address + sv.first.size)
THEN RETURN[v];
};
ENDLOOP;
ENDLOOP;
RETURN[NIL]
};
systemVolume: Volume ← NIL;
--File.--FindSystemVolume: PUBLIC ENTRY PROC RETURNS [found: BOOL] = {
ENABLE UNWIND => NULL;
IF systemVolume = NIL THEN {
systemVolume ← FindVolumeFromLocation[GermSwap.bootedFrom.location];
Don't use a non-cedar system volume. Temp kludge: in that case, try Cedar
IF systemVolume # NIL AND systemVolume.rootStatus = nonCedarVolume
THEN systemVolume ← File.FindVolumeFromName["Cedar"];
};
FindDebugger[];
RETURN[systemVolume # NIL]
};
--File.--SystemVolume: PUBLIC ENTRY PROC RETURNS [volume: Volume] = {
RETURN[IF systemVolume = NIL OR systemVolume.destroyed THEN NIL ELSE systemVolume];
};
--File.--SetSystemVolume: PUBLIC ENTRY PROC [volume: Volume] = {
systemVolume ← volume;
FindDebugger[ ! UNWIND => NULL];
};
debuggerFound: BOOLFALSE;
FindDebugger: INTERNAL PROC = TRUSTED {
IF systemVolume = NIL OR debuggerFound THEN RETURN;
FOR v: Volume ← File.NextVolume[NIL], File.NextVolume[v] UNTIL v = NIL DO
IF (v.rootStatus = ok OR v.rootStatus = nonCedarVolume)
AND v.root.bootingInfo[debuggee] # VolumeFormat.nullDiskFileID
AND systemVolume # NIL
AND ( SELECT systemVolume.root.type FROM
pilot => v.root.type = pilotDebugger,
pilotDebugger => v.root.type = pilotDebuggerDebugger,
pilotDebuggerDebugger => FALSE,
cedar => IF v.root.type = cedar
THEN ( NOT systemVolume.root.coCedar AND v.root.coCedar)
ELSE v.root.type = pilotDebugger -- change to FALSE after bootstrap to 5.0--,
ENDCASE => FALSE)
THEN {
type: DiskFace.Type;
ordinal: CARDINAL;
[type: type, ordinal: ordinal] ← Disk.DriveAttributes[v.subVolumes.first.channel];
DebuggerSwap.NoteDiskDebugger[
debugger: [type, ordinal, disk[v.root.bootingInfo[debugger]]],
debuggee: [type, ordinal, disk[v.root.bootingInfo[debuggee]]]
];
debuggerFound ← TRUE;
EXIT
};
ENDLOOP;
};
RelocateDebugger: ENTRY PROC = {
Re-consider debugger location after a rollback
debuggerFound ← FALSE;
FindDebugger[ ! UNWIND => NULL];
};
vmFound: BOOLFALSE;
CheckVMFP: PROC [volume: Volume] RETURNS [BOOL] = {
fp: File.FP = FileBackdoor.GetRoot[volume, VM ! File.Error => GOTO noGo ].fp;
file: File.Handle = File.Open[volume, fp ! File.Error => GOTO noGo ];
FileInternal.RegisterVMFile[file];
RETURN[vmFound ← TRUE];
EXITS noGo => RETURN[FALSE]
};
bootFileRead: BOOLFALSE;
--File.--FindVM: PUBLIC ENTRY PROC RETURNS [found: BOOLFALSE] = TRUSTED {
ENABLE UNWIND => NULL;
IF vmFound THEN RETURN[TRUE];
IF systemVolume # NIL THEN {
IF CheckVMFP[systemVolume]
THEN found ← TRUE
ELSE
FOR v: Volume ← File.NextVolume[NIL], File.NextVolume[v] UNTIL v = NIL DO
weAreCoCedar: BOOL = systemVolume.rootStatus = ok AND systemVolume.root.coCedar;
itsCoCedar: BOOL = v.rootStatus = ok AND v.root.coCedar;
IF itsCoCedar = weAreCoCedar AND CheckVMFP[v] THEN {
found ← TRUE;
EXIT };
ENDLOOP;
};
We get here regardless of whether we found a VM file. On first time only, read boot file
IF NOT bootFileRead THEN { bootFileRead ← TRUE; CopyBootFile[]--releases monitor-- };
TRUSTED {IF GermSwap.switches[four] THEN DebuggerSwap.CallDebugger["Key stop 4"L]};
};
CheckpointThings: ENTRY PROC = {
ENABLE UNWIND => NULL;
checkPointExists: BOOL ← systemVolume # NIL;
IF checkPointExists THEN
checkPointExists ← (FileBackdoor.GetRoot[systemVolume, checkpoint
! File.Error => { checkPointExists ← FALSE; CONTINUE }].fp # File.nullFP);
IF checkPointExists
THEN {
bootedLoc: BootFile.Location = GermSwap.bootedFrom.location;
Compiler won't do equality check for me!
Equal: PROC [diskLoc: --disk-- BootFile.Location] RETURNS [BOOL] = TRUSTED {
RETURN[diskLoc.deviceType = bootedLoc.deviceType AND diskLoc.deviceOrdinal = bootedLoc.deviceOrdinal AND diskLoc.diskFileID = bootedLoc.diskFileID];
};
IF Equal[FileInternal.GetLogicalLocation[systemVolume,bootFile]] OR Equal[FileInternal.GetPhysicalLocation[PhysicalVolume.GetPhysical[systemVolume],bootFile]] THEN
GermSwap.switches[r] ← TRUE;
}
ELSE GermSwap.switches[r] ← FALSE;
IF GermSwap.switches[f] THEN GermSwap.switches[r] ← FALSE;
Booting.RegisterProcs[c: MyCheckpoint, r: MyRollback];
};
MyCheckpoint: Booting.CheckpointProc = {
First, try (but not very hard) to ensure our VAM information is written out
FOR volume: File.Volume ← File.NextVolume[NIL,FALSE], File.NextVolume[volume, FALSE] UNTIL volume = NIL DO
FileInternal.Commit[volume ! File.Error => CONTINUE];
ENDLOOP;
Then lock all the files (before the volumes, to avoid deadlocking
FileInternal.LockAndCloseFiles[];
Then lock all the volumes
FOR volume: File.Volume ← File.NextVolume[NIL,FALSE], File.NextVolume[volume, FALSE] UNTIL volume = NIL DO
FileInternal.LockVolume[volume];
ENDLOOP;
};
MyRollback: Booting.RollbackProc = {
Unlock the files first, to allow opening the volume VAM files
FileInternal.UnlockFiles[];
FOR volume: File.Volume ← File.NextVolume[NIL,FALSE], File.NextVolume[volume, FALSE] UNTIL volume = NIL DO
FileInternal.ReadRootPage[volume];
ENDLOOP;
RelocateDebugger[];
};
Copying in the non-initial-loaded part of the boot file
--DiskFace.--RelID: PUBLIC TYPE = VolumeFormat.RelID;
CopyBootFile: INTERNAL PROC = TRUSTED {
maxProcesses: NAT = 2;
processesInUse: NAT ← 0;
processAvailable: CONDITION ← [timeout: 0];
bootFileVolume: File.Volume;
bootFileFP: RelID;
bootFileHandle: File.Handle;
ForkedRead: UNSAFE PROC [from: File.PageNumber, nPages: File.PageCount, to: LONG POINTER] = UNCHECKED {
File.Read[file: bootFileHandle, from: from, nPages: nPages, to: to];
NotifyProcessAvailable[];
};
WaitForAProcess: INTERNAL PROC = CHECKED {
WHILE processesInUse = maxProcesses DO WAIT processAvailable ENDLOOP;
processesInUse ← processesInUse + 1;
};
NotifyProcessAvailable: ENTRY PROC = CHECKED {
ENABLE UNWIND => NULL;
processesInUse ← processesInUse - 1;
NOTIFY processAvailable;
};
WaitUntilDone: INTERNAL PROC = CHECKED {
UNTIL processesInUse = 0 DO WAIT processAvailable ENDLOOP;
};
somethingToDo: BOOLFALSE;
CheckForSwappedOut: BootStartList.Proc--RETURNS [stop: BOOLFALSE]-- = UNCHECKED {
OPEN BootStartList;
entry: EntryPointer = IndexToEntryPointer[index];
WITH e: entry SELECT FROM
space =>
IF ~e.bootLoaded AND e.type.class ~= empty THEN {
somethingToDo ← TRUE; stop ← TRUE;
};
swapUnit => NULL;
ENDCASE => ERROR;
};
SwapIn: INTERNAL BootStartList.Proc = UNCHECKED {
OPEN BootStartList;
entry: EntryPointer = IndexToEntryPointer[index];
WITH e: entry SELECT FROM
space =>
IF ~e.bootLoaded AND e.type.class ~= empty THEN {
WaitForAProcess[];
Process.Detach[FORK ForkedRead[
from: [e.backingPage],
nPages: e.pages,
to: VM.AddressForPageNumber[e.vmPage]
]];
};
swapUnit => NULL;
ENDCASE => ERROR;
};
MakeReadOnly: BootStartList.Proc = UNCHECKED {
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+e.base, e.pages]];
};
space => NULL;
ENDCASE => ERROR;
};
BootStartList.Enumerate[CheckForSwappedOut];
IF somethingToDo THEN {
"bootFileVolume" is logically independent of "SystemVolume[]"
bootFileVolume ← FindVolumeFromLocation[GermSwap.bootedFrom.location];
IF bootFileVolume = NIL THEN RETURN;
bootFileFP ← GermSwap.bootedFrom.location.diskFileID.fID.relID;
bootFileHandle ← File.Open[bootFileVolume, bootFileFP ! File.Error => GOTO noGo];
BootStartList.Enumerate[SwapIn];
WaitUntilDone[]; -- before making them read-only!
BootStartList.Enumerate[MakeReadOnly];
EXITS noGo => NULL
};
};
TRUSTED {
Initialization
IF NOT GermSwap.switches[n] THEN [] ← FindSystemVolume[];
CheckpointThings[];
IF GermSwap.switches[three] THEN DebuggerSwap.CallDebugger["Key stop 3"L];
ProcessorFace.SetMP[MPCodes.fileInitialized];
};
}.
Bob Hagmann January 31, 1985 11:04:48 am PST
Cedar 6.0 conversion
changes to: DIRECTORY