diff options
Diffstat (limited to 'book/en/src/internals/non-reentrancy.md')
-rw-r--r-- | book/en/src/internals/non-reentrancy.md | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/book/en/src/internals/non-reentrancy.md b/book/en/src/internals/non-reentrancy.md new file mode 100644 index 00000000..408a012e --- /dev/null +++ b/book/en/src/internals/non-reentrancy.md @@ -0,0 +1,84 @@ +# Non-reentrancy + +In RTFM, tasks handlers are *not* reentrant. Reentering a task handler can break +Rust aliasing rules and lead to *undefined behavior*. A task handler can be +reentered in one of two ways: in software or by hardware. + +## In software + +To reenter a task handler in software its underlying interrupt handler must be +invoked using FFI (see example below). FFI requires `unsafe` code so end users +are discouraged from directly invoking an interrupt handler. + +``` rust +#[rtfm::app(device = ..)] +const APP: () = { + static mut X: u64 = 0; + + #[init] + fn init(c: init::Context) { .. } + + #[interrupt(binds = UART0, resources = [X])] + fn foo(c: foo::Context) { + let x: &mut u64 = c.resources.X; + + *x = 1; + + //~ `bar` can preempt `foo` at this point + + *x = 2; + + if *x == 2 { + // something + } + } + + #[interrupt(binds = UART1, priority = 2)] + fn bar(c: foo::Context) { + extern "C" { + fn UART0(); + } + + // this interrupt handler will invoke task handler `foo` resulting + // in mutable aliasing of the static variable `X` + unsafe { UART0() } + } +}; +``` + +The RTFM framework must generate the interrupt handler code that calls the user +defined task handlers. We are careful in making these handlers `unsafe` and / or +impossible to call from user code. + +The above example expands into: + +``` rust +fn foo(c: foo::Context) { + // .. user code .. +} + +fn bar(c: bar::Context) { + // .. user code .. +} + +const APP: () = { + // everything in this block is not visible to user code + + #[no_mangle] + unsafe fn USART0() { + foo(..); + } + + #[no_mangle] + unsafe fn USART1() { + bar(..); + } +}; +``` + +## By hardware + +A task handler can also be reentered without software intervention. This can +occur if the same handler is assigned to two or more interrupts in the vector +table but there's no syntax for this kind of configuration in the RTFM +framework. |