Cedar Remote Debugging: processes
AMProcessImpl.mesa
Andrew Birrell August 2, 1983 12:19 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, GFTableObject, Info, Thaw ],
AMTypes USING[ Error, New, TV, TVType, TypeClass ],
IO USING[ PutFR ],
PrincOps USING[ FrameHandle, GlobalFrameHandle, PDA, PsbIndex, StartPsb ],
Rope USING[ ROPE ],
WorldVM USING[ Address, CurrentIncarnation, LocalWorld, Read, ShortAddress, World ];
AMProcessImpl: MONITOR
IMPORTS AMBridge, AMEventsPrivate, AMModel, AMProcessBasic, AMTypes, IO, WorldVM
EXPORTS AMProcess =
BEGIN
Process: TYPE = AMProcess.Process;
nullProcess: Process = AMProcess.nullProcess;
PSBI: TYPE = PrincOps.PsbIndex;
PSBIToTV: PUBLIC PROC[world: WorldVM.World, psbi: PrincOps.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[@PrincOps.PDA.count, WorldVM.Address]];
filter: GFTable = ContextFrames[context, world];
l ← NIL;
FOR psbi: PSBI DECREASING IN [PrincOps.StartPsb .. PrincOps.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[IO.PutFR["PSB %bB", [cardinal[psbi]]]]
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: AMTypes.TVNIL,
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: AMTypes.TV, result: AMTypes.TV] =
Retry: PUBLIC PROC[p: Process, frame: AMTypes.TV, args: AMTypes.TV] =
GFTable: TYPE = AMProcessBasic.GFTable;
gfTable: GFTable ← NEW[AMProcessBasic.GFTableObject[100]];
ContextFrames: INTERNAL PROC[context: LIST OF AMModel.Context, world: WorldVM.World]
RETURNS[filter: GFTable] =
BEGIN
Add: PROC[gfh: PrincOps.GlobalFrameHandle] =
BEGIN
IF filter.count = filter.length
THEN BEGIN
old: GFTable = filter;
filter ← NEW[AMProcessBasic.GFTableObject[filter.length+100]];
FOR i: CARDINAL IN [0..old.count) DO filter[i] ← old[i] ENDLOOP;
filter.count ← old.count;
END;
filter[filter.count] ← gfh;
filter.count ← filter.count+1;
END;
Enum: PROC[child: AMModel.Context] RETURNS[stop: BOOL] =
BEGIN
IF AMBridge.IsRemote[child]
THEN BEGIN
gfh: AMBridge.RemoteGlobalFrameHandle = AMBridge.RemoteGFHFromTV[child];
Add[LOOPHOLE[gfh.gfh]];
END
ELSE Add[AMBridge.GFHFromTV[child]];
stop ← FALSE;
END;
IF context = NIL
THEN filter ← NIL
ELSE BEGIN
filter ← gfTable; filter.count ← 0;
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: BOOLFALSE,
thaw: BOOLFALSE,
fullStatus: BOOLFALSE,
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 BOOLALL[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;
[state, faultData, priority, frame, frozenFrame, topFrame] ←
AMProcessBasic.Info[world, psbi, freeze, thaw, fullStatus, filter, wantedStates ];
END;
FrameToTV: PROC[world: WorldVM.World, frame: PrincOps.FrameHandle] RETURNS[AMTypes.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]] ] ] };
END.