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

Reply via email to