-- LoadState.mesa Last Modified by Sandman on August 1, 1980 10:31 AM -- Copyright Xerox Corporation 1979, 1980 DIRECTORY AltoFileDefs USING [eofDA, FP, NullSN, vDA], BcdOps USING [BcdBase], ControlDefs USING [GFTIndex], LoadStateFormat USING [ AltoVersionID, BcdObject, ConfigIndex, LoadState, ModuleInfo, ModuleTable, NullConfig, NullModule], LoadStateOps USING [EnumerationDirection, Map], MiscDefs USING [Zero], NucleusOps USING [], SDDefs USING [SD, sGFTLength], SegmentDefs: FROM "segmentdefs" USING [ DefaultMDSBase, DeleteFileSegment, FileHint, FileSegmentAddress, FileSegmentHandle, GetFileFP, GetFileSegmentDA, HardUp, InsertFile, MakeSwappedIn, NewFileSegment, Read, SwapUp, Unlock, VMtoFileSegment], Storage USING [Node, Free]; LoadState: PROGRAM IMPORTS MiscDefs, SegmentDefs, Storage EXPORTS LoadStateOps, NucleusOps =PUBLIC BEGIN OPEN ControlDefs, LoadStateOps, LoadStateFormat; FileSegmentHandle: TYPE = SegmentDefs.FileSegmentHandle; state, initstate: FileSegmentHandle; loadstate: LoadState; gft: ModuleTable; dirty: BOOLEAN; LoadStateFull: SIGNAL = CODE; LoadStateInvalid: SIGNAL = CODE; InputLoadState: PROCEDURE RETURNS [ConfigIndex] = BEGIN OPEN SegmentDefs; MakeSwappedIn[seg: state, base: DefaultMDSBase, info: HardUp]; loadstate ← FileSegmentAddress[state]; IF loadstate.versionident # AltoVersionID THEN ERROR LoadStateInvalid[ ! UNWIND => Unlock[state]]; gft ← DESCRIPTOR[@loadstate.gft, SDDefs.SD[SDDefs.sGFTLength]]; RETURN[loadstate.nBcds] END; UpdateLoadState: PROCEDURE [config: ConfigIndex, bcd: BcdOps.BcdBase] = BEGIN OPEN SegmentDefs; bcdseg: FileSegmentHandle ← VMtoFileSegment[bcd]; fp: AltoFileDefs.FP; da: AltoFileDefs.vDA; IF bcd = NIL THEN ERROR LoadStateInvalid; IF config >= LAST[ConfigIndex] THEN ERROR LoadStateFull; da ← WITH s: bcdseg SELECT FROM disk => s.hint.da, ENDCASE => AltoFileDefs.eofDA; GetFileFP[bcdseg.file, @fp]; loadstate.bcds[config] ← [exports: bcd.nExports # 0 OR bcd.nModules = 1, typeExported: bcd.typeExported, pages: bcdseg.pages, body: alto[fp: fp, da: da, base: bcdseg.base]]; IF config >= loadstate.nBcds THEN loadstate.nBcds ← loadstate.nBcds + 1; dirty ← TRUE; END; RemoveConfig: PUBLIC PROCEDURE [map: Map, config: ConfigIndex] = BEGIN i: CARDINAL; FOR i IN [1..LENGTH[gft]) DO IF gft[i].config > config AND gft[i].config # NullConfig THEN gft[i].config ← gft[i].config - 1; ENDLOOP; FOR i IN [1..LENGTH[map]) DO gft[map[i]] ← NullModule; ENDLOOP; FOR i IN [config..loadstate.nBcds) DO loadstate.bcds[i] ← loadstate.bcds[i + 1]; ENDLOOP; dirty ← TRUE; loadstate.nBcds ← loadstate.nBcds - 1; END; ReleaseLoadState: PROCEDURE = BEGIN IF ~state.swappedin THEN RETURN; SegmentDefs.Unlock[state]; state.inuse ← TRUE; IF state.lock = 0 THEN BEGIN IF dirty THEN BEGIN state.write ← TRUE; SegmentDefs.SwapUp[state]; dirty ← state.write ← FALSE; END; loadstate ← NIL; END; END; EnterModule: PROCEDURE [rgfi: GFTIndex, module: ModuleInfo] = BEGIN gft[rgfi] ← module; dirty ← TRUE; END; GetModule: PROCEDURE [rgfi: GFTIndex] RETURNS [module: ModuleInfo] = BEGIN RETURN[gft[rgfi]]; END; MapConfigToReal: PROCEDURE [cgfi: GFTIndex, config: ConfigIndex] RETURNS [rgfi: GFTIndex] = BEGIN IF cgfi = 0 THEN RETURN[0]; FOR rgfi IN [0..LENGTH[gft]) DO IF gft[rgfi].config = config AND gft[rgfi].gfi = cgfi THEN RETURN[rgfi]; ENDLOOP; RETURN[0]; END; MapRealToConfig: PROCEDURE [rgfi: GFTIndex] RETURNS [cgfi: GFTIndex, config: ConfigIndex] = BEGIN RETURN[gft[rgfi].gfi, gft[rgfi].config]; END; GetMap: PROCEDURE [config: ConfigIndex] RETURNS [map: Map] = BEGIN max: CARDINAL ← 0; i: GFTIndex; FOR i IN [0..LENGTH[gft]) DO IF gft[i].config = config THEN max ← MAX[max, gft[i].gfi]; ENDLOOP; map ← DESCRIPTOR[Storage.Node[max + 1], max + 1]; MiscDefs.Zero[BASE[map], max + 1]; FOR i IN [0..LENGTH[gft]) DO IF gft[i].config = config THEN map[gft[i].gfi] ← i; ENDLOOP; END; ReleaseMap: PROCEDURE [map: Map] = BEGIN IF BASE[map] # NIL THEN Storage.Free[BASE[map]]; END; AcquireBcd: PROCEDURE [config: ConfigIndex] RETURNS [bcd: BcdOps.BcdBase] = BEGIN OPEN SegmentDefs; fp: POINTER TO AltoFileDefs.FP; b: POINTER TO alto BcdObject; seg: FileSegmentHandle; WITH object: loadstate.bcds[config] SELECT FROM alto => b ← @object; ENDCASE => ERROR LoadStateInvalid; fp ← IF b.fp.serial = AltoFileDefs.NullSN THEN @state.file.fp ELSE @b.fp; seg ← NewFileSegment[InsertFile[fp, Read], b.base, b.pages, Read]; IF b.da # AltoFileDefs.eofDA THEN WITH s: seg SELECT FROM disk => s.hint ← SegmentDefs.FileHint[b.da, b.base]; ENDCASE; MakeSwappedIn[seg: seg, base: DefaultMDSBase, info: HardUp]; IF b.da = AltoFileDefs.eofDA THEN BEGIN b.da ← GetFileSegmentDA[seg]; dirty ← TRUE END; RETURN[FileSegmentAddress[seg]]; END; ReleaseBcd: PROCEDURE [bcd: BcdOps.BcdBase] = BEGIN OPEN SegmentDefs; seg: FileSegmentHandle ← VMtoFileSegment[bcd]; IF seg = NIL THEN RETURN; Unlock[seg]; IF seg.lock = 0 THEN DeleteFileSegment[seg]; END; EnumerateModules: PROCEDURE [ proc: PROCEDURE [GFTIndex, ModuleInfo] RETURNS [BOOLEAN]] RETURNS [GFTIndex] = BEGIN i: GFTIndex; FOR i IN [0..LENGTH[gft]) DO IF proc[i, gft[i]] THEN RETURN[i]; ENDLOOP; RETURN[0] END; EnumerateBcds: PROCEDURE [ dir: EnumerationDirection, proc: PROCEDURE [ConfigIndex] RETURNS [BOOLEAN]] RETURNS [config: ConfigIndex] = BEGIN SELECT dir FROM recentfirst => FOR config DECREASING IN [0..loadstate.nBcds) DO IF proc[config] THEN RETURN[config]; ENDLOOP; recentlast => FOR config IN [0..loadstate.nBcds) DO IF proc[config] THEN RETURN[config]; ENDLOOP; ENDCASE; RETURN[NullConfig] END; BcdUnresolved: PROCEDURE [bcd: ConfigIndex] RETURNS [BOOLEAN] = BEGIN i: GFTIndex; FOR i IN [0..LENGTH[gft]) DO IF bcd = gft[i].config AND ~gft[i].resolved THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; END; BcdExports: PROCEDURE [bcd: ConfigIndex] RETURNS [BOOLEAN] = BEGIN RETURN[loadstate.bcds[bcd].exports]; END; BcdExportsTypes: PROCEDURE [bcd: ConfigIndex] RETURNS [BOOLEAN] = BEGIN RETURN[loadstate.bcds[bcd].typeExported]; END; GetBcdInfo: PROCEDURE [config: ConfigIndex] RETURNS [fp: POINTER TO AltoFileDefs.FP, base, pages: CARDINAL] = BEGIN WITH b: loadstate.bcds[config] SELECT FROM alto => RETURN[@b.fp, b.base, b.pages]; ENDCASE; RETURN[NIL, 0, 0]; END; SetBcdInfo: PROCEDURE [ config: ConfigIndex, fp: POINTER TO AltoFileDefs.FP, base, pages: CARDINAL] = BEGIN WITH b: loadstate.bcds[config] SELECT FROM alto => BEGIN b.fp ← fp↑; b.base ← base; b.pages ← pages END; ENDCASE; END; END..