Cedar Abstract Machine: interactions with client
AMEvents.mesa
Andrew Birrell September 20, 1983 3:25 pm
Paul Rovner July 20, 1983 12:42 am
DIRECTORY
AMModel USING[ Section ],
AMTypes USING[ TV ],
Rope USING[ ROPE ],
WorldVM USING[ Address, World ];
AMEvents: DEFINITIONS =
BEGIN
World: TYPE = WorldVM.World;
EventProc:
TYPE =
PROC[data:
REF
ANY, event: Event]
RETURNS[outcome: Outcome];
"data" is as passed to "GetEvents". An EventProc is called whenever something interesting happens in the client world. Returning from the event allows the client process to proceed, as specified by outcome.type:
quit => raise ABORTED in victim process
proceed => depending on the event.type:
breakpoints => execute saved byte and continue (result=NIL)
explicit call => return from the call (result=NIL)
signals => RESUME[result]
retry => redo the call that caused specified local frame, with given arguments.
returnFrom => return control from specified local frame, with given result.
Event: TYPE = REF EventRec;
Eventuality:
TYPE = {
break, call, signal, unknown };
EventRec:
TYPE =
RECORD[
world: World ← NIL, -- world requesting the debugger
session: INT ← 0, -- monotonic, incremented at StopEvents or when world boots
process: AMTypes.TV ← NIL, -- process requesting the debugger
frame: AMTypes.TV ← NIL, -- local frame requesting the debugger
worry: BOOLEAN ← FALSE, -- TRUE => don't try to call client procedures --
detail:
SELECT type: Eventuality
FROM
break => [id: BreakID, clientData: REF ANY],
call => [msg: Rope.ROPE],
signal => [signal, args: AMTypes.TV ],
unknown => [why: Rope.ROPE], -- client bug; psbi and frame are valid.
ENDCASE];
Outcome:
TYPE =
RECORD[
SELECT type: *
FROM
proceed => [result: AMTypes.TV],
quit => NULL,
retry => [frame, result: AMTypes.TV],
returnFrom => [frame, result: AMTypes.TV],
ENDCASE] ← [proceed[NIL]];
GetEvents: PROC[world: World, data: REF ANY, proc: EventProc];
StopEvents: PROC[world: World];
Debugging: --INFORMATIONAL-- SIGNAL;
Debugged:
--INFORMATIONAL--
SIGNAL;
-- "Debugging" is raised in a process when it is about to be suspended for an event --
-- "Debugged" is raised in a process when the EventProc returns --
NOTE: These are raised as "informational" signals: clients may catch them, but must not
jump out of their catch-phrase. The signaller will resume them.
BootedNotifier:
TYPE =
PROC[world: WorldVM.World, session:
INT, clientData:
REF];
registered "BootedNotifiers" are called at end of a client session. This occurs when StopEvents is called for that world, or when AMEventsImpl notices that the debuggee has been booted. All events for which "session" is <= the given "session" should return (their result will be ignored). At end of session, all outstanding calls of "Apply" for that debuggee are terminated by raising the "EndSession" signal.
RegisterBootedNotifier:
PROC[proc: BootedNotifier, world: WorldVM.World ←
NIL, clientData:
REF ←
NIL];
worldName = NIL causes proc to be called for all booted events
UnRegisterBootedNotifier:
PROC[proc: BootedNotifier, world: WorldVM.World ←
NIL, clientData:
REF ←
NIL];
clientData = NIL implies wildcard match on clientData
ditto for world
WorldSwapLocalSignals:
PROC[
BOOL];
Iff the last call of this procedure has argument "TRUE", signals in the local world
will be sent to the world-swap debugger instead of being reported locally.
CallDebugger:
PROC[msg: Rope.
ROPE];
Cause a local "call" event. If someone is handling local events, this will debug without
a world-swap, otherwise it will world-swap. Note that DebuggerSwap.CallDebugger will
always cause a world-swap.
-- Breakpoints --
Multiple breaks at one place are illegal.
BreakID: TYPE = REF BreakRec;
BreakRec: TYPE;
BreakAt:
PROC[world: World, section: AMModel.Section, clientData:
REF
ANY]
RETURNS[id: BreakID];
Sets breakpoint at beginning of the section (statement or procedure).
BreakAfter:
PROC[world: World, section: AMModel.Section, clientData:
REF
ANY]
RETURNS[id: BreakID];
Sets breakpoint at end of the section (procedure only).
FrameBreak:
PROC[gf: AMTypes.
TV, pc:
CARDINAL, clientData:
REF
ANY]
RETURNS[id: BreakID];
-- OctalBreak(1): Sets breakpoint at specified byte relative to "gf"s codebase --
SetBreak:
PROC[world: World, addr: WorldVM.Address, pc:
CARDINAL, clientData:
REF
ANY]
RETURNS[id: BreakID];
OctalBreak(2): Sets breakpoint at specified byte. "addr" is typically a codebase.
ClearBreak: PROC[id: BreakID];
NextBreak:
PROC[world: World, prev: BreakID]
RETURNS[id: BreakID, clientData:
REF
ANY];
Enumerator for breakpoints. Starts and ends with NIL. Returns the currently set breakpoints in most-recent-first order. If "world" is NIL, returns breakpoint in any world.
-- Procedure invokation --
Apply:
PROC[control, args: AMTypes.
TV]
RETURNS[result: AMTypes.
TV];
"control" may have class "procedure", "signal" or "error", corresponding to procedure calls or raising a signal or error. Error's are treated the same as signals. This may raise BadControlLink, BadArgType, BadResStack or EndSession.
BadControlLink: ERROR; -- "control" had wrong type class
BadArgType: ERROR; -- type of "arg" # range of type of "control"
BadResStack: ERROR; -- result stack size was incorrect.
EndSession: ERROR; -- debuggee was booted (or StopEvents was called) instead of returning.
Kill:
SAFE
PROC[world: World];
Currently, calls TemporaryBooting.BootButton[] in client world.
Screen: SAFE PROC[world: WorldVM.World];
END.