When an event happens, this method arranges for its handler to be
called. Although traps cannot be raised artificially, interrupts can
(e.g. to notify users of artificial interrupts ``caused by the
kernel'', and not by the hardware). Both from Traps and Irqs
can raise be called to automatically build EventReqs. Whenever
additional information should be delivered along with the trap (e.g.
the faulting address on page faults, etc.) the message should be built
explicitly.
<Other public methods of off_Event. >+= (<-U) [<-D->]
// Artificially raises an instance of this event.
err_t raise(const off_EventReq *e, vm_size_t s);
To raise an event we simply invoke its handler passing as an argument an instance of event being raised.
<off_Event::raise implementation. >= (U->)
// raises an instance for this event.
inline err_t off_Event::raise(const off_EventReq *e, vm_size_t s)
{
ev_count++; // We might loose some event counts :-)
if (!ev_hndlr) // But that's the worse that might happen.
return ENOENT;
else
return (*ev_hndlr)(e,s);
}
This method is also responsible for a per-event counter, ev_count,
maintenance.
<Other private members of off_Event. >+= (<-U) [<-D]
natural_t ev_count; // How many instances up to now.
<Initialize other aggregate members of off_Event. >= (<-U <-U <-U <-U)
ev_count(0)
At any time, the counter can be obtained with get_count.
<Other public methods of off_Event. >+= (<-U) [<-D]
// How many instances so far?
natural_t get_count(void) const;
<off_Event::get_count implementation. >= (U->)
// How many instances so far?
natural_t off_Event::get_count(void) const { return ev_count; }
The event table provides a total count.
<Other public methods of off_EventTbl. >+= (<-U) [<-D]
// How many event instances so far?
virtual natural_t get_count(void) =0;
Trap and interrupt tables implement it by computing the total number of events.
<Other public methods of off_TrapTbl. >+= (<-U) [<-D->]
// How many trap instances so far?
virtual natural_t get_count(void);
<Other public methods of off_IntTbl. >+= (<-U) [<-D->]
// How many interrupt instances so far?
virtual natural_t get_count(void);
<off_TrapTbl::get_count implementation. >= (U->)
// How many trap instances so far?
natural_t off_TrapTbl::get_count(void)
{
natural_t e=0;
for (e=0; e<OFF_MDEP_NTRP_MAX; e++)
e+= ((*this)+e)->get_count();
return e;
}
<off_IntTbl::get_count implementation. >= (U->)
// How many interrupt instances so far?
natural_t off_IntTbl::get_count(void)
{
natural_t e=0;
for (e=0; e<OFF_MDEP_NINT_MAX; e++)
e+= ((*this)+e)->get_count();
return e;
}
The event raise method gets called by calling to raise methods
of concrete events. Initially, there are generic raises for traps
and interrupts. Specific traps or interrupts might redefine raise
to gather event information from machine dependent data.
<Other public methods of off_Trap. >+= (<-U) [<-D]
// raises an instance for this trap.
err_t raise(const err_t e);
For hardware traps, we usually receive the trap error number and deliver a trap event request message with the trap and error numbers.
<off_Trap::raise implementation. >= (U->)
// raises an instance for this trap.
err_t off_Trap::raise(const err_t e)
{
off_TrapReq m(get_id(),e);
return off_Event::raise(&m,sizeof(m));
}
For interrupts we deliver just the interrupt number.
<Other public methods of off_Irq. >+= (<-U) [<-D->]
// raises an instance for this event.
err_t raise(void);
<off_Irq::raiseimplementation. >= (U->) // raises an instance for this event. err_t off_Irq::raise(void) { <Ensurethisinterrupt can be raised. > { off_IrqReq m(get_id()); return off_Event::raise(&m,sizeof(m)); } }
We still have to define both TrapReq and IrqReq.
<Off user-kernel messages. >=
// Event messages, traps and interrupts.
struct off_EventReq : public off_MsgReq {
off_EventReq(const off_id_t &n) : off_MsgReq(n.i_offset) {;}
off_EventReq(off_ex_t e) : off_MsgReq(e) {;}
};
struct off_IrqReq : public off_EventReq {
off_IrqReq(const off_id_t &n) : off_EventReq(n) {;}
off_IrqReq(off_ex_t i) : off_EventReq(i) {;}
};
struct off_TrapReq: public off_EventReq {
err_t t_error;
off_TrapReq(const off_id_t &n, err_t e) : off_EventReq(n), t_error(e) {;}
off_TrapReq(off_ex_t t, err_t e) : off_EventReq(t), t_error(e) {;}
};
Definesoff_EventReq,off_IrqReq,off_TrapReq(links are to index).
There are some ``traps'' defined by Off++ itself and not by the architecture it runs on, some of them have appeared before and some will appear later on.
<Off Virtual traps. >=
// Virtual (Off++ raised) exceptions
enum { OFF_EX_UNUSED=OFF_MDEP_NPTRP_MAX, // Resource no longer
//referenced.
OFF_EX_MISSING, // Resource missing (remote?).
OFF_EX_UNAVAILABLE, // Resource exhaust. Revocation needed.
OFF_EX_RELOC, // Resource has changed its location.
OFF_EX_FROZEN, // Reference to a frozen resource.
OFF_EX_XDT, // Translation to native format needed.
OFF_EX_FWD, // Request should be processed remotely.
OFF_EX_SCERR, // System call failed.
OFF_EX_PUTS, // Mom!, --The kernel cried out loud.
<Other virtual traps. >
};
typedef natural_t off_ex_t;
DefinesOFF_EX_FROZEN,OFF_EX_FWD,OFF_EX_MISSING,OFF_EX_PUTS,OFF_EX_RELOC,OFF_EX_SCERR,off_ex_t,OFF_EX_UNAVAILABLE,OFF_EX_UNUSED,OFF_EX_XDT(links are to index).
<Off Virtual traps dependencies. >= #include <hw/mdep/mEventTbl.h> // for OFF_MDEP_NPTRP_MAX
These virtual traps are defined in prtl/ex.h because they are used
for kernel-user exceptions. We simply include their definition.
<Off event dependencies. >+= (U->) [<-D->] #include <prtl/ex.h> // for off_ex_t and event types.
In any case, the number of virtual traps must not exceed
MDEP_NVTRAP_MAX. The machine dependent trap table implementation
reserves this number of trap entries for fake traps raised by the
kernel.
To implement virtual traps, the trap table only needs to allocate and deallocate them. They are never raised nor handled by the hardware; they are raised by the kernel.
Finally, there are a bunch of methods returning identifiers for virtual and well-known traps (alternatively, the trap table navigator can be used to inspect trap names and identifiers).
<Other public methods of off_TrapTbl. >+= (<-U) [<-D->]
// Returns the id for the first virtual trap
off_ev_id_t get_vtrap0(void) const;
// Returns the id for the page fault trap.
off_ev_id_t get_pgflt(void) const;
<off_TrapTbl::get_vtrap0andget_pgfltimplementation. >= // Returns the id for the first virtual trap off_ev_id_t off_TrapTbl::get_vtrap0(void) const { off_ev_id_t t(get_id(),OFF_MDEP_NPTRP_MAX); return i; } // Returns the id for the page fault trap. off_ev_id_t off_TrapTbl::get_pgflt(void) const { off_ev_id_t t(get_id(),off_mdepTrapTbl::get_pgflt()); return i; }