Hi Eric! There is no internal documentation of the Tasklet interface, so let me post it here if others would be interested.
The RFXLINK stack almost never uses atomic sections (unlike other radio stacks) because we ensure that the stack is not reentered asynchronously. If a (radio or timer) interrupt arrives and the previous interrupt handler has not returned, then we do not reenter the radio stack but remember that we have to handle this interrupt when the previous one is finished. Similarly, if we are in the middle of sending of a packet, then we are not going to handle an incoming message interrupt until we have finished with the send. This simplifies all stat transitions and the readability of the code, and does not impose much limitations since there is usually a shared resource (SPI, radio chip) which would prevent concurrent access anyways (this is achieved by huge and long running atomic blocks in other drivers). Thus we need a task like semantics, lets call it tasklet, which allows only one tasklet to run at a time. This tasklet scheduling domain sits between real tasks and interrupts in a way that it can be configured either to be regular tasks (if TASKLET_IS_TASK is defined) or will run in interrupt context. Tasklet can be scheduled to be executed (similar to posting a task) and the Tasklet.run will be executed when no other tasklet is runing. You can disable/enable the execution of tasklets with the disable/enable commands, which is used when we want to enter the radio stack to send a message and want to get exclusive access (no interruption). Of course only the time critical parts of RFXLINK are protected by tasklets. If Tasklets are configured to run in interrupt context, then taking the first interrupt (A) we call Tasklet.schedule() which will call the Taskletr.run() command immediately, but it remembers internally that a tasklet is already running. When a subsequent interrupt arrives (B) before (A) has returned, and calls Tasklet.schedule() again, then we just remember that Tasklet.run() must be called again, and we immediatelly return from the (B) interrupt. When interrupt (A) returns, then we check whether there were other interrupts so whether we should call Tasklet.run() again. This is why you see the forever loop in the tasklet code: the first interrupt handler acts as a dispatcher (tasklet scheduler) for all subsequent tasklet calls. I hope this makes sense. A similar logic is used in the fast serial path where we prevent the reentrance of the serial interrupt driver by bufferring subsequent received bytes in memory and later calling the handler when the previous one has returned. In fact, I think a general Tasklet infrastructure should be moved to the core tinyos library. It can adapt the Tasklet from the RFXLINK library, but it should allow the creation of independent tasklets (THE RFXLINK library has a single one shared by all components, and everyone will be notified if someone called schedule). Let me know if someone would like to play with such an idea. Best, Miklos On Tue, Jun 4, 2013 at 10:52 PM, Eric Decker <[email protected]> wrote: > > I've started looking at the rfxlib stuff and am wondering why tasklets. > > Any internal documentation that talks about why and how it works? > > -- > Eric B. Decker > Senior (over 50 :-) Researcher > _______________________________________________ Tinyos-help mailing list [email protected] https://www.millennium.berkeley.edu/cgi-bin/mailman/listinfo/tinyos-help
