-- Cedar Abstract Machine: interactions with client -- AMEvents.mesa -- Andrew Birrell November 1, 1982 8:58 am DIRECTORY AMModel USING[ Section ], Rope USING[ ROPE ], RTBasic USING[ TV ], 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] -- interrupt => continue (result=NIL) -- retry => redo the call that caused specified local frame, with given arguments. -- returnFrom => return control from specified local frame, with given result. -- -- If the client world is not the local world, the client world -- is frozen when the EventProc is called. -- If the client world is booted, the event proc is called with -- event.type = booted. When this happens, the debugger should -- return from all previous events for this client (these returns -- will have no effect on the client), and from the -- "booted" event; the debugger should also arrange to flush -- any cached client state. Outstanding calls to the client will -- get the "Booted" error. Events that happen after the client has been -- booted are delayed until previous events have returned. Event: TYPE = REF EventRec; Eventuality: TYPE = { booted, break, call, signal, interrupt, unknown }; EventRec: TYPE = RECORD[ world: World, -- world requesting the debugger process: RTBasic.TV, -- process requesting the debugger (compatible with AMProcess.Process) frame: RTBasic.TV, -- local frame requesting the debugger worry: BOOLEAN, -- TRUE => don't try to call client procedures -- detail: SELECT type: Eventuality FROM booted => NULL, -- see comment under "EventProc". break => [id: BreakID, clientData: REF ANY], call => [msg: Rope.ROPE], signal => [signal, args: RTBasic.TV ], interrupt => NULL, unknown => [why: Rope.ROPE], -- client bug; psbi and frame are valid. ENDCASE]; Outcome: TYPE = RECORD[ SELECT type: * FROM proceed => [result: RTBasic.TV], quit => NULL, retry => [frame, result: RTBasic.TV], returnFrom => [frame, result: RTBasic.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. 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 Pilot's Runtime.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: RTBasic.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]; -- Procedure invokation -- Apply: PROC[control, args: RTBasic.TV] RETURNS[result: RTBasic.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 Booted. BadControlLink: ERROR; -- "control" had wrong type class BadArgType: ERROR; -- type of "arg" # range of type of "control" BadResStack: ERROR; -- result stack size was incorrect. Booted: ERROR; -- client was booted instead of returning. Kill: PROC[world: World]; -- Currently, calls TemporaryBooting.BootButton[] in client world. END.