[Tinyos-host-mote-wg] Re: [Tinyos-2.0wg] Resource handles
Cory Sharp
cory at moteiv.com
Fri Oct 21 16:59:07 PDT 2005
Okay, let me try throwing some examples around.
One thing I want is to immediately satisfy requests if possible,
otherwise defer. This is (at least for me) what I commonly want from
the arbiter. Of course, it's possible to do that in TOS2 with this
technique:
void doSomethingGranted() {
// use the resource
call Resource.release();
}
void doSomething() {
if( call Resource.immediateRequest() )
doSomethingGranted();
else
call Resource.request();
}
event void Resource.granted() {
doSomethingGranted();
}
That pattern becomes tedious if you use it a lot. For instance, my
modified CC2420Control interface now looks like this, notice the
"uint8_t rh" parameters:
interface CC2420Control {
command result_t TunePreset( uint8_t rh, uint8_t channel );
command result_t TuneManual( uint8_t rh, uint16_t freq );
command uint8_t GetPreset();
command uint16_t GetFrequency();
async command result_t VREFOn();
async command result_t VREFOff();
async command result_t OscillatorOn( uint8_t rh );
async command result_t OscillatorOff( uint8_t rh );
async command result_t TxMode( uint8_t rh );
async command result_t TxModeOnCCA( uint8_t rh );
async command result_t RxMode( uint8_t rh );
command result_t SetRFPower( uint8_t rh, uint8_t power );
command uint8_t GetRFPower();
async command result_t enableAutoAck( uint8_t rh );
async command result_t disableAutoAck( uint8_t rh );
async command result_t enableAddrDecode( uint8_t rh );
async command result_t disableAddrDecode( uint8_t rh );
command result_t setShortAddress( uint8_t rh, uint16_t addr );
}
Those parameters means, "This command is arbitrated. If you call me
with an ungranted resource handle such as RESOURCE_NONE, I will defer
your request if the resource is not available. If you call me with a
granted resource handle, I will execute immediately."
If each of those arbitrated commands is a unique resource user, that
"if immediateRequest else request, create a body handler" pattern is
repeated 12 times.
Why might I implement each one as a unique resource user? Because I
don't know how many of those different commands to CC2420Control will
be called before the resource becomes available, I need to either 1)
force each user of the CC2420Control interface to re-request if a
command FAIL'ed, or 2) use just one resource and internally implement
some form of internal command queueing, or 3) make each command be a
unique resource user, handing off the queueing to the arbiter.
As much as possible, I don't want require components above to check
for error codes, because that's tedious, error prone, and possibly
duplicative. I don't want to necessarily implement an internal queue
if I don't have to for the same reasons. And if I want my system to
be responsive, I want the commands satisified immediately if they can
be, otherwise deferred.
All of that together means I want the arbitration semantic to call
back immediately if possible, and that means pairing async requests
with async granteds, and sync requests with sync granteds. And, in
the most clean way possible, that means two interfaces.
By the way, as I use it more, I *like* having the "uint8_t rh"
parameter, because it forces me to know that the command uses an
arbitrated resource and act accordingly.
The way I've structured my code, having two interfaces is barely a
burden. Here, the generic MSP430ResourceUSART0C allocates a new
resource user ID and exposes the two interfaces. Internal to the
arbiter, those ID's map to the same queue, just as if the two
interfaces were conjoined. The user can pick either interface to use,
but not both:
generic configuration MSP430ResourceUSART0C() {
provides interface ResourceUser;
provides interface ResourceUserAsync;
}
implementation {
components MSP430ArbiterUSART0C as ArbiterC;
enum { ID = unique("MSP430ResourceUSART0")+1 };
ResourceUser = ArbiterC.ResourceUser[ID];
ResourceUserAsync = ArbiterC.ResourceUserAsync[ID];
}
Another thing I want is for lower level components to *assert* that it
is okay for them to use the resource, even if the aribtration request
happens above them. (This is what I meant by "nesting" of requests.)
I'm not quite sure how this works in the current TOS2 Resource and
ResourceUser interfaces work to achieve this. If it's possible, it
looks complicated, and if it's simple, I'd to see it how it works.
async command uint8_t HPLCC2420.cmd( uint8_t rh, uint8_t addr ) {
uint8_t status = 0;
if( call CC2420Resource.immediateRequest(rh) ) {
atomic f.busy = TRUE;
TOSH_CLR_RADIO_CSN_PIN();
// clear the RX flag if set
call USARTControl.isTxIntrPending();
call USARTControl.rx(); //isRxIntrPending();
call USARTControl.tx(addr);
while(f.enabled && !(call USARTControl.isRxIntrPending())) ;
status = adjustStatusByte(call USARTControl.rx());
TOSH_SET_RADIO_CSN_PIN();
atomic f.busy = FALSE;
call CC2420Resource.release();
}
return status;
}
Because HPLCC2420.cmd is a synchronous command that returns a status
byte, it must only use immediateRequest and fail otherwise. I still
want to have that command play nice with the bus, in case the
component above isn't playing nice. And, I also want to allow the
component above to reserve the bus for a sequence of uninterrupted
HPLCC2420.cmd's.
Another example is CC2420Control. Once CC2420RadioM gets the bus, I
want to allow it to call a series of HPLCC2420 commands intermingled
with CC2420Control commands. If an interrupt occurs in that sequence
and another component decides it wants to use CC2420Control commands,
which is acceptable, I want that other component to defer, which is
the right thing to do.
I can dig around for more examples, but let me know if that helps
clarify anything about my thinking...
Cory
On 10/21/05, David Gay <dgay42 at gmail.com> wrote:
> [I think concrete examples/code would help, I'm somewhat confused as
> to what the problems and proposals are...]
>
> On 10/21/05, Cory Sharp <cory at moteiv.com> wrote:
> > Hi all,
> >
> > I'd like to propose some changes to the TOS2 resource arbitration.
> > Below are requests (R#) and arguments (A#) for them.
> >
> > R1) Allow components to share their permission
>
> I'm unclear what this means?
>
> > A1.1) Provide for resource reservations across a batch of commands.
> > To maximize robustness, we'd like lower components to not just assume
> > they have access to the shared resource, but validate their access
> > with the arbiter.
>
> While runtime checking is all well and good, I'd have to ask whether
> this was a major source of runtime failures, and worth the checking
> effort... Also, to validate access with the arbiter requires that the
> components have access to the client identity everywhere (which is
> often not otherwise necessary - look at AdcC on the atmega128 for
> instance).
>
> > This allows for "nesting" of arbitration requests.
>
> I'm also unclear what this means. And to the extent I do guess at
> something, what's missing from the ResourceUser interface?
>
> > There is currently no way to do this with the current arbitration
> > proposal. The only options are all or none. That is, a component
> > must either 1) defer *all* requests through the resource arbiter,
> > which could allow for unwanted shared bus usage during a sensitive
> > transaction, or 2) provide *no* resource arbitration guarantees.
>
> Again, I'm not quite clear what this means.
>
> > A1.2) Allow for multiple users of a submodule to play nicely.
> > Consider a Radio module for send/receive and its Control module for
> > ack enable/disable, etc. Radio gets the bus and performs a number of
> > operations, including some Control commands. While this is happening,
> > commands from other modules (application, routing, etc) that are also
> > using the Control module should be deferred.
>
> How isn't this achieved by having a common arbiter used by the radio,
> application, routing, etc?
>
> > R2) Allow for urgent requests that take precedence over standard requests
> >
> > A2) When time stamping outgoing packets, the radio component releases
> > the bus, captures a start of frame delimiter interrupt, then must
> > reacquire the bus to put the time stamp bytes into the outgoing queue.
> > Failure to do so results in corrupted/lost packets. While we can't
> > expect to fully eliminate these failures, we'd like to minimize them
> > by allowing these requests to go to the front of the arbitration
> > queue.
>
> I think that's readily supportable by an appropriate arbiter, no?
> There's definitely no exhaustive list of desired arbiters yet...
>
> > R3) Make granting requests more efficient if the resource is
> > immediately available.
> >
> > A3) Currently all granted events go through tasks, meaning they are
> > deferred even if immediately satisfiable. This is an extension of R2
> > above, where we don't want urgent grants to go through the task queue
> > if they don't need to.
>
> You can use immediateRequest for that, followed by request if it fails.
>
> > R4) Make it more apparent in the interfaces which components need to
> > be arbitrated
> >
> > A4) It's not apparent which components expect to be arbitrated and
> > which components manage their own arbitration.
>
> Yes. I think taking a leaf from the paper, non-private components
> should either have @atmostonce() interfaces (no arbitration), Resource
> interfaces or be virtualised (ok, they'll probably be exceptions, but
> they should be rare).
>
> > R5) Separate the "requested" event into a separate, optional interface.
> >
> > A5) A majority of resource users will choose not to handle the
> > requested event, because their arbitrated usage of the resource is
> > essentially uninterruptable. For the usage patterns of a component
> > individually arbitrating many commands, writing stub handlers can be a
> > tedious burden.
>
> Sounds like a good idea. Though it does decrease the change that
> components that could release a resource will.
>
> > PROPOSAL:
> >
> > P1) Pass around resource handles/tokens. A request is immediately
> > satisfied if made using the token from the current resource owner.
> > Otherwise, the request is deferred into the arbitration queue. The
> > token RESOURCE_NONE is always invalid. This initially seems like a
> > burden, but it quickly becomes a feature when you can more explicitly
> > follow the train of ownership and users.
>
> I have to say I'm not convinced. Essentially every split-phase call
> which isn't virtualised will end up with a client-id, no? And doesn't
> this make sharing the same interfaces with virtualised services
> harder?
>
> > P2) Create ResourceUser, ResourceUserUrgent, and ResourceRequested interfaces.
> >
> > interface ResourceUser {
> > command void request( uint8_t rh );
> > async command uint8_t immediateRequest( uint8_t rh );
> > event void granted( uint8_t rh );
> > async command void release();
> > }
> >
> > interface ResourceUserUrgent {
> > async command void request( uint8_t rh );
> > async command uint8_t immediateRequest( uint8_t rh );
> > async event void granted( uint8_t rh );
> > async command void release();
> > }
>
> As I said above, I don't think these two distinctions are useful
> (examples otherwise appreciated).
>
> >
> > interface ResourceRequest {
> > async event void requested( bool urgent );
> > }
>
> This one seemed reasonable (not sure about the async or urgent bit).
>
> > In both the ResourceUser and ResourceUserUrgent interfaces, if
> > request(rh) is immediately satisfiable, granted(rh) is signalled
> > within the request call. Otherwise, the requests is put either last
> > or next in the queue, respectively. When release is called, if the
> > next user is urgent, granted is signalled within the release call,
> > otherwise the next grant is signalled through a new task. Only the
> > true owner can release a component. Releases by permitted non-owners
> > are ignored.
> >
> > Interfaces that allow for outer arbitration add "uint8_t rh" as the
> > first parameter to arbitrated commands, such as commands on the
> > CC2420Control interface. Components are not required to do this, and
> > can instead choose manage a separate internal queuing, such as the
> > commands in the SendMsg interface.
> >
> > This proposal is currently derived from my direct experience with the
> > FCFS arbiter. I don't know how it plays out with the round robin
> > arbiter.
> >
> > What have other people's experiences been with the TOS2 aribiters?
>
> No particular problems for the mica Adc... Phil?
>
> David
>
> _______________________________________________
> Tinyos-2.0wg mailing list
> Tinyos-2.0wg at Mail.Millennium.Berkeley.EDU
> https://mail.millennium.berkeley.edu/cgi-bin/mailman/listinfo/tinyos-2.0wg
>
_______________________________________________
Tinyos-2.0wg mailing list
Tinyos-2.0wg at Mail.Millennium.Berkeley.EDU
https://mail.millennium.berkeley.edu/cgi-bin/mailman/listinfo/tinyos-2.0wg
More information about the Tinyos-host-mote-wg
mailing list