BasicLoadStateImpl.mesa
last edited by Levin on June 21, 1983 11:40 am
DIRECTORY
BasicLoadState USING [ModuleIndex, NullModule],
BasicLoadStateFormat USING [
BcdInfo, ConfigIndex, LoadState, ModuleInfo, nullConfig],
BcdDefs USING [BcdBase, MTHandle],
BootStartList USING [
h, IndexToSpaceEntryPointer, IndexToSwapUnitEntryPointer, SpaceEntryPointer, SwapUnitEntryPointer],
PrincOps USING [GFT, GFTIndex, GFTItem, GlobalFrameHandle],
VM USING [Allocate, Free, Interval, PageNumberToAddress, WordsToPages];
BasicLoadStateImpl: PROGRAM
IMPORTS BootStartList, VM
EXPORTS BasicLoadState =
BEGIN
OPEN BasicLoadStateFormat;
Types
ConfigID: PUBLIC TYPE = ConfigIndex;
ModuleIndex: TYPE = BasicLoadState.ModuleIndex;
TypeCode: PUBLIC TYPE = CARDINAL;
Extension: 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 ModuleEntry];
ModuleEntry: TYPE = RECORD [
gfh: PrincOps.GlobalFrameHandle,
type: TypeCode];
Global Variables
NullConfig: PUBLIC ConfigID ← BasicLoadStateFormat.nullConfig;
loadState: LoadState ← NIL;
extension: Extension ← NIL;
loadStateInterval, extensionInterval: VM.Interval;
Errors
BasicLoadStateGone: ERROR = CODE;
BogusConfigID: ERROR = CODE;
BogusModuleIndex: ERROR = CODE;
Exported Procedures
Destroy: PUBLIC PROC = {
IF loadState = NIL THEN RETURN;
VM.Free[extensionInterval];
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 ← extension[config];
IF module >= moduleMap.length THEN ERROR BogusModuleIndex;
RETURN [moduleMap[module].gfh]
};
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] = {
info: ModuleInfo;
IF loadState = NIL THEN ERROR BasicLoadStateGone;
info ← loadState.gft[gfh.gfi];
RETURN[extension[info.config]^[info.module].type]
};
SetType: PUBLIC PROC [gfh: PrincOps.GlobalFrameHandle, type: TypeCode] = {
info: ModuleInfo;
IF loadState = NIL THEN ERROR BasicLoadStateGone;
info ← loadState.gft[gfh.gfi];
IF extension[info.config]^[info.module].gfh ~= gfh THEN ERROR;
extension[info.config]^[info.module].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 ← extension[config];
FOR module IN [1..moduleMap.length) DO
IF moduleMap[module].gfh = prev THEN LOOP;
IF proc[module] THEN RETURN;
prev ← moduleMap[module].gfh;
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 = extension[config];
FOR module IN [1..moduleMap.length) DO
IF moduleMap[module].gfh = prev THEN LOOP;
IF proc[config, module] THEN RETURN;
prev ← moduleMap[module].gfh;
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]
};
BuildLoadState: PROC = {
FindLoadState: PROC RETURNS [LoadState] = {
OPEN BootStartList;
su: SwapUnitEntryPointer = IndexToSwapUnitEntryPointer[h.initLoadState];
parent: SpaceEntryPointer = IndexToSpaceEntryPointer[su.parent];
loadStateInterval ← [page: parent.vmPage + su.base, count: su.pages];
RETURN[VM.PageNumberToAddress[loadStateInterval.page]]
};
GetFrame: PROC [g: PrincOps.GFTItem] RETURNS [PrincOps.GlobalFrameHandle] = {
g.epbias ← 0;
RETURN[g.framePtr]
};
MapSize: PROC [bcd: BcdDefs.BcdBase] RETURNS [CARDINAL] = {
IF bcd.nModules > 1 THEN RETURN[bcd.firstdummy];
RETURN[1+LOOPHOLE[bcd+bcd.mtOffset, BcdDefs.MTHandle].ngfi]
};
extensionSize, configTableSize: NAT;
moduleMap: ModuleMap;
loadState ← FindLoadState[];
extensionSize ← configTableSize ← SIZE[ConfigTable[loadState.nBcds]];
FOR config: ConfigID IN [0..loadState.nBcds) DO
bcd: BcdDefs.BcdBase = ConfigToBcd[config];
extensionSize ← extensionSize + SIZE[ModuleMapTable[MapSize[bcd]]];
ENDLOOP;
extensionInterval ← VM.Allocate[VM.WordsToPages[extensionSize]];
extension ← VM.PageNumberToAddress[extensionInterval.page];
moduleMap ← LOOPHOLE[extension + configTableSize];
FOR config: ConfigID IN [0..loadState.nBcds) DO
bcd: BcdDefs.BcdBase = ConfigToBcd[config];
mapSize: CARDINAL = MapSize[bcd];
extension[config] ← moduleMap;
LOOPHOLE[moduleMap, LONG POINTER TO CARDINAL]^ ← mapSize;
moduleMap[0] ← [gfh: NIL, type: 0];
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] ← [
gfh: GetFrame[PrincOps.GFT[gfi]],
type: 0
];
};
ENDLOOP;
moduleMap ← moduleMap + SIZE[ModuleMapTable[mapSize]];
ENDLOOP;
};
BuildLoadState[];
END.