An event allocator is a subclass a TBmAllocator. It is not subject
to revocation. Actually we have two kinds of event allocators, which
can be instantiated to allocate traps and interrupts. The number of
traps and the number of interrupts is a machine dependent constant.
Each allocator maintains an indexer and also an array where allocated resources are kept.
<Off trap allocator. >= (U->)
// A trap allocator.
//
class off_TrapAllocator : public off_TBmAllocator<off_Trap> {
private:
static off_Indexer<off_Trap> t_idx;
off_Trap t_traps[OFF_MDEP_NTRP_MAX];
public:
// Creates a trap allocator.
off_TrapAllocator(off_Exhausted *r) :
off_TBmAllocator<off_Trap>(r,(const off_Indexable *)&t_idx,
&t_traps[0],OFF_MDEP_NTRP_MAX )
{ do_debug(putchar('t')); }
<Other public methods of off_TrapAllocator. >
};
Definesoff_TrapAllocator(links are to index).
<Off event allocator dependencies. >= (U->) [D->] #include <flux/debug.h> // for do_debug
<Off trap allocator static members. >= (U->) off_Indexer<off_Trap> off_TrapAllocator::t_idx;
<Off interrupt allocator. >= (U->)
// An interrupt allocator.
//
class off_IntAllocator : public off_TBmAllocator<off_Irq> {
static off_Indexer<off_Irq> i_idx;
off_Irq i_irqs[OFF_MDEP_NINT_MAX];
public:
// Creates an interrupt allocator.
off_IntAllocator(off_Exhausted *r) :
off_TBmAllocator<off_Irq>(r,(const off_Indexable *)&i_idx,
&i_irqs[0],OFF_MDEP_NINT_MAX)
{ do_debug(putchar('i')); }
<Other public methods of off_IntAllocator. >
};
Definesoff_IntAllocator(links are to index).
<Off interrupt allocator static members. >= (U->) off_Indexer<off_Irq> off_IntAllocator::i_idx;
<Off event allocator dependencies. >+= (U->) [<-D]
#include <klib/BmAllocator.h> // for off_TBmAllocator
#include <hw/mdep/mEventTbl.h> // for OFF_MDEP_N{INT,TRP}_MAX
#include <hw/Event.h> // for off_Trap, off_Irq et al.
These allocators are created at trap and interrupt table instantiation time.
<Initialize t_alloc. >= (<-U)
t_alloc((off_Exhausted*)this)
<Initialize i_alloc. >= (<-U)
i_alloc((off_Exhausted*)this)
Note how in every case the revocator is the event table. As it does not makes sense to perform event revocation it behaves as a null revocator.
<Other public methods of off_EventTbl. >= (<-U) [D->]
// Notifies that events are exhausted.
void notify(void){;}
Once allocators have been created, trap and interrupt tables can be indexed to gain references to traps and interrupts.
<Other public methods of off_TrapTbl. >+= (<-U) [<-D->]
inline off_Trap *operator +(vm_offset_t t);
<Other public methods of off_IntTbl. >+= (<-U) [<-D->]
inline off_Irq *operator +(vm_offset_t i);
<off_TrapTbl::operator + implementation. >= (U->)
inline off_Trap *off_TrapTbl::operator +(vm_offset_t t){
assert(valid());
return t_alloc+t;
}
<off_IntTbl::operator + implementation. >= (U->)
inline off_Irq *off_IntTbl::operator +(vm_offset_t i){
assert(valid());
return i_alloc+i;
}
For efficiency purposes, we also define this operator for event allocators to bypass allocator indexers.
<Other public methods of off_IntAllocator. >= (<-U)
inline off_Irq *operator +(vm_offset_t i);
<Other public methods of off_TrapAllocator. >= (<-U)
inline off_Trap *operator +(vm_offset_t t);
<off_IntAllocator::operator + implementation. >= (U->)
inline off_Irq *off_IntAllocator::operator +(vm_offset_t i) {
return i_irqs+i;
}
<off_TrapAllocator::operator + implementation. >= (U->)
inline off_Trap *off_TrapAllocator::operator +(vm_offset_t t) {
return t_traps+t;
}
These allocators can be obtained with the get_allocator methods of
the Events using it.
<off_TrapTbl::get_allocator implementation. >= (U->)
// Returns a pointer to the trap allocator.
inline off_TrapAllocator *off_TrapTbl::get_allocator(void)
{
return &t_alloc;
}
<off_IntTbl::get_allocator implementation. >= (U->)
// Returns a pointer to the trap allocator.
inline off_IntAllocator *off_IntTbl::get_allocator(void)
{
return &i_alloc;
}
\Note{Redefine [] to gain an index right to the trap structure for a given trap number (same for interrupts). This must be fast.
Trap and interrupt tables can allocate trap and interrupts using these allocators.
<Other public methods of off_TrapTbl. >+= (<-U) [<-D->]
// Allocates a trap.
off_Trap *alloc(const off_ev_id_t at=OFF_EU_ID_NULL);
// Deallocates a trap.
void free( off_Trap *t );
<Other public methods of off_IntTbl. >+= (<-U) [<-D->]
// Allocates an interrupt.
off_Irq *alloc(const off_ev_id_t at=OFF_EU_ID_NULL);
// Deallocates an interrupt.
void free( off_Irq *t );
The implementation is the same seen for previous hardware resource containers.
<off_TrapTbl::alloc implementation. >= (U->)
// Allocates a trap.
off_Trap *off_TrapTbl::alloc(const off_ev_id_t at=OFF_EU_ID_NULL)
{
off_Trap *t;
assert(valid());
w_lock();
t=t_alloc.allocate(at);
w_unlock();
return t;
}
<Off event table dependencies. >+= (U->) [<-D->] #include <assert.h> // for assert
<off_TrapTbl::free implementation. >= (U->)
// Deallocates a trap.
void off_TrapTbl::free( off_Trap *t )
{
assert(valid());
w_lock();
t_alloc.deallocate(t);
w_unlock();
}
<off_IntTbl::alloc implementation. >= (U->)
// Allocates an interrupt..
off_Irq *off_IntTbl::alloc(const off_ev_id_t at=OFF_EU_ID_NULL)
{
off_Irq *i;
assert(valid());
w_lock();
i=i_alloc.allocate(at);
w_unlock();
return i;
}
<off_IntTbl::free implementation. >= (U->)
// Deallocates an interrupt.
void off_IntTbl::free( off_Irq *i )
{
assert(valid());
w_lock();
i_alloc.deallocate(i);
w_unlock();
}
Trap and interrupts are allocated and deallocated with new and
delete operators. The operator new receives the table where
the event should be allocated.
<Other public methods of off_Trap. >+= (<-U) [<-D->]
void *operator new(size_t s, off_TrapTbl *tbl, off_ev_id_t at);
void operator delete(void *p);
<Other public methods of off_Irq. >+= (<-U) [<-D->]
void *operator new(size_t s, off_IntTbl *tbl, off_ev_id_t at);
void operator delete(void *p);
<off_Trap::operator new/delete implementation. >= (U->)
void *off_Trap::operator new(size_t s, off_TrapTbl *tbl, off_io_id_t at)
{
off_Trap *t=tbl->alloc(at);
(void)s;
assert(tbl);
return (void*)t;
}
void off_Trap::operator delete(void *p)
{
off_Trap *t=(off_Trap*)p;
assert(p);
((off_TrapTbl*)(t->get_container()))->free(t);
}
<off_Irq::operator new/delete implementation. >= (U->)
void *off_Irq::operator new(size_t s, off_IntTbl *tbl, off_io_id_t at)
{
off_Irq *i=tbl->alloc(at);
(void)s;
assert(tbl);
return (void*)i;
}
void off_Irq::operator delete(void *p)
{
off_Irq *i=(off_Irq*)p;
assert(p);
((off_IntTbl*)(i->get_container()))->free(i);
}
\subsection{Trap and Interrupt handling}