Skip to content

Commit

Permalink
Merge pull request raspberrypi#641 from wedsonaf/static-mutex
Browse files Browse the repository at this point in the history
rust: add support for static synchronisation primitives
  • Loading branch information
wedsonaf authored Jan 27, 2022
2 parents 8d97e52 + 4b9a68f commit 4aa73fd
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 7 deletions.
1 change: 1 addition & 0 deletions init/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2059,6 +2059,7 @@ config RUST
depends on ARM64 || CPU_32v6 || CPU_32v6K || (PPC64 && CPU_LITTLE_ENDIAN) || X86_64 || RISCV
depends on !MODVERSIONS
depends on !GCC_PLUGIN_RANDSTRUCT
select CONSTRUCTORS
default n
help
Enables Rust support in the kernel.
Expand Down
2 changes: 1 addition & 1 deletion rust/kernel/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ where
/// ```
#[macro_export]
macro_rules! c_str {
($str:literal) => {{
($str:expr) => {{
const S: &str = concat!($str, "\0");
const C: &$crate::str::CStr = $crate::str::CStr::from_bytes_with_nul_unwrap(S.as_bytes());
C
Expand Down
2 changes: 1 addition & 1 deletion rust/kernel/sync/condvar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl CondVar {
/// # Safety
///
/// The caller must call `CondVar::init` before using the conditional variable.
pub unsafe fn new() -> Self {
pub const unsafe fn new() -> Self {
Self {
wait_list: Opaque::uninit(),
_pin: PhantomPinned,
Expand Down
65 changes: 64 additions & 1 deletion rust/kernel/sync/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub use spinlock::SpinLock;
#[doc(hidden)]
#[macro_export]
macro_rules! init_with_lockdep {
($obj:expr, $name:literal) => {{
($obj:expr, $name:expr) => {{
static mut CLASS1: core::mem::MaybeUninit<$crate::bindings::lock_class_key> =
core::mem::MaybeUninit::uninit();
static mut CLASS2: core::mem::MaybeUninit<$crate::bindings::lock_class_key> =
Expand Down Expand Up @@ -87,6 +87,69 @@ pub trait NeedsLockClass {
);
}

/// 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 = ".ctors"]
#[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.
Expand Down
2 changes: 1 addition & 1 deletion rust/kernel/sync/mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl<T> Mutex<T> {
/// # Safety
///
/// The caller must call [`Mutex::init_lock`] before using the mutex.
pub unsafe fn new(t: T) -> Self {
pub const unsafe fn new(t: T) -> Self {
Self {
mutex: Opaque::uninit(),
data: UnsafeCell::new(t),
Expand Down
2 changes: 1 addition & 1 deletion rust/kernel/sync/revocable_mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl<T> RevocableMutex<T> {
/// # Safety
///
/// The caller must call [`RevocableMutex::init`] before using the revocable mutex.
pub unsafe fn new(data: T) -> Self {
pub const unsafe fn new(data: T) -> Self {
Self {
// SAFETY: The safety requirements of this function require that `RevocableMutex::init`
// be called before the returned object can be used. Mutex initialisation is called
Expand Down
2 changes: 1 addition & 1 deletion rust/kernel/sync/spinlock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ impl<T> SpinLock<T> {
/// # Safety
///
/// The caller must call [`SpinLock::init_lock`] before using the spinlock.
pub unsafe fn new(t: T) -> Self {
pub const unsafe fn new(t: T) -> Self {
Self {
spin_lock: Opaque::uninit(),
data: UnsafeCell::new(t),
Expand Down
2 changes: 1 addition & 1 deletion rust/kernel/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ impl<T> Opaque<T> {
}

/// Creates an uninitialised value.
pub fn uninit() -> Self {
pub const fn uninit() -> Self {
Self(MaybeUninit::uninit())
}

Expand Down

0 comments on commit 4aa73fd

Please sign in to comment.