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];
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];
NullConfig: PUBLIC ConfigID ← nullConfig;
loadState: LoadState ← NIL;
extension: LONG POINTER TO Extension ← NIL;
gfMap: GFMap ← NIL;
loadStateInterval, gfMapInterval: VM.Interval;
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]
};
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;
};