-- Cedar Remote Debugging: processes -- AMProcessImpl.mesa -- Andrew Birrell January 27, 1983 3:42 pm -- Russ Atkinson, January 19, 1983 9:12 pm DIRECTORY AMBridge USING[ GFHFromTV, SetTVFromLC, TVForFrame, TVToCardinal, GetWorld, IsRemote, RemoteGFHFromTV, RemoteGlobalFrameHandle, TVForRemoteFrame ], AMEventsPrivate USING[ Outcome, ProvokeProcessEvent ], AMModel USING[ Context, ContextChildren, ContextClass, ContextWorld ], AMProcess USING[ nullProcess, Process, State ], AMProcessBasic USING[ Abort, GFTable, Info, Thaw ], AMTypes USING[ Error, New, TVType, TypeClass ], Convert USING[ ValueToRope ], Environment USING[ bitsPerWord, wordsPerPage ], PrincOps USING[ FrameHandle, GFTIndex, GlobalFrame ], PSB USING[ PDA, PsbIndex, StartPsb ], Rope USING[ Cat, ROPE ], RTBasic USING[ TV ], Space USING[ Create, Handle, LongPointer, Map, virtualMemory ], SpecialSpace USING[ MakeResident, MakeSwappable ], WorldVM USING[ Address, CopyRead, CurrentIncarnation, LocalWorld, Long, Read, ShortAddress, World ]; AMProcessImpl: MONITOR IMPORTS AMBridge, AMEventsPrivate, AMModel, AMProcessBasic, AMTypes, Convert, Rope, SpecialSpace, Space, WorldVM EXPORTS AMProcess = BEGIN Process: TYPE = AMProcess.Process; nullProcess: Process = AMProcess.nullProcess; PSBI: TYPE = PSB.PsbIndex; PSBIToTV: PUBLIC PROC[world: WorldVM.World, psbi: PSB.PsbIndex] RETURNS[p: Process] = BEGIN p _ AMTypes.New[CODE[PROCESS], mutable, world]; AMBridge.SetTVFromLC[p, psbi]; END; TVToPSBI: PUBLIC PROC[p: Process] RETURNS[world: WorldVM.World, psbi: PSBI] = BEGIN IF AMTypes.TypeClass[AMTypes.TVType[p]] # process THEN ERROR AMTypes.Error[typeFault, "TV should be for a process", AMTypes.TVType[p] ]; psbi _ AMBridge.TVToCardinal[p]; world _ AMBridge.GetWorld[p]; END; GetProcesses: PUBLIC ENTRY PROC[context: LIST OF AMModel.Context _ NIL, states: LIST OF AMProcess.State] RETURNS[l: LIST OF Process] = BEGIN ENABLE UNWIND => NULL; world: WorldVM.World = IF context = NIL THEN WorldVM.LocalWorld[] ELSE AMModel.ContextWorld[context.first]; count: CARDINAL = WorldVM.Read[world, LOOPHOLE[@PSB.PDA.count, WorldVM.Address]]; filter: GFTable = ContextFrames[context, world]; l _ NIL; FOR psbi: PSBI DECREASING IN [PSB.StartPsb .. PSB.StartPsb + count) DO state: AMProcess.State; frame: PrincOps.FrameHandle; [state: state, frame: frame] _ PrincOpsInfo[world, psbi, TRUE, FALSE, TRUE, filter, states]; IF state # dead AND frame # NIL THEN l _ CONS[first: PSBIToTV[world, psbi], rest: l]; ENDLOOP; END; Name: PUBLIC PROC[p: Process] RETURNS[Rope.ROPE] = BEGIN psbi: PSBI; world: WorldVM.World; [world, psbi] _ TVToPSBI[p]; RETURN[Rope.Cat["PSB ", Convert.ValueToRope[[unsigned[psbi, 8]]], "B"]] END; Freeze: PUBLIC PROC[processes: LIST OF Process, context: LIST OF AMModel.Context _ NIL] = { FreezeOrAdjust[processes, context, FALSE] }; Adjust: PUBLIC PROC[processes: LIST OF Process, context: LIST OF AMModel.Context _ NIL] = { FreezeOrAdjust[processes, context, TRUE] }; FreezeOrAdjust: ENTRY PROC[l: LIST OF Process, context: LIST OF AMModel.Context, thaw: BOOL] = BEGIN world: WorldVM.World = IF context = NIL THEN WorldVM.LocalWorld[] ELSE AMModel.ContextWorld[context.first]; filter: GFTable = ContextFrames[context, world]; FOR this: LIST OF Process _ l, this.rest UNTIL this = NIL DO psbi: PSBI; pWorld: WorldVM.World; [pWorld, psbi] _ TVToPSBI[this.first]; IF pWorld = world THEN [] _ PrincOpsInfo[world, psbi, TRUE, thaw, FALSE, filter]; ENDLOOP; END; Thaw: PUBLIC PROC[l: LIST OF Process] = BEGIN FOR this: LIST OF Process _ l, this.rest UNTIL this = NIL DO psbi: PSBI; world: WorldVM.World; [world, psbi] _ TVToPSBI[this.first]; AMProcessBasic.Thaw[world, psbi]; ENDLOOP; END; GetState: PUBLIC ENTRY PROC[p: Process] RETURNS[ state: AMProcess.State, faultData: LONG CARDINAL _ 0, priority: [0..7], stack: RTBasic.TV _ NIL, topFrame: BOOL ] = BEGIN ENABLE UNWIND => NULL; psbi: PSBI; world: WorldVM.World; frozenFrame, current: PrincOps.FrameHandle; [world, psbi] _ TVToPSBI[p]; [state:state, faultData:faultData, priority:priority, frozenFrame:frozenFrame, topFrame:current] _ PrincOpsInfo[world: world, psbi: psbi, fullStatus: TRUE]; topFrame _ frozenFrame = current; IF frozenFrame # NIL THEN stack _ FrameToTV[world, frozenFrame] ELSE stack _ NIL; END; NotImplemented: ERROR = CODE; CallDebugger: PUBLIC PROC[p: Process, msg: Rope.ROPE] = BEGIN psbi: PSBI; world: WorldVM.World; frozenFrame: PrincOps.FrameHandle; [world, psbi] _ TVToPSBI[p]; frozenFrame _ PrincOpsInfo[world: world, psbi: psbi].frozenFrame; IF frozenFrame = NIL THEN frozenFrame _ PrincOpsInfo[world: world, psbi: psbi, freeze: TRUE].frozenFrame; IF frozenFrame # NIL THEN BEGIN outcome: AMEventsPrivate.Outcome _ AMEventsPrivate.ProvokeProcessEvent[p, FrameToTV[world, frozenFrame], msg]; WITH o: outcome SELECT FROM proceed => NULL; quit => Abort[p]; retry, returnFrom => ERROR NotImplemented[]; ENDCASE => ERROR; END; END; LocalOnly: PUBLIC ERROR = CODE; Abort: PUBLIC PROC[p: Process] = BEGIN psbi: PSBI; world: WorldVM.World; [world, psbi] _ TVToPSBI[p]; AMProcessBasic.Abort[world, psbi]; END; -- ReturnFrom: PUBLIC PROC[p: Process, frame: RTBasic.TV, result: RTBasic.TV] = -- Retry: PUBLIC PROC[p: Process, frame: RTBasic.TV, args: RTBasic.TV] = GFI: TYPE = PrincOps.GFTIndex; gfTableSpace: Space.Handle = Space.Create[ size: ((LAST[GFI]-FIRST[GFI]+1+Environment.bitsPerWord-1)/Environment.bitsPerWord + Environment.wordsPerPage-1) / Environment.wordsPerPage, parent: Space.virtualMemory]; GFTable: TYPE = AMProcessBasic.GFTable; gfTable: GFTable = Space.LongPointer[gfTableSpace]; ContextFrames: INTERNAL PROC[context: LIST OF AMModel.Context, world: WorldVM.World] RETURNS[filter: GFTable] = BEGIN Enum: PROC[child: AMModel.Context] RETURNS[stop: BOOL] = BEGIN IF AMBridge.IsRemote[child] THEN BEGIN gfh: AMBridge.RemoteGlobalFrameHandle = AMBridge.RemoteGFHFromTV[child]; gf: PrincOps.GlobalFrame; WorldVM.CopyRead[world: gfh.world, from: WorldVM.Long[gfh.world, LOOPHOLE[gfh.gfh, WorldVM.ShortAddress]], to: @gf, nwords: SIZE[PrincOps.GlobalFrame]]; gfTable[gf.gfi] _ TRUE; END ELSE gfTable[AMBridge.GFHFromTV[child].gfi] _ TRUE; stop _ FALSE; END; IF context = NIL THEN filter _ NIL ELSE BEGIN gfTable^ _ ALL[FALSE]; filter _ gfTable; FOR this: LIST OF AMModel.Context _ context, context.rest UNTIL this = NIL DO IF AMModel.ContextWorld[this.first] = world THEN SELECT AMModel.ContextClass[this.first] FROM world => { filter _ NIL; EXIT }; model => [] _ AMModel.ContextChildren[this.first, Enum]; prog => [] _ Enum[this.first]; ENDCASE => ERROR; ENDLOOP; END; END; PrincOpsInfo: PROC[world: WorldVM.World, psbi: CARDINAL, freeze: BOOL _ FALSE, thaw: BOOL _ FALSE, fullStatus: BOOL _ FALSE, filter: GFTable _ NIL, states: LIST OF AMProcess.State _ NIL] RETURNS[ state: AMProcess.State, faultData: LONG CARDINAL, priority: [0..7], frame: PrincOps.FrameHandle, frozenFrame: PrincOps.FrameHandle, topFrame: PrincOps.FrameHandle] = BEGIN wantedStates: PACKED ARRAY AMProcess.State OF BOOL _ ALL[FALSE]; IF states = NIL THEN wantedStates _ ALL[TRUE] ELSE FOR s: LIST OF AMProcess.State _ states, s.rest UNTIL s = NIL DO wantedStates[s.first] _ TRUE ENDLOOP; IF filter # NIL THEN SpecialSpace.MakeResident[gfTableSpace]; [state, faultData, priority, frame, frozenFrame, topFrame] _ AMProcessBasic.Info[world, psbi, freeze, thaw, fullStatus, filter, wantedStates ! UNWIND => IF filter # NIL THEN SpecialSpace.MakeSwappable[gfTableSpace] ]; IF filter # NIL THEN SpecialSpace.MakeSwappable[gfTableSpace]; END; FrameToTV: PROC[world: WorldVM.World, frame: PrincOps.FrameHandle] RETURNS[RTBasic.TV] = { RETURN[ IF frame = NIL THEN NIL ELSE IF world = WorldVM.LocalWorld[] THEN AMBridge.TVForFrame[frame] ELSE AMBridge.TVForRemoteFrame[ [world: world, worldIncarnation: WorldVM.CurrentIncarnation[world], fh: LOOPHOLE[frame, WorldVM.ShortAddress]] ] ] }; Space.Map[gfTableSpace]; END.