-- PilotUnLoaderImpl.mesa; edited by Sandman on August 28, 1980 2:02 PM
-- edited by Paul Rovner on 23-Sep-81 13:02:30
DIRECTORY
BcdDefs USING [Base, MTIndex],
BcdOps USING [BcdBase, MTHandle, ProcessModules],
Inline USING [BITAND],
PilotLoaderOps USING [
CloseLinkSpace, FreeSpace, GetSpace, OpenLinkSpace, ReadLink, WriteLink, LinkSegmentLength, IthLink],
PilotLoadStateFormat USING [ModuleInfo],
PilotLoadStateOps USING [
AcquireBcd, ConfigIndex, EnterModule, EnumerateBcds, GetMap, GetModule,
InputLoadState, MapRealToConfig, ReleaseBcd, ReleaseLoadState, ReleaseMap,
Map, RemoveConfig],
Mopcodes USING [zFREE],
PrincOps USING [
ControlLink, FrameCodeBase, GFTIndex, GFTNull, GlobalFrameHandle,
NullGlobalFrame, PrefixHandle, TrapLink, UnboundLink],
PrincOpsRuntime USING [EmptyGFTItem, GetFrame, GFT],
Runtime USING [GlobalFrame, UnNew],
RuntimeInternal USING [GetNextGlobalFrame],
Space USING [
Delete, GetAttributes, GetHandle, Handle, PageFromLongPointer, Pointer,
wordsPerPage],
SubSys USING [];
PilotUnLoaderImpl: PROGRAM
IMPORTS
BcdOps, Inline, PilotLoaderOps, PilotLoadStateOps, PrincOpsRuntime, Runtime,
RuntimeInternal, Space
EXPORTS Runtime, SubSys =
BEGIN OPEN PrincOps, RuntimeInternal;
ConfigIndex: TYPE = PilotLoadStateOps.ConfigIndex;
Map: TYPE = PilotLoadStateOps.Map;
BcdBase: TYPE = BcdOps.BcdBase;
GlobalFrameHandle: TYPE = PrincOps.GlobalFrameHandle;
NullGlobalFrame: GlobalFrameHandle = PrincOps.NullGlobalFrame;
Item: TYPE = RECORD [next: List, space: Space.Handle, pages: CARDINAL];
List: TYPE = POINTER TO Item;
fList, cList: List;
UnNewConfig, UnLoad: PUBLIC PROC [link: UNSPECIFIED] =
BEGIN OPEN PilotLoadStateOps;
config: ConfigIndex;
map: Map;
bcd: BcdBase;
frame, f: GlobalFrameHandle;
frame ← LOOPHOLE[Runtime.GlobalFrame[link]];
IF frame.copied THEN
FOR f ← GetNextGlobalFrame[NullGlobalFrame], GetNextGlobalFrame[f] UNTIL f =
NullGlobalFrame DO
IF f # frame AND SameCode[frame, f] AND ~f.copied THEN
BEGIN frame ← f; EXIT END;
ENDLOOP;
[] ← InputLoadState[];
BEGIN
ENABLE UNWIND => ReleaseLoadState[];
[config: config] ← MapRealToConfig[frame.gfi];
bcd ← AcquireBcd[config];
map ← GetMap[config];
CollectSpaces[map];
UnBindConfig[config, bcd, map];
CleanupFrames[map];
RemoveConfig[map, config];
ReleaseMap[map];
ReleaseBcd[bcd];
END; -- ELBANE
ReleaseLoadState[];
RETURN
END;
CollectSpaces: PROC [map: Map] =
BEGIN OPEN PrincOpsRuntime, Space;
frame: GlobalFrameHandle;
i: CARDINAL;
fList ← cList ← NIL;
FOR i IN [1..LENGTH[map]) DO
frame ← GetFrame[GFT[map[i]]];
IF frame = NullGlobalFrame OR GFT[map[i]].epbias # 0 THEN LOOP;
IF LENGTH[map] > 2 THEN
fList ← AddSpaceToList[list: fList, space: FindMappedSpace[frame]];
cList ← AddSpaceToList[
list: cList, space: FindMappedSpace[frame.code.longbase]];
ENDLOOP;
RETURN
END;
FindMappedSpace: PROCEDURE [lp: LONG POINTER] RETURNS [space: Space.Handle] =
BEGIN
mapped: BOOLEAN;
parent: Space.Handle;
space ← Space.GetHandle[Space.PageFromLongPointer[lp]];
DO
[mapped: mapped, parent: parent] ← Space.GetAttributes[space];
IF mapped THEN RETURN[space];
space ← parent;
ENDLOOP;
END;
AddSpaceToList: PROCEDURE [list: List, space: Space.Handle] RETURNS [List] =
BEGIN
l: List;
FOR l ← list, l.next UNTIL l = NIL DO
IF l.space = space THEN RETURN[list]; ENDLOOP;
l ← PilotLoaderOps.GetSpace[SIZE[Item]];
l↑ ← [next: list, space: space, pages: Space.GetAttributes[space].size];
RETURN[l];
END;
SameCode: PROC [f1, f2: GlobalFrameHandle] RETURNS [BOOLEAN] =
BEGIN
fcb1, fcb2: PrincOps.FrameCodeBase;
fcb1 ← f1.code;
fcb2 ← f2.code;
fcb1.out ← fcb2.out ← FALSE;
RETURN[fcb1 = fcb2];
END;
DestroyCopy: PROC [f: GlobalFrameHandle] RETURNS [BOOLEAN] =
BEGIN Runtime.UnNew[LOOPHOLE[f]]; RETURN[FALSE]; END;
Free: PROC [POINTER] = MACHINE CODE BEGIN Mopcodes.zFREE END;
CleanupFrames: PROC [map: Map] =
BEGIN OPEN PrincOpsRuntime, Space;
frame: GlobalFrameHandle;
f, c: List;
i, ep: CARDINAL;
FOR i IN [1..LENGTH[map]) DO
frame ← GetFrame[GFT[map[i]]];
ep ← GFT[map[i]].epbias;
IF frame = NullGlobalFrame OR ep # 0 THEN LOOP;
[] ← EnumerateCopies[frame, DestroyCopy];
IF frame.alloced THEN
BEGIN
Align: PROC [POINTER, WORD] RETURNS [POINTER] = LOOPHOLE[Inline.BITAND];
IF frame.codelinks THEN Free[frame]
ELSE
BEGIN
nlinks: [0..256) ← FindNLinks[frame];
Free[Align[frame - nlinks, 177774B]];
END;
END;
ENDLOOP;
FOR f ← fList, fList UNTIL f = NIL DO
Space.Delete[f.space]; fList ← f.next; PilotLoaderOps.FreeSpace[f]; ENDLOOP;
FOR i IN [1..LENGTH[map]) DO GFT[map[i]] ← EmptyGFTItem ENDLOOP;
FOR frame ← GetNextGlobalFrame[NullGlobalFrame], GetNextGlobalFrame[frame]
UNTIL frame = NullGlobalFrame DO
space: Space.Handle ← FindMappedSpace[frame.code.longbase];
FOR c ← cList, c.next UNTIL c = NIL DO
IF space = c.space THEN {c.pages ← 0; EXIT}; ENDLOOP;
ENDLOOP;
FOR c ← cList, cList UNTIL c = NIL DO
IF c.pages # 0 THEN Space.Delete[c.space];
cList ← c.next;
PilotLoaderOps.FreeSpace[c];
ENDLOOP;
RETURN
END;
FindNLinks: PROC [frame: GlobalFrameHandle] RETURNS [nlinks: CARDINAL] = INLINE
BEGIN
RETURN[LOOPHOLE[frame.code.longbase, LONG PrefixHandle].header.info.nlinks]
END;
NextMultipleOfFour: PROC [n: UNSPECIFIED] RETURNS [UNSPECIFIED] = INLINE {
RETURN[n + Inline.BITAND[-n, 3B]]};
UnBindConfig: PROC [config: ConfigIndex, bcd: BcdBase, map: Map] =
BEGIN OPEN PilotLoadStateOps;
bmap: Map;
UnBind: PROC [c: ConfigIndex] RETURNS [BOOLEAN] =
BEGIN
bindee: BcdBase;
IF c = config THEN RETURN[FALSE];
bindee ← AcquireBcd[c];
IF bindee.nImports # 0 THEN
BEGIN
bmap ← GetMap[c];
[] ← BcdOps.ProcessModules[bindee, AdjustLinks];
ReleaseMap[bmap];
END;
ReleaseBcd[bindee];
RETURN[FALSE]
END;
AdjustLinks: PROC [mth: BcdOps.MTHandle, mti: BcdDefs.MTIndex]
RETURNS [BOOLEAN] =
BEGIN OPEN PrincOpsRuntime;
gfi: PrincOps.GFTIndex = bmap[mth.gfi];
frame: GlobalFrameHandle = GetFrame[GFT[gfi]];
changed: BOOLEAN;
AdjustCopies: PROC [f: GlobalFrameHandle] RETURNS [BOOLEAN] = {
[] ← AdjustFrame[f, mth]; RETURN[FALSE]};
IF frame = NullGlobalFrame OR PilotLoaderOps.LinkSegmentLength[mth, bcd] = 0 THEN RETURN[FALSE];
changed ← AdjustFrame[frame, mth];
IF changed AND frame.shared AND ~frame.codelinks THEN
[] ← EnumerateCopies[frame, AdjustCopies];
IF changed THEN
BEGIN
info: PilotLoadStateFormat.ModuleInfo ← GetModule[gfi];
info.resolved ← FALSE;
EnterModule[rgfi: gfi, module: info];
END;
RETURN[FALSE]
END;
AdjustFrame: PROC [frame: GlobalFrameHandle, mth: BcdOps.MTHandle]
RETURNS [changed: BOOLEAN] =
BEGIN
i: CARDINAL;
link: PrincOps.ControlLink;
changed ← FALSE;
PilotLoaderOps.OpenLinkSpace[frame, mth, bcd];
FOR i IN [0..PilotLoaderOps.LinkSegmentLength[mth, bcd]) DO
link ← PilotLoaderOps.ReadLink[i];
IF BoundHere[link, PilotLoaderOps.IthLink[mth,i, bcd].vtag = var] THEN
BEGIN
link ← IF link.proc OR link.indirect THEN UnboundLink ELSE TrapLink;
PilotLoaderOps.WriteLink[i, link];
changed ← TRUE;
END;
ENDLOOP;
PilotLoaderOps.CloseLinkSpace[frame];
RETURN
END;
BoundHere: PROC [link: ControlLink, var: BOOLEAN] RETURNS [BOOLEAN] =
BEGIN
i: CARDINAL;
gfi: GFTIndex ← GFTNull;
SELECT TRUE FROM
var => {
op: ORDERED POINTER = LOOPHOLE[link];
f: List;
IF LENGTH[map] = 2 THEN RETURN[op IN [frameStart..frameEnd)]
ELSE
FOR f ← fList, f.next UNTIL f = NIL DO
frameStart ← LOOPHOLE[Space.Pointer[f.space]];
frameEnd ← frameStart + Space.wordsPerPage*f.pages;
IF op IN [frameStart..frameEnd) THEN RETURN[TRUE];
ENDLOOP;
RETURN[FALSE]};
link.proc => gfi ← link.gfi;
ENDCASE => RETURN[FALSE];
FOR i IN [1..LENGTH[map]) DO IF map[i] = gfi THEN RETURN[TRUE]; ENDLOOP;
RETURN[FALSE];
END;
frameStart, frameEnd: ORDERED POINTER;
IF bcd.nExports = 0 AND bcd.nModules # 1 THEN RETURN;
frameStart ← LOOPHOLE[PrincOpsRuntime.GetFrame[PrincOpsRuntime.GFT[map[1]]]];
IF bcd.nModules = 1 THEN
BEGIN OPEN BcdDefs;
mth: BcdOps.MTHandle = @LOOPHOLE[bcd + bcd.mtOffset, BcdDefs.Base][
FIRST[BcdDefs.MTIndex]];
frameEnd ← LOOPHOLE[frameStart + mth.framesize]
END;
[] ← EnumerateBcds[recentfirst, UnBind];
RETURN
END;
EnumerateCopies: PROC [
frame: GlobalFrameHandle, proc: PROC [GlobalFrameHandle] RETURNS [BOOLEAN]]
RETURNS [result: GlobalFrameHandle] =
BEGIN
f: GlobalFrameHandle;
IF ~frame.shared THEN RETURN[NullGlobalFrame];
FOR f ← GetNextGlobalFrame[NullGlobalFrame], GetNextGlobalFrame[f] UNTIL f =
NullGlobalFrame DO
IF f # frame AND f.copied AND SameCode[frame, f] AND proc[f] THEN EXIT;
ENDLOOP;
RETURN[f];
END;
END...