BasicLoadStateImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Levin on October 3, 1983 1:10 pm
Russ Atkinson, January 31, 1985 11:29:16 am PST
DIRECTORY
BasicLoadState USING [ModuleIndex, NullModule],
BasicLoadStateFormat USING [BcdInfo, ConfigIndex, Extension, LoadState, LoadStateObject, ModuleInfo, nullConfig],
BcdDefs USING [BcdBase, MTHandle],
BootStartList USING [h, IndexToSpaceEntryPointer, IndexToSwapUnitEntryPointer, SpaceEntryPointer, SwapUnitEntryPointer],
DebuggerSwap USING [NoteLoadstate],
PrincOps USING [GFT, GFTIndex, GFTItem, GlobalFrameHandle],
VM USING [AddressForPageNumber, Allocate, Free, Interval, PagesForWords];
BasicLoadStateImpl: PROGRAM
IMPORTS BootStartList, DebuggerSwap, VM
EXPORTS BasicLoadState
= BEGIN OPEN BasicLoadStateFormat;
Types
ConfigID: PUBLIC TYPE = ConfigIndex;
ModuleIndex: TYPE = BasicLoadState.ModuleIndex;
TypeCode: PUBLIC TYPE = CARDINAL;
GFMap: TYPE = LONG POINTER TO ConfigTable;
ConfigTable: TYPE = RECORD[SEQUENCE COMPUTED ConfigID OF ModuleMap];
ModuleMap: TYPE = LONG POINTER TO ModuleMapTable;
ModuleMapTable: TYPE = RECORD [
SEQUENCE length: CARDINAL OF PrincOps.GlobalFrameHandle];
Global Variables
NullConfig: PUBLIC ConfigID ← nullConfig;
loadState: LoadState ← NIL;
extension: LONG POINTER TO Extension ← NIL;
gfMap: GFMap ← NIL;
loadStateInterval, gfMapInterval: VM.Interval;
Errors
BasicLoadStateGone: ERROR = CODE;
BogusConfigID: ERROR = CODE;
BogusModuleIndex: ERROR = CODE;
Exported Procedures
Destroy: PUBLIC PROC = {
IF loadState = NIL THEN RETURN;
loadState.versionident ← 0; -- Make sure that no one trusts the load state
VM.Free[gfMapInterval];
VM.Free[loadStateInterval];
loadState ← NIL;
};
ModuleToGlobalFrame: PUBLIC PROC [config: ConfigID, module: ModuleIndex] RETURNS [gfh: PrincOps.GlobalFrameHandle] = {
moduleMap: ModuleMap;
IF loadState = NIL THEN ERROR BasicLoadStateGone;
IF ~(config IN [ConfigID.FIRST..loadState.nBcds)) THEN ERROR BogusConfigID;
moduleMap ← gfMap[config];
IF module >= moduleMap.length THEN ERROR BogusModuleIndex;
RETURN [moduleMap[module]]
};
GlobalFrameToModule: PUBLIC PROC [gfh: PrincOps.GlobalFrameHandle] RETURNS [config: ConfigID, module: ModuleIndex] = {
info: ModuleInfo;
IF loadState = NIL THEN ERROR BasicLoadStateGone;
info ← loadState.gft[gfh.gfi];
RETURN[config: info.config, module: info.module]
};
GlobalFrameToType: PUBLIC PROC [gfh: PrincOps.GlobalFrameHandle] RETURNS [type: TypeCode] = {
IF loadState = NIL THEN ERROR BasicLoadStateGone;
RETURN[extension[gfh.gfi].type]
};
SetType: PUBLIC PROC [gfh: PrincOps.GlobalFrameHandle, type: TypeCode] = {
IF loadState = NIL THEN ERROR BasicLoadStateGone;
extension[gfh.gfi].type ← type;
};
ConfigInfo: PUBLIC PROC [config: ConfigID] RETURNS [
bcd: BcdDefs.BcdBase, exports, exportsTypes: BOOL] = {
bi: BcdInfo;
IF loadState = NIL THEN ERROR BasicLoadStateGone;
IF ~(config IN [ConfigID.FIRST..loadState.nBcds)) THEN ERROR BogusConfigID;
bi ← loadState.bcds[config];
exports ← bi.exports; exportsTypes ← bi.typeExported;
bi.exports ← bi.typeExported ← FALSE;
bcd ← bi.bcd;
};
EnumerateConfigs: PUBLIC PROC [proc: PROC [ConfigID] RETURNS [BOOL]] RETURNS [config: ConfigID] = {
IF loadState = NIL THEN ERROR BasicLoadStateGone;
FOR config IN [0..loadState.nBcds) DO
IF proc[config] THEN RETURN;
ENDLOOP;
RETURN[nullConfig]
};
EnumerateModulesInConfig: PUBLIC PROC [ config: ConfigID, proc: PROC [ModuleIndex] RETURNS [BOOL]] RETURNS [module: ModuleIndex] = {
moduleMap: ModuleMap;
prev: PrincOps.GlobalFrameHandle ← NIL;
IF loadState = NIL THEN ERROR BasicLoadStateGone;
moduleMap ← gfMap[config];
FOR module IN [1..moduleMap.length) DO
IF moduleMap[module] = prev THEN LOOP;
IF proc[module] THEN RETURN;
prev ← moduleMap[module];
ENDLOOP;
RETURN[BasicLoadState.NullModule]
};
EnumerateAllModules: PUBLIC PROC [proc: PROC [ConfigID, ModuleIndex] RETURNS [BOOL]] RETURNS [config: ConfigID, module: ModuleIndex] = {
IF loadState = NIL THEN ERROR BasicLoadStateGone;
FOR config IN [0..loadState.nBcds) DO
prev: PrincOps.GlobalFrameHandle ← NIL;
moduleMap: ModuleMap = gfMap[config];
FOR module IN [1..moduleMap.length) DO
IF moduleMap[module] = prev THEN LOOP;
IF proc[config, module] THEN RETURN;
prev ← moduleMap[module];
ENDLOOP;
ENDLOOP;
RETURN[NullConfig, BasicLoadState.NullModule]
};
Internal Procedures
ConfigToBcd: PROC [config: ConfigID] RETURNS [BcdDefs.BcdBase] = {
bi: BcdInfo ← loadState.bcds[config];
bi.exports ← bi.typeExported ← FALSE;
RETURN [bi.bcd]
};
FindMakeBootLoadState: PROC = {
OPEN BootStartList;
su: SwapUnitEntryPointer = IndexToSwapUnitEntryPointer[h.initLoadState];
parent: SpaceEntryPointer = IndexToSpaceEntryPointer[su.parent];
loadStateInterval ← [page: parent.vmPage + su.base, count: su.pages];
DebuggerSwap.NoteLoadstate[loadStateInterval.page];
loadState ← VM.AddressForPageNumber[loadStateInterval.page];
extension ← LOOPHOLE[loadState+SIZE[LoadStateObject[loadState.length]]];
};
BuildGFTable: PROC = {
GetFrame: PROC [g: PrincOps.GFTItem] RETURNS [PrincOps.GlobalFrameHandle] = {
g.epbias ← 0;
RETURN[g.framePtr]
};
MapSizeForBcd: PROC [bcd: BcdDefs.BcdBase] RETURNS [CARDINAL] = {
IF bcd.nModules > 1 THEN RETURN[bcd.firstdummy];
Compiler always sets bcd.firstdummy to PrincOps.MaxNGfi+1. The truth is in the module table entry.
RETURN[1+LOOPHOLE[bcd+bcd.mtOffset, BcdDefs.MTHandle].ngfi]
};
gfMapSize, configTableSize: NAT;
moduleMap: ModuleMap;
gfMapSize ← configTableSize ← SIZE[ConfigTable[loadState.nBcds]];
FOR config: ConfigID IN [0..loadState.nBcds) DO
bcd: BcdDefs.BcdBase = ConfigToBcd[config];
gfMapSize ← gfMapSize + SIZE[ModuleMapTable[MapSizeForBcd[bcd]]];
ENDLOOP;
gfMapInterval ← VM.Allocate[VM.PagesForWords[gfMapSize]];
gfMap ← VM.AddressForPageNumber[gfMapInterval.page];
moduleMap ← LOOPHOLE[gfMap + configTableSize];
FOR config: ConfigID IN [0..loadState.nBcds) DO
bcd: BcdDefs.BcdBase = ConfigToBcd[config];
mapSize: CARDINAL = MapSizeForBcd[bcd];
gfMap[config] ← moduleMap;
LOOPHOLE[moduleMap, LONG POINTER TO CARDINAL]^ ← mapSize;
moduleMap[0] ← NIL;
FOR gfi: PrincOps.GFTIndex IN PrincOps.GFTIndex DO
IF loadState.gft[gfi].config = config THEN {
IF loadState.gft[gfi].module >= mapSize THEN ERROR;
moduleMap[loadState.gft[gfi].module] ← GetFrame[PrincOps.GFT[gfi]];
};
ENDLOOP;
moduleMap ← moduleMap + SIZE[ModuleMapTable[mapSize]];
ENDLOOP;
};
FindMakeBootLoadState[];
BuildGFTable[];
END.