-- file: LaurelSegments.mesa
-- edited by Levin, January 27, 1981 11:57 AM
-- edited by Brotz, September 18, 1980 11:57 AM
DIRECTORY
AltoDefs: FROM "AltoDefs",
AltoFileDefs: FROM "AltoFileDefs",
crD: FROM "CoreDefs",
exD: FROM "ExceptionDefs",
lsD: FROM "LaurelStateDefs",
SegmentDefs: FROM "SegmentDefs";
LaurelSegments: PROGRAM
IMPORTS crD, exD, lsD, SegmentDefs
EXPORTS lsD
SHARES lsD =
BEGIN
OPEN lsD;
-- Exported procedures for clients --
DefineStateSegment: PUBLIC PROCEDURE [nPages: PageCount]
RETURNS [seg: StateSegment] =
BEGIN
OPEN SegmentDefs;
IF ~beforeInstallation THEN exD.SysBug[];
seg ← AllocateStateNode[SIZE[StateSegmentObject]];
seg↑ ←
[pages: nPages,
link: NIL,
body: inCore[fsh: NewFileSegment[stateFile, stateFF, nPages, Read+Write]]];
IF segmentListHead = NIL THEN segmentListHead ← seg
ELSE segmentListTail.link ← seg;
segmentListTail ← seg;
stateFF ← stateFF + nPages;
SetEndOfFile[stateFile, stateFF-1, AltoDefs.BytesPerPage];
END; -- of DefineStateSegment --
SwapInStateSegment: PUBLIC PROCEDURE[segment: StateSegment]
RETURNS [POINTER] =
BEGIN
OPEN SegmentDefs;
MakeSwappedIn[segment.fsh, DefaultBase, HardDown];
RETURN[FileSegmentAddress[segment.fsh]]
END; -- of SwapInStateSegment --
StateSegmentAddress: PUBLIC PROCEDURE[segment: StateSegment]
RETURNS [POINTER] =
BEGIN
IF segment.fsh.lock = 0 THEN exD.SysBug[];
RETURN[SegmentDefs.FileSegmentAddress[segment.fsh]]
END; -- of StateSegmentAddress --
WriteStateSegment: PUBLIC PROCEDURE [segment: StateSegment] =
BEGIN
segment.fsh.write ← TRUE;
SegmentDefs.SwapUp[segment.fsh];
END; -- of WriteStateSegment --
ReleaseStateSegment: PUBLIC PROCEDURE [segment: StateSegment] =
BEGIN
SegmentDefs.Unlock[segment.fsh];
END; -- of ReleaseStateSegment --
-- Exported procedures private to the implementation --
segmentListHead, segmentListTail: StateSegment ← NIL;
InstallSegments: PUBLIC PROCEDURE [header: POINTER TO StateHeader] =
BEGIN
-- this uses an n↑2 algorithm to discover the disk hints, but we don’t care
-- how long installation takes.
seg: StateSegment;
fsh: SegmentDefs.FileSegmentHandle;
IF (header.segmentList ← segmentListHead) = NIL THEN RETURN;
header.firstSegmentPage ← segmentListHead.fsh.base;
FOR seg ← segmentListHead, seg.link UNTIL seg = NIL DO
OPEN SegmentDefs;
fsh ← seg.fsh;
SwapIn[fsh];
seg.hint ← GetFileSegmentDA[fsh];
Unlock[fsh];
DeleteFileSegment[fsh];
ENDLOOP;
END; -- of InstallSegments --
InitializeSegments: PUBLIC PROCEDURE [header: POINTER TO StateHeader] =
BEGIN
OPEN SegmentDefs;
seg: StateSegment;
fsh: FileSegmentHandle;
base: PageNumber ← header.firstSegmentPage;
IF beforeInstallation THEN beforeInstallation ← FALSE
ELSE exD.SysBug[];
FOR seg ← header.segmentList, seg.link UNTIL seg = NIL DO
fsh ← NewFileSegment[stateFile, base, seg.pages, Read];
SetFileSegmentDA[fsh, seg.hint];
seg.fsh ← fsh;
base ← base + seg.pages;
ENDLOOP;
END; -- of InitializeSegments --
-- Main program (executed by start trap) --
stateFF: PageNumber;
stateFile: PUBLIC SegmentDefs.FileHandle;
beforeInstallation: BOOLEAN ← TRUE;
Initialize: PROCEDURE =
BEGIN
byte: CARDINAL;
IF (stateFile ← crD.LookupInFileCache["Laurel.state"L]) = NIL THEN exD.SysBug[];
SegmentDefs.LockFile[stateFile];
SegmentDefs.SetFileAccess[stateFile, SegmentDefs.ReadWriteAppend];
[stateFF, byte] ← SegmentDefs.GetEndOfFile[stateFile];
IF byte ~= AltoDefs.BytesPerPage THEN exD.SysBug[]
ELSE stateFF ← stateFF + 1;
END; -- of Initialize --
Initialize[];
END.