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.
TV ←
NIL, 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:
BOOL ←
FALSE, thaw:
BOOL ←
FALSE, fullStatus:
BOOL ←
FALSE, 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 BOOL ← ALL[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.
TV ←
NIL] = {
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] ] ];
};
}.