zephyr/sync.rs
1//! Higher level synchronization primitives.
2//!
3//! These are modeled after the synchronization primitives in
4//! [`std::sync`](https://doc.rust-lang.org/stable/std/sync/index.html) and those from
5//! [`crossbeam-channel`](https://docs.rs/crossbeam-channel/latest/crossbeam_channel/), in as much
6//! as it makes sense.
7
8// Channels are currently only available with allocation. Bounded channels later might be
9// available.
10#[cfg(CONFIG_RUST_ALLOC)]
11pub mod channel;
12
13pub mod atomic {
14 //! Re-export portable atomic.
15 //!
16 //! Although `core` contains a
17 //! [`sync::atomic`](https://doc.rust-lang.org/stable/core/sync/atomic/index.html) module,
18 //! these are dependent on the target having atomic instructions, and the types are missing
19 //! when the platform cannot support them. Zephyr, however, does provide atomics on platforms
20 //! that don't support atomic instructions, using spinlocks. In the Rust-embedded world, this
21 //! is done through the [`portable-atomic`](https://crates.io/crates/portable-atomic) crate,
22 //! which will either just re-export the types from core, or provide an implementation using
23 //! spinlocks when those aren't available.
24
25 pub use portable_atomic::*;
26}
27
28#[cfg(CONFIG_RUST_ALLOC)]
29mod pinweak {
30 use core::pin::Pin;
31 pub use portable_atomic_util::Arc;
32 pub use portable_atomic_util::Weak;
33
34 /// Safe Pinned Weak references.
35 ///
36 /// `Pin<Arc<T>>` can't be converted to/from Weak safely, because there is know way to know if a given
37 /// weak reference came from a pinned Arc. This wraps the weak reference in a new type so we know
38 /// that it came from a pinned Arc.
39 ///
40 /// There is a pin-weak crate that provides this for `std::sync::Arc`, but not for the one in the
41 /// portable-atomic-utils crate.
42 pub struct PinWeak<T>(Weak<T>);
43
44 impl<T> PinWeak<T> {
45 /// Downgrade an `Pin<Arc<T>>` into a `PinWeak`.
46 ///
47 /// This would be easier to use if it could be added to Arc.
48 pub fn downgrade(this: Pin<Arc<T>>) -> Self {
49 // SAFETY: we will never return anything other than a Pin<Arc<T>>.
50 Self(Arc::downgrade(&unsafe { Pin::into_inner_unchecked(this) }))
51 }
52
53 /// Upgrade back to a `Pin<Arc<T>>`.
54 pub fn upgrade(&self) -> Option<Pin<Arc<T>>> {
55 // SAFETY: The weak was only constructed from a `Pin<Arc<T>>`.
56 self.0
57 .upgrade()
58 .map(|arc| unsafe { Pin::new_unchecked(arc) })
59 }
60 }
61}
62
63#[cfg(CONFIG_RUST_ALLOC)]
64pub use pinweak::*;
65
66mod mutex;
67
68pub use mutex::{Condvar, LockResult, Mutex, MutexGuard, TryLockError, TryLockResult};
69
70mod spinmutex;
71
72pub use spinmutex::{SpinMutex, SpinMutexGuard};