Hi Oldrine, I think the code is correct as it is. You have to realize the meaning of tasklet_async: it means that it is guaranteed that code protected by tasklet_async will never execute concurrently. In the driver this is achieved by just setting a flag when an interrupt occurs and then calling Tasklet.schedule which either 1) calls the Tasklet.run if it is not already running, or schedules it to be run again when the pevious one completes, 2) or when TASKLET_IS_TASK is defined then just posts the task that driver the same Tasklet.run event. Both of these guarantees that only ONE of those will run at any time. This was the interaction between interrupt context and tasklet context. You also have to think about task and tasklet context: look at what MessageBufferLayerP does: it calls Tasklet.suspend and Tasklet.resume to make sure that when in the critical tasklet section then no other code is running.
It is by design that we do not sprinkle code with a lot of atomic, because there is much more going on than atomic access, you really do not want to update the state of the WHOLE radio stack concurrently, even though you could prevent the update of individual registers concurrently. To make sure that your code works as it should, you should compile it with both TASKLET_IS_TASK enabled and disabled. If it gives a warning in either of these cases, then you do not use tasklets correctly. Please let me know if this makes sense, or I just really do not see the problem. Miklos On Mon, Dec 10, 2012 at 9:28 AM, Oldrine Lewis <[email protected]> wrote: > I have been experiencing some lockups with the radio recently. The problem > seems to occur when RandomCollisionLayerP::SubSend.send() is called by > MessageBufferLayerP, but RandomCollisionLayerP never calls > RF230DriverHwAckP::RadioSend.send(). MessageBufferLayerP ends up waiting > forever for SendDone() to be signaled. > > I debugged the code and it seems that the following sequence of events could > be the likely cause > > The following sequence of events seems to be trigger > > · RandomCollisionLayerP::SubReceive.receive() is signaled by > RF230DriverHwAckP > > · After executing the line if( state == STATE_READY ), > RandomCollisionLayerP::RadioSend.send() Interrupts the receive routine > > · Since state == STATE_READY , > RandomCollisionLayerP::RadioSend.send() proceeds and sets, state = > STATE_TX_PENDING_FIRST > > · RandomCollisionLayerP::SubReceive.receive() resumes and overwrites > the state ( state = STATE_BARRIER) > > · The radio is essentially locked at this moment > > > > Solution: > > Protect RandomCollisionLayerP::RadioSend.send() and RandomCollisionLayerP:: > SubReceive.receive() from race conditions > > > > tasklet_async command error_t RadioSend.send(message_t* msg) > > { > > atomic > > { > > if( state != STATE_READY || ! call RadioAlarm.isFree() ) > > { > > return EBUSY; > > } > > state = STATE_TX_PENDING_FIRST; > > } > > > > > > txMsg = msg; > > > > call RadioAlarm.wait(getBackoff(call > Config.getInitialBackoff(msg))); > > //post DBG_Snd(); > > atomic bIsTxRxExec = FALSE; > > return SUCCESS; > > } > > > > > > > > > > tasklet_async event message_t* SubReceive.receive(message_t* msg) > > { > > > > if( delay > 0 ) > > { > > atomic > > { > > if( state == STATE_READY ) > > { > > call RadioAlarm.wait(delay); > > state = STATE_BARRIER; > > } > > else > > { > > state |= STATE_BARRIER; > > } > > } > > } > > > > > > > > I have noticed extensive use of the norace keyword, while that itself will > not cause problems, it might fail to draw attention to variables that need > more attention > > > > > _______________________________________________ > Tinyos-help mailing list > [email protected] > https://www.millennium.berkeley.edu/cgi-bin/mailman/listinfo/tinyos-help _______________________________________________ Tinyos-help mailing list [email protected] https://www.millennium.berkeley.edu/cgi-bin/mailman/listinfo/tinyos-help
