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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
// SPDX-License-Identifier: GPL-2.0
//! Synchronisation primitives.
//!
//! This module contains the kernel APIs related to synchronisation that have been ported or
//! wrapped for usage by Rust code in the kernel.
//!
//! # Examples
//!
//! ```
//! # use kernel::mutex_init;
//! # use kernel::sync::Mutex;
//! # use alloc::boxed::Box;
//! # use core::pin::Pin;
//! // SAFETY: `init` is called below.
//! let mut data = Pin::from(Box::try_new(unsafe { Mutex::new(10) }).unwrap());
//! mutex_init!(data.as_mut(), "test::data");
//!
//! assert_eq!(*data.lock(), 10);
//! *data.lock() = 20;
//! assert_eq!(*data.lock(), 20);
//! ```
use crate::{bindings, str::CStr};
use core::{cell::UnsafeCell, mem::MaybeUninit, pin::Pin};
mod arc;
mod condvar;
mod guard;
mod locked_by;
mod mutex;
mod nowait;
pub mod rcu;
mod revocable;
mod rwsem;
mod seqlock;
pub mod smutex;
mod spinlock;
pub use arc::{new_refcount, Arc, ArcBorrow, StaticArc, UniqueArc};
pub use condvar::CondVar;
pub use guard::{Guard, Lock, LockFactory, LockInfo, LockIniter, ReadLock, WriteLock};
pub use locked_by::LockedBy;
pub use mutex::{Mutex, RevocableMutex, RevocableMutexGuard};
pub use nowait::{NoWaitLock, NoWaitLockGuard};
pub use revocable::{Revocable, RevocableGuard};
pub use rwsem::{RevocableRwSemaphore, RevocableRwSemaphoreGuard, RwSemaphore};
pub use seqlock::{SeqLock, SeqLockReadGuard};
pub use spinlock::{RawSpinLock, SpinLock};
/// Represents a lockdep class. It's a wrapper around C's `lock_class_key`.
#[repr(transparent)]
pub struct LockClassKey(UnsafeCell<MaybeUninit<bindings::lock_class_key>>);
// SAFETY: This is a wrapper around a lock class key, so it is safe to use references to it from
// any thread.
unsafe impl Sync for LockClassKey {}
impl LockClassKey {
/// Creates a new lock class key.
pub const fn new() -> Self {
Self(UnsafeCell::new(MaybeUninit::uninit()))
}
pub(crate) fn get(&self) -> *mut bindings::lock_class_key {
self.0.get().cast()
}
}
/// Safely initialises an object that has an `init` function that takes a name and a lock class as
/// arguments, examples of these are [`Mutex`] and [`SpinLock`]. Each of them also provides a more
/// specialised name that uses this macro.
#[doc(hidden)]
#[macro_export]
macro_rules! init_with_lockdep {
($obj:expr, $name:expr) => {{
static CLASS1: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
static CLASS2: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
let obj = $obj;
let name = $crate::c_str!($name);
$crate::sync::NeedsLockClass::init(obj, name, &CLASS1, &CLASS2)
}};
}
/// A trait for types that need a lock class during initialisation.
///
/// Implementers of this trait benefit from the [`init_with_lockdep`] macro that generates a new
/// class for each initialisation call site.
pub trait NeedsLockClass {
/// Initialises the type instance so that it can be safely used.
///
/// Callers are encouraged to use the [`init_with_lockdep`] macro as it automatically creates a
/// new lock class on each usage.
fn init(
self: Pin<&mut Self>,
name: &'static CStr,
key1: &'static LockClassKey,
key2: &'static LockClassKey,
);
}
/// Automatically initialises static instances of synchronisation primitives.
///
/// The syntax resembles that of regular static variables, except that the value assigned is that
/// of the protected type (if one exists). In the examples below, all primitives except for
/// [`CondVar`] require the inner value to be supplied.
///
/// # Examples
///
/// ```ignore
/// # use kernel::{init_static_sync, sync::{CondVar, Mutex, RevocableMutex, SpinLock}};
/// struct Test {
/// a: u32,
/// b: u32,
/// }
///
/// init_static_sync! {
/// static A: Mutex<Test> = Test { a: 10, b: 20 };
///
/// /// Documentation for `B`.
/// pub static B: Mutex<u32> = 0;
///
/// pub(crate) static C: SpinLock<Test> = Test { a: 10, b: 20 };
/// static D: CondVar;
///
/// static E: RevocableMutex<Test> = Test { a: 30, b: 40 };
/// }
/// ```
#[macro_export]
macro_rules! init_static_sync {
($($(#[$outer:meta])* $v:vis static $id:ident : $t:ty $(= $value:expr)?;)*) => {
$(
$(#[$outer])*
$v static $id: $t = {
#[link_section = ".init_array"]
#[used]
static TMP: extern "C" fn() = {
extern "C" fn constructor() {
// SAFETY: This locally-defined function is only called from a constructor,
// which guarantees that `$id` is not accessible from other threads
// concurrently.
#[allow(clippy::cast_ref_to_mut)]
let mutable = unsafe { &mut *(&$id as *const _ as *mut $t) };
// SAFETY: It's a shared static, so it cannot move.
let pinned = unsafe { core::pin::Pin::new_unchecked(mutable) };
$crate::init_with_lockdep!(pinned, stringify!($id));
}
constructor
};
$crate::init_static_sync!(@call_new $t, $($value)?)
};
)*
};
(@call_new $t:ty, $value:expr) => {{
let v = $value;
// SAFETY: the initialisation function is called by the constructor above.
unsafe { <$t>::new(v) }
}};
(@call_new $t:ty,) => {
// SAFETY: the initialisation function is called by the constructor above.
unsafe { <$t>::new() }
};
}
/// Reschedules the caller's task if needed.
pub fn cond_resched() -> bool {
// SAFETY: No arguments, reschedules `current` if needed.
unsafe { bindings::cond_resched() != 0 }
}