Because the execution of TinyOS tasks are nonpreemptive and
interrupt handlers preempts tasks, SC is always atomic with respect to
other SCs. However, any update to shared state from AC, or from SC
that is also updated from AC, is a potential race condition. To reinstate
atomicity of updating shared state, nesC provides a keyword
atomic to indicate that the execution of a block of statements should
not be preempted. This construction can be efficiently implemented
by turning off hardware interrupts. To prevent blocking the interrupts
for too long and affecting the responsiveness of the node, nesC
does not allow method calls in atomic blocks. In fact, nesC has a compiler
rule to enforce the accessing of shared variables to maintain the
race-free condition. If a variable x is accessed by AC, then any access
of x outside of an atomic statement is a compile-time error. This rule
may be too rigid in reality. When a programmer knows for sure that
a data race is not going to occur, or does not care if it occurs, then
a norace declaration of the variable can prevent the compiler from
checking the race condition on that variable.