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};