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: BOOLEANFALSE, -- 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: REFNIL];
worldName = NIL causes proc to be called for all booted events
UnRegisterBootedNotifier: PROC[proc: BootedNotifier, world: WorldVM.World ← NIL, clientData: REFNIL];
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.