AMProcessImpl.mesa: processes
Copyright © 1985 by Xerox Corporation. All rights reserved.
Andrew Birrell August 2, 1983 12:19 pm
Russ Atkinson, February 12, 1985 12:58:39 pm PST
DIRECTORY
AMBridge USING [ GFHFromTV, SetTVFromLC, TVForFrame, TVToCardinal, GetWorld, IsRemote, RemoteGFHFromTV, RemoteGlobalFrameHandle, TVForRemoteFrame ],
AMEvents 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, AMEvents, AMModel, AMProcessBasic, AMTypes, IO, WorldVM
EXPORTS AMProcess = { OPEN PrincOps;
Context: TYPE = AMModel.Context;
Process: TYPE = AMProcess.Process;
nullProcess: Process = AMProcess.nullProcess;
PSBI: TYPE = PrincOps.PsbIndex;
ROPE: TYPE = Rope.ROPE;
State: TYPE = AMProcess.State;
World: TYPE = WorldVM.World;
PSBIToTV: PUBLIC PROC [world: World, psbi: PsbIndex] RETURNS [p: Process] = {
p ← AMTypes.New[CODE[PROCESS], mutable, world];
AMBridge.SetTVFromLC[p, psbi];
};
TVToPSBI: PUBLIC PROC [p: Process] RETURNS [world: World, psbi: PSBI] = {
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];
};
GetProcesses: PUBLIC ENTRY PROC [context: LIST OF Context ← NIL, states: LIST OF State] RETURNS [l: LIST OF Process] = {
ENABLE UNWIND => NULL;
world: World =
IF context = NIL THEN WorldVM.LocalWorld[] ELSE AMModel.ContextWorld[context.first];
count: CARDINAL = WorldVM.Read[world, LOOPHOLE[@PDA.count, WorldVM.Address]];
filter: GFTable = ContextFrames[context, world];
l ← NIL;
FOR psbi: PSBI DECREASING IN [StartPsb .. StartPsb + count) DO
state: State;
frame: 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;
};
Name: PUBLIC PROC [p: Process] RETURNS [ROPE] = {
RETURN[IO.PutFR["PSB %bB", [cardinal[TVToPSBI[p].psbi]]]]
};
Freeze: PUBLIC PROC [processes: LIST OF Process, context: LIST OF Context ← NIL] = {
FreezeOrAdjust[processes, context, FALSE];
};
Adjust: PUBLIC PROC [processes: LIST OF Process, context: LIST OF Context ← NIL] = {
FreezeOrAdjust[processes, context, TRUE];
};
FreezeOrAdjust: ENTRY PROC [l: LIST OF Process, context: LIST OF Context, thaw: BOOL] = {
world: 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: World;
[pWorld, psbi] ← TVToPSBI[this.first];
IF pWorld = world THEN [] ← PrincOpsInfo[world, psbi, TRUE, thaw, FALSE, filter];
ENDLOOP;
};
Thaw: PUBLIC PROC [l: LIST OF Process] = {
FOR this: LIST OF Process ← l, this.rest UNTIL this = NIL DO
psbi: PSBI;
world: World;
[world, psbi] ← TVToPSBI[this.first];
AMProcessBasic.Thaw[world, psbi];
ENDLOOP;
};
GetState: PUBLIC ENTRY PROC [p: Process] RETURNS [ state: State, faultData: LONG CARDINAL ← 0, priority: [0..7], stack: AMTypes.TVNIL, topFrame: BOOL ] = {
ENABLE UNWIND => NULL;
psbi: PSBI;
world: World;
frozenFrame, current: 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;
};
NotImplemented: ERROR = CODE;
CallDebugger: PUBLIC PROC [p: Process, msg: ROPE] = {
psbi: PSBI;
world: World;
frozenFrame: 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 {
outcome: AMEvents.Outcome ←
AMEvents.ProvokeProcessEvent[p, FrameToTV[world, frozenFrame], msg];
WITH o: outcome SELECT FROM
proceed => NULL;
quit => Abort[p];
retry, returnFrom => ERROR NotImplemented[];
ENDCASE => ERROR;
};
};
LocalOnly: PUBLIC ERROR = CODE;
Abort: PUBLIC PROC [p: Process] = {
psbi: PSBI;
world: World;
[world, psbi] ← TVToPSBI[p];
AMProcessBasic.Abort[world, psbi];
};
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 Context, world: World] RETURNS [filter: GFTable] = {
Add: PROC [gfh: GlobalFrameHandle] = {
IF filter.count = filter.length THEN {
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;
};
filter[filter.count] ← gfh;
filter.count ← filter.count+1;
};
Enum: PROC [child: Context] RETURNS [stop: BOOL] = {
IF AMBridge.IsRemote[child]
THEN {
gfh: AMBridge.RemoteGlobalFrameHandle = AMBridge.RemoteGFHFromTV[child];
Add[LOOPHOLE[gfh.gfh]];
}
ELSE Add[AMBridge.GFHFromTV[child]];
stop ← FALSE;
};
IF context = NIL
THEN filter ← NIL
ELSE {
filter ← gfTable; filter.count ← 0;
FOR this: LIST OF 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;
};
};
PrincOpsInfo: PROC [
world: World, psbi: CARDINAL, freeze: BOOLFALSE, thaw: BOOLFALSE, fullStatus: BOOLFALSE, filter: GFTable ← NIL, states: LIST OF State ← NIL]
RETURNS
[ state: State, faultData: LONG CARDINAL, priority: [0..7], frame: FrameHandle, frozenFrame: FrameHandle, topFrame: FrameHandle] = {
wantedStates: PACKED ARRAY State OF BOOLALL[TRUE];
IF states # NIL THEN {
wantedStates ← ALL[FALSE];
FOR s: LIST OF 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 ];
};
FrameToTV: PROC [world: World, frame: FrameHandle] RETURNS [tv: AMTypes.TVNIL] = {
SELECT TRUE FROM
frame = NIL => {};
world = WorldVM.LocalWorld[] => tv ← AMBridge.TVForFrame[frame];
ENDCASE => tv ← AMBridge.TVForRemoteFrame[ [
world: world,
worldIncarnation: WorldVM.CurrentIncarnation[world],
fh: LOOPHOLE[frame, WorldVM.ShortAddress] ] ];
};
}.