mirror of
https://github.com/nkbai/book.git
synced 2026-08-26 13:23:28 +08:00
Merge #71
71: concurrency: small tweaks to the atomics section r=adamgreig a=japaric r? @adamgreig Co-authored-by: Jorge Aparicio <jorge@japaric.io>
This commit is contained in:
@@ -161,9 +161,9 @@ increment operation. These atomic operations are safe even across multiple
|
||||
cores.
|
||||
|
||||
```rust
|
||||
// New type for COUNTER
|
||||
use core::sync::atomic;
|
||||
static mut COUNTER: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
static COUNTER: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
@@ -174,7 +174,7 @@ fn main() -> ! {
|
||||
if state && !last_state {
|
||||
last_state = state;
|
||||
// Use `fetch_add` to atomically add 1 to COUNTER
|
||||
unsafe { COUNTER.fetch_add(1, atomic::Ordering::Relaxed) };
|
||||
COUNTER.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -182,22 +182,22 @@ fn main() -> ! {
|
||||
#[interrupt]
|
||||
fn timer() {
|
||||
// Use `store` to write 0 directly to COUNTER
|
||||
unsafe { COUNTER.store(0, atomic::Ordering::Relaxed) }
|
||||
COUNTER.store(0, Ordering::Relaxed)
|
||||
}
|
||||
```
|
||||
|
||||
We still require `unsafe` blocks since `COUNTER` is a `static mut`, but we no
|
||||
longer have the overhead of disabling all interrupts. When possible, this is a
|
||||
better solution — but it may not be supported on your platform.
|
||||
This time `COUNTER` is a safe `static` variable. Thanks to the `AtomicUsize`
|
||||
type `COUNTER` can be safely modified from both the interrupt handler and the
|
||||
main thread without disabling interrupts. When possible, this is a better
|
||||
solution — but it may not be supported on your platform.
|
||||
|
||||
A note on [`Ordering`]: this affects how the compiler and hardware may reorder
|
||||
instructions, and also has consequences on cache visibility. For simple atomic
|
||||
operations like incrementing a counter, where we are not synchronising any
|
||||
other tasks on the counter, `Relaxed` is sufficient, and will have the best
|
||||
performance on typical embedded platforms. Stricter ordering will cause the
|
||||
compiler to emit memory barriers around the atomic operations; depending on
|
||||
what you're using atomics for you may or may not need this! The precise
|
||||
details of the atomic model are complicated and best described elsewhere.
|
||||
instructions, and also has consequences on cache visibility. Assuming that the
|
||||
target is a single core platform `Relaxed` is sufficient and the most efficient
|
||||
choice in this particular case. Stricter ordering will cause the compiler to
|
||||
emit memory barriers around the atomic operations; depending on what you're
|
||||
using atomics for you may or may not need this! The precise details of the
|
||||
atomic model are complicated and best described elsewhere.
|
||||
|
||||
For more details on atomics and ordering, see the [nomicon].
|
||||
|
||||
|
||||
Reference in New Issue
Block a user