From 72eb16b46dc9ff12ae38b9d9fb94e3ad7a4b2e65 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 15 Jun 2022 10:24:36 +0200 Subject: [PATCH] Add missing documentation for all public modules and types --- embassy/src/blocking_mutex/mod.rs | 30 +++++++++++++++++++++++++----- embassy/src/blocking_mutex/raw.rs | 23 +++++++++++++++++++++++ embassy/src/channel/signal.rs | 1 + embassy/src/mutex.rs | 24 ++++++++++++++++++------ embassy/src/util/steal.rs | 10 ++++++++++ embassy/src/waitqueue/waker.rs | 9 +++++++++ 6 files changed, 86 insertions(+), 11 deletions(-) diff --git a/embassy/src/blocking_mutex/mod.rs b/embassy/src/blocking_mutex/mod.rs index eb3cd9392..65daf15c4 100644 --- a/embassy/src/blocking_mutex/mod.rs +++ b/embassy/src/blocking_mutex/mod.rs @@ -1,14 +1,23 @@ -//! Blocking mutex (not async) - +//! Blocking mutex. +//! +//! This module provides a blocking mutex that can be used to synchronize data. pub mod raw; use core::cell::UnsafeCell; use self::raw::RawMutex; -/// Any object implementing this trait guarantees exclusive access to the data contained -/// within the mutex for the duration of the lock. -/// Adapted from . +/// Blocking mutex (not async) +/// +/// Provides a blocking mutual exclusion primitive backed by an implementation of [`raw::RawMutex`]. +/// +/// Which implementation you select depends on the context in which you're using the mutex. +/// +/// Use [`CriticalSectionMutex`] when data can be shared between threads and interrupts. +/// +/// Use [`NoopMutex`] when data is only shared between tasks running on the same executor. +/// +/// Use [`ThreadModeMutex`] when data is shared between tasks running on the same executor but you want a global singleton. pub struct Mutex { // NOTE: `raw` must be FIRST, so when using ThreadModeMutex the "can't drop in non-thread-mode" gets // to run BEFORE dropping `data`. @@ -78,7 +87,18 @@ impl Mutex { } } +/// A mutex that allows borrowing data across executors and interrupts. +/// +/// # Safety +/// +/// This mutex is safe to share between different executors and interrupts. pub type CriticalSectionMutex = Mutex; + +/// A mutex that allows borrowing data in the context of a single executor. +/// +/// # Safety +/// +/// **This Mutex is only safe within a single executor.** pub type NoopMutex = Mutex; impl Mutex { diff --git a/embassy/src/blocking_mutex/raw.rs b/embassy/src/blocking_mutex/raw.rs index f9d249b08..bdb443e4d 100644 --- a/embassy/src/blocking_mutex/raw.rs +++ b/embassy/src/blocking_mutex/raw.rs @@ -1,11 +1,22 @@ +//! Mutex primitives. +//! +//! This module provides a trait for mutexes that can be used in different contexts. use core::marker::PhantomData; +/// Any object implementing this trait guarantees exclusive access to the data contained +/// within the mutex for the duration of the lock. +/// Adapted from . pub trait RawMutex { const INIT: Self; fn lock(&self, f: impl FnOnce() -> R) -> R; } +/// A mutex that allows borrowing data across executors and interrupts. +/// +/// # Safety +/// +/// This mutex is safe to share between different executors and interrupts. pub struct CriticalSectionRawMutex { _phantom: PhantomData<()>, } @@ -28,6 +39,11 @@ impl RawMutex for CriticalSectionRawMutex { // ================ +/// A mutex that allows borrowing data in the context of a single executor. +/// +/// # Safety +/// +/// **This Mutex is only safe within a single executor.** pub struct NoopRawMutex { _phantom: PhantomData<*mut ()>, } @@ -53,6 +69,13 @@ impl RawMutex for NoopRawMutex { mod thread_mode { use super::*; + /// A "mutex" that only allows borrowing from thread mode. + /// + /// # Safety + /// + /// **This Mutex is only safe on single-core systems.** + /// + /// On multi-core systems, a `ThreadModeRawMutex` **is not sufficient** to ensure exclusive access. pub struct ThreadModeRawMutex { _phantom: PhantomData<()>, } diff --git a/embassy/src/channel/signal.rs b/embassy/src/channel/signal.rs index 5a2c9d47a..cf78dad8b 100644 --- a/embassy/src/channel/signal.rs +++ b/embassy/src/channel/signal.rs @@ -1,3 +1,4 @@ +//! A synchronization primitive for passing the latest value to a task. use core::cell::UnsafeCell; use core::future::Future; use core::mem; diff --git a/embassy/src/mutex.rs b/embassy/src/mutex.rs index 7b6bcb147..9cfaaa845 100644 --- a/embassy/src/mutex.rs +++ b/embassy/src/mutex.rs @@ -1,9 +1,6 @@ -/// Async mutex. -/// -/// The mutex is generic over a blocking [`RawMutex`](crate::blocking_mutex::raw::RawMutex). -/// The raw mutex is used to guard access to the internal "is locked" flag. It -/// is held for very short periods only, while locking and unlocking. It is *not* held -/// for the entire time the async Mutex is locked. +//! Async mutex. +//! +//! This module provides a mutex that can be used to synchronize data between asynchronous tasks. use core::cell::{RefCell, UnsafeCell}; use core::ops::{Deref, DerefMut}; use core::task::Poll; @@ -24,6 +21,21 @@ struct State { waker: WakerRegistration, } +/// Async mutex. +/// +/// The mutex is generic over a blocking [`RawMutex`](crate::blocking_mutex::raw::RawMutex). +/// The raw mutex is used to guard access to the internal "is locked" flag. It +/// is held for very short periods only, while locking and unlocking. It is *not* held +/// for the entire time the async Mutex is locked. +/// +/// Which implementation you select depends on the context in which you're using the mutex. +/// +/// Use [`CriticalSectionRawMutex`](crate::blocking_mutex::raw::CriticalSectionRawMutex) when data can be shared between threads and interrupts. +/// +/// Use [`NoopRawMutex`](crate::blocking_mutex::raw::NoopRawMutex) when data is only shared between tasks running on the same executor. +/// +/// Use [`ThreadModeRawMutex`](crate::blocking_mutex::raw::ThreadModeRawMutex) when data is shared between tasks running on the same executor but you want a singleton. +/// pub struct Mutex where M: RawMutex, diff --git a/embassy/src/util/steal.rs b/embassy/src/util/steal.rs index a0d5f1359..07eb5fffd 100644 --- a/embassy/src/util/steal.rs +++ b/embassy/src/util/steal.rs @@ -1,3 +1,13 @@ +/// A type that can retrieved unsafely from anywhere. pub trait Steal { + /// Retrieve and instance of this type. + /// + /// # Safety + /// + /// It is the responsibility of the application to ensure that the + /// usage of the returned instance is not in conflict with other uses + /// of this instance. + /// + /// The implementation may panic if the instance is already in use. unsafe fn steal() -> Self; } diff --git a/embassy/src/waitqueue/waker.rs b/embassy/src/waitqueue/waker.rs index 1ac6054f9..da907300a 100644 --- a/embassy/src/waitqueue/waker.rs +++ b/embassy/src/waitqueue/waker.rs @@ -6,6 +6,10 @@ use atomic_polyfill::{compiler_fence, AtomicPtr, Ordering}; use crate::executor::raw::{task_from_waker, wake_task, TaskHeader}; /// Utility struct to register and wake a waker. +/// +/// # Safety +/// +/// This type is optimized for (and only works with) embassy tasks. #[derive(Debug)] pub struct WakerRegistration { waker: Option>, @@ -53,6 +57,11 @@ impl WakerRegistration { unsafe impl Send for WakerRegistration {} unsafe impl Sync for WakerRegistration {} +/// Utility struct to atomically register and wake a waker. +/// +/// # Safety +/// +/// This type is optimized for (and only works with) embassy tasks. pub struct AtomicWaker { waker: AtomicPtr, }