-- 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...