On Jul 3, 2006, at 11:45 PM, Frigging wrote:

Hi,
I'm a little bit confused.
I'm wondering, but:
1) only async events can preempt tasks?
2) async events can preempt sync commands/events?
3) therefore, sync events can't peempt task or other sync commands/ events,
is it?
4) but if a async function can preempt other async function where did handle the policy, and where did save the program counter when there's preemption? 5) if while interrupt is handling, an other interrupt comes, will it be
dropped?

Sorry for my silly questions :-(

We run around on this every few months. :)

The basic confusion stems from the fact that the original TinyOS paper did not have the sync/async boundary and uses the word "event" for two purposes: a TinyOS event (an upcall) and a hardware event (an interrupt). Hardware interrupts can preempt tasks.

I find the easiest way to understand it is to just look at main(), which goes something like this:

main() {
  // initialize system
  while(1) {
    while(runNextTask()) {}
    sleep();
  }
}

The system is normally sleeping. When an interrupt comes in, it wakes up the MCU (the sleep instruction completes), which then checks if there are any tasks pending. If not, it goes back to sleep. If there are tasks in the queue, it runs them one after the other. They run non-preemptively, because the main() loop doesn't run a new one until the current one returns. This is why tasks cannot preempt one another.

Interrupts, however, can preempt tasks. All code that an interrupt handler calls must be async. The hardware takes care of pushing some context on the stack, and the compiler takes care of spilling registers to memory. The question of when interrupts can be handled or not (interrupt preemption, etc.) depends on 2 things: the chip architecture and whether the code has disabled interrupts or adjusted the interrupt priority level.

Note, however, that preemption and re-entrancy are different issues. This is one reason why there's the guideline of "don't signal events from commands." Take this example:

component A {
  busy = FALSE;

  command error_t x() {
     if (busy) {return FAIL;}
     if (call Y.start() == SUCCESS) {
        busy = TRUE;
        return SUCCESS;
     }
  }

  event void Y.done() {
     busy = FALSE;
  }
}

If Y is a truly split-phase interface, this code will work OK. But if Y's implementation does this:


  command error_t Y.start() {
    if (z) {
      signal Y.done();
      return SUCCESS;
    }
    // something else
  }

Then when component A calls Y.start, Y.done will be signaled while it is still in the statement call Y.start(). This will set busy to be FALSE, but then when Y.start returns, component A will set busy to be TRUE and the component will never make another request.

The TinyOS programming manual has a discussion of the concurrency model:

http://csl.stanford.edu/~pal/pubs/tinyos-programming.pdf

Phil



_______________________________________________
Tinyos-help mailing list
[email protected]
https://mail.millennium.berkeley.edu/cgi-bin/mailman/listinfo/tinyos-help

Reply via email to