1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//! # Overview
//!
//! hermit-sync provides synchronization primitives targeted at operating system kernels.
//!
//! # Interrupts
//!
//! [`without_interrupts`] runs a closure with disabled interrupts.
//!
//! # Mutexes
//!
//! This crate provides three kinds of mutexes based on [`lock_api::RawMutex`]:
//! * [`RawSpinMutex`] is a simple [test and test-and-set] [spinlock] with [exponential backoff].
//! * [`RawTicketMutex`] is a [fair] [ticket lock] with [exponential backoff].
//! * [`RawInterruptMutex`] wraps another mutex and disables interrupts while locked.
//!
//! [test and test-and-set]: https://en.wikipedia.org/wiki/Test_and_test-and-set
//! [spinlock]: https://en.wikipedia.org/wiki/Spinlock
//! [exponential backoff]: https://en.wikipedia.org/wiki/Exponential_backoff
//! [fair]: https://en.wikipedia.org/wiki/Unbounded_nondeterminism
//! [ticket lock]: https://en.wikipedia.org/wiki/Ticket_lock
//!
//! For API documentation see [`lock_api::Mutex`].
//!
//! # Initializing Static Data
//!
//! There are two primitives for safely initializing static data based on [`generic_once_cell`] and [`RawSpinMutex`]:
//! * [`OnceCell`] can be written to only once and can then be accessed without locking.
//! * [`Lazy`] wraps a [`OnceCell`] and is initialized on the first access from a closure.
//!
//! For API documentation see [`generic_once_cell::OnceCell`] and [`generic_once_cell::Lazy`].
//!
//! # Type Definitions
//!
//! This crate provides a lot of type definitions for ease of use:
//!
//! | [`RawMutex`]       | Base                 | With [`RawInterruptMutex`]    |
//! | ------------------ | -------------------- | ----------------------------- |
//! | [`RawSpinMutex`]   | [`SpinMutex`]        | [`InterruptSpinMutex`]        |
//! |                    | [`SpinMutexGuard`]   | [`InterruptSpinMutexGuard`]   |
//! |                    | [`OnceCell`]         | [`InterruptOnceCell`]         |
//! |                    | [`Lazy`]             | [`InterruptLazy`]             |
//! | [`RawTicketMutex`] | [`TicketMutex`]      | [`InterruptTicketMutex`]      |
//! |                    | [`TicketMutexGuard`] | [`InterruptTicketMutexGuard`] |
//!
//! [`RawMutex`]: lock_api::RawMutex

#![cfg_attr(not(test), no_std)]
#![warn(unsafe_op_in_unsafe_fn)]

pub(crate) mod interrupts;
pub(crate) mod mutex;

pub use interrupts::without_interrupts;
pub use mutex::{
    interrupt::{InterruptMutex, InterruptMutexGuard, RawInterruptMutex},
    spin::{RawSpinMutex, SpinMutex, SpinMutexGuard},
    ticket::{RawTicketMutex, TicketMutex, TicketMutexGuard},
    InterruptSpinMutex, InterruptSpinMutexGuard, InterruptTicketMutex, InterruptTicketMutexGuard,
};

pub type OnceCell<T> = generic_once_cell::OnceCell<mutex::spin::RawSpinMutex, T>;
pub type Lazy<T, F = fn() -> T> = generic_once_cell::Lazy<mutex::spin::RawSpinMutex, T, F>;

pub type InterruptOnceCell<T> = generic_once_cell::OnceCell<mutex::RawInterruptSpinMutex, T>;
pub type InterruptLazy<T, F = fn() -> T> =
    generic_once_cell::Lazy<mutex::RawInterruptSpinMutex, T, F>;