Hardwire shuttle properties are not an issue for allocation.
Non-hardwired Shuttle Properties are kept in property sets, of type
ShtlPropAllocator. A ShtlPropAllocator is a collection of
ShtlProps using a fixed allocator.
<Off shuttle property allocator. >= (U->)
// A set of property values
class off_ShtlPropAllocator : public off_TBmAllocator<off_ShtlProp> {
private:
static off_Indexer<off_ShtlProp> s_idx;
off_ShtlProp s_props[OFF_NPROP_MAX];
public:
// Allows uninitialized allocators.
off_ShtlPropAllocator(void):
off_TBmAllocator<off_ShtlProp>(OFF_NPROP_MAX)
{;}
<off_ShtlPropAllocator::off_ShtlPropAllocator implementation. >
const off_ShtlPropAllocator &operator=(const off_ShtlPropAllocator &other) {
return (*this=other);
}
<Other public methods of off_ShtlPropAllocator. >
};
Definesoff_ShtlPropAllocator(links are to index).
<Off shuttle property allocator static members. >= (U->) off_Indexer<off_ShtlProp> off_ShtlPropAllocator::s_idx;
The maximum number of shuttle properties is a system limit.
<Off limits. >= const int OFF_NPROP_MAX = 8; // Max. # of shuttle properties.
DefinesOFF_NPROP_MAX(links are to index).
<Off shuttle property allocator dependencies. >= (U->) #include <klib/ids.h> // for off_id_t et al. #include <klib/BmAllocator.h> // for off_TBmAllocator #include <shtl/ShtlProp.h> // for off_ShtlProp #include <klib/limits.h> // for OFF_NPROP_MAX #include <flux/debug.h> // for do_debug
The property allocator redefines a couple of TBmAllocator methods
to implement them more efficiently.
<Other public methods of off_ShtlPropAllocator. >= (<-U)
off_ShtlProp *operator +(natural_t at) {
return s_props+(at);
}
off_ShtlProp &operator [](natural_t at) {
return s_props[at];
}
natural_t pos(off_ShtlProp*p) {
return p - s_props;
}
Where OFF_NPROP_BUILTIN is a shuttle server supplied constant.
When the property allocator is created, it initializes its property array.
<off_ShtlPropAllocator::off_ShtlPropAllocator implementation. >= (<-U)
// Creates a ShtlProp allocator.
off_ShtlPropAllocator::off_ShtlPropAllocator(off_Exhausted *r) :
off_TBmAllocator<off_ShtlProp>(r,(const off_Indexable*)&s_idx,
&s_props[0],OFF_NPROP_MAX )
{
do_debug(putchar('p'));
}
The allocator is initialized when the shuttle is instantiated. It uses the shuttle as a (null) revocator.
<Initialize Shtl::s_palloc. >= (<-U)
s_palloc((off_Exhausted*)this)
The shuttle provides this null notify routine.
<Other public methods of off_Shtl. >+= (<-U) [<-D->]
// Notifies that properties are exhausted.
void notify(void){;}
After being initialized, the allocator is filled up with those properties found in the prototype shuttle so that a shuttle can not violate the constraints imposed by its properties by creating another shuttle.
<Initialize other private members ofoff_Shtlaccording toproto. >= (<-U) s_palloc=*proto->get_allocator(); <Initialize hardwired properties with those ofproto. >
To simplify property handling, shuttles provide only three methods to handle their properties.
<Other public methods of off_Shtl. >+= (<-U) [<-D->]
// Defines a new property and sets its initial value.
off_prop_t def_prop(off_ShtlPropSrv *srv, const off_id_t &val);
// Gets the value for a given property.
off_id_t get_prop(off_prop_t p);
// Sets the value for a given property.
void set_prop(off_prop_t p, const off_id_t &val);
<Off shuttle dependencies. >+= (U->) [<-D->] #include <shtl/ShtlProp.h>
When a property is defined it uses the first available property slot
and its number (adjusted with the number of predefined properties,
NPROP_BUILTIN) is returned to the user.
<off_Shtl::def_prop implementation. >= (U->)
// Defines a new property.
off_prop_t off_Shtl::def_prop(off_ShtlPropSrv *srv, const off_id_t &val)
{
off_ShtlProp *p=new(this) off_ShtlProp(srv,val);
if (!p)
return OFF_PROP_NULL;
else
return s_palloc.pos(p) + OFF_NPROP_BUILTIN;
}
<off_Shtl::get_propimplementation. >= (U->) // Gets the value for a given property. off_id_t off_Shtl::get_prop(off_prop_t p) { switch(p){ <case to return predefined propertypvalue inget_prop. > default: return s_palloc[p-OFF_NPROP_BUILTIN].get_val(); } }
<off_Shtl::set_propimplementation. >= (U->) // Sets the value for a given property. void off_Shtl::set_prop(off_prop_t p, const off_id_t &val) { switch(p){ <case to set predefined propertypvaluevalinset_prop. > default: s_palloc[p].pset(val,get_id()); s_palloc[p].set_val(val); } }
Before we used the operator new to define a new property. We have
to implement it.
<Other public methods of off_ShtlProp. >+= (<-U) [<-D]
// Allocates a new property slot.
void *operator new(size_t s, off_Shtl *s);
<off_ShtlProp::operator new implementation. >= (U->)
// Allocates a new property slot.
void *off_ShtlProp::operator new(size_t s, off_Shtl *sh)
{
(void)s;
return (void*)(sh->get_allocator()->allocate(FALSE));
}
<Off shuttle property dependencies. >+= (U->) [<-D] class off_Shtl;
<Off shuttle property implementation dependencies. >= (U->) #include <shtl/Shtl.h>
\subsection{Hardwired shuttle properties}
Most of the hardwired properties are properties already supported by
the processor hardware. They are usually implemented in the machine
dependent part. Every shuttle maintains a data structure, s_mdep
with machine dependent information and routines.
<Off shuttle server predefined properties numbers. >= (U->) // Predefined shuttle properties: const off_prop_t OFF_SHTLP_PCTX = 0; // processor context const off_prop_t OFF_SHTLP_IPL = 1; // irq privilege level const off_prop_t OFF_SHTLP_DTLB = 2; // dtlb being used const off_prop_t OFF_SHTLP_RUNS = 3; // run state (blocked|ready) const off_prop_t OFF_SHTLP_YLDS = 4; // yield state. const off_prop_t OFF_SHTLP_IOPL = 5; // Can doo user io? // # of predefined shuttle properties. const off_prop_t OFF_NPROP_BUILTIN= 6;
We will be seeing features provided by mdepShtl through this
section.