Skip to content

Commit 4aa73fd

Browse files
authored
Merge pull request torvalds#641 from wedsonaf/static-mutex
rust: add support for static synchronisation primitives
2 parents 8d97e52 + 4b9a68f commit 4aa73fd

File tree

8 files changed

+71
-7
lines changed

8 files changed

+71
-7
lines changed

init/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2059,6 +2059,7 @@ config RUST
20592059
depends on ARM64 || CPU_32v6 || CPU_32v6K || (PPC64 && CPU_LITTLE_ENDIAN) || X86_64 || RISCV
20602060
depends on !MODVERSIONS
20612061
depends on !GCC_PLUGIN_RANDSTRUCT
2062+
select CONSTRUCTORS
20622063
default n
20632064
help
20642065
Enables Rust support in the kernel.

rust/kernel/str.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ where
338338
/// ```
339339
#[macro_export]
340340
macro_rules! c_str {
341-
($str:literal) => {{
341+
($str:expr) => {{
342342
const S: &str = concat!($str, "\0");
343343
const C: &$crate::str::CStr = $crate::str::CStr::from_bytes_with_nul_unwrap(S.as_bytes());
344344
C

rust/kernel/sync/condvar.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ impl CondVar {
4848
/// # Safety
4949
///
5050
/// The caller must call `CondVar::init` before using the conditional variable.
51-
pub unsafe fn new() -> Self {
51+
pub const unsafe fn new() -> Self {
5252
Self {
5353
wait_list: Opaque::uninit(),
5454
_pin: PhantomPinned,

rust/kernel/sync/mod.rs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub use spinlock::SpinLock;
4949
#[doc(hidden)]
5050
#[macro_export]
5151
macro_rules! init_with_lockdep {
52-
($obj:expr, $name:literal) => {{
52+
($obj:expr, $name:expr) => {{
5353
static mut CLASS1: core::mem::MaybeUninit<$crate::bindings::lock_class_key> =
5454
core::mem::MaybeUninit::uninit();
5555
static mut CLASS2: core::mem::MaybeUninit<$crate::bindings::lock_class_key> =
@@ -87,6 +87,69 @@ pub trait NeedsLockClass {
8787
);
8888
}
8989

90+
/// Automatically initialises static instances of synchronisation primitives.
91+
///
92+
/// The syntax resembles that of regular static variables, except that the value assigned is that
93+
/// of the protected type (if one exists). In the examples below, all primitives except for
94+
/// [`CondVar`] require the inner value to be supplied.
95+
///
96+
/// # Examples
97+
///
98+
/// ```ignore
99+
/// # use kernel::{init_static_sync, sync::{CondVar, Mutex, RevocableMutex, SpinLock}};
100+
/// struct Test {
101+
/// a: u32,
102+
/// b: u32,
103+
/// }
104+
///
105+
/// init_static_sync! {
106+
/// static A: Mutex<Test> = Test { a: 10, b: 20 };
107+
///
108+
/// /// Documentation for `B`.
109+
/// pub static B: Mutex<u32> = 0;
110+
///
111+
/// pub(crate) static C: SpinLock<Test> = Test { a: 10, b: 20 };
112+
/// static D: CondVar;
113+
///
114+
/// static E: RevocableMutex<Test> = Test { a: 30, b: 40 };
115+
/// }
116+
/// ```
117+
#[macro_export]
118+
macro_rules! init_static_sync {
119+
($($(#[$outer:meta])* $v:vis static $id:ident : $t:ty $(= $value:expr)?;)*) => {
120+
$(
121+
$(#[$outer])*
122+
$v static $id: $t = {
123+
#[link_section = ".ctors"]
124+
#[used]
125+
static TMP: extern "C" fn() = {
126+
extern "C" fn constructor() {
127+
// SAFETY: This locally-defined function is only called from a constructor,
128+
// which guarantees that `$id` is not accessible from other threads
129+
// concurrently.
130+
#[allow(clippy::cast_ref_to_mut)]
131+
let mutable = unsafe { &mut *(&$id as *const _ as *mut $t) };
132+
// SAFETY: It's a shared static, so it cannot move.
133+
let pinned = unsafe { core::pin::Pin::new_unchecked(mutable) };
134+
$crate::init_with_lockdep!(pinned, stringify!($id));
135+
}
136+
constructor
137+
};
138+
$crate::init_static_sync!(@call_new $t, $($value)?)
139+
};
140+
)*
141+
};
142+
(@call_new $t:ty, $value:expr) => {{
143+
let v = $value;
144+
// SAFETY: the initialisation function is called by the constructor above.
145+
unsafe { <$t>::new(v) }
146+
}};
147+
(@call_new $t:ty,) => {
148+
// SAFETY: the initialisation function is called by the constructor above.
149+
unsafe { <$t>::new() }
150+
};
151+
}
152+
90153
/// Reschedules the caller's task if needed.
91154
pub fn cond_resched() -> bool {
92155
// SAFETY: No arguments, reschedules `current` if needed.

rust/kernel/sync/mutex.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ impl<T> Mutex<T> {
5353
/// # Safety
5454
///
5555
/// The caller must call [`Mutex::init_lock`] before using the mutex.
56-
pub unsafe fn new(t: T) -> Self {
56+
pub const unsafe fn new(t: T) -> Self {
5757
Self {
5858
mutex: Opaque::uninit(),
5959
data: UnsafeCell::new(t),

rust/kernel/sync/revocable_mutex.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ impl<T> RevocableMutex<T> {
8080
/// # Safety
8181
///
8282
/// The caller must call [`RevocableMutex::init`] before using the revocable mutex.
83-
pub unsafe fn new(data: T) -> Self {
83+
pub const unsafe fn new(data: T) -> Self {
8484
Self {
8585
// SAFETY: The safety requirements of this function require that `RevocableMutex::init`
8686
// be called before the returned object can be used. Mutex initialisation is called

rust/kernel/sync/spinlock.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ impl<T> SpinLock<T> {
9696
/// # Safety
9797
///
9898
/// The caller must call [`SpinLock::init_lock`] before using the spinlock.
99-
pub unsafe fn new(t: T) -> Self {
99+
pub const unsafe fn new(t: T) -> Self {
100100
Self {
101101
spin_lock: Opaque::uninit(),
102102
data: UnsafeCell::new(t),

rust/kernel/types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ impl<T> Opaque<T> {
283283
}
284284

285285
/// Creates an uninitialised value.
286-
pub fn uninit() -> Self {
286+
pub const fn uninit() -> Self {
287287
Self(MaybeUninit::uninit())
288288
}
289289

0 commit comments

Comments
 (0)