diff options
Diffstat (limited to 'rust')
-rw-r--r-- | rust/kernel/sync/lock.rs | 13 | ||||
-rw-r--r-- | rust/kernel/task.rs | 10 | ||||
-rw-r--r-- | rust/kernel/types.rs | 21 |
3 files changed, 36 insertions, 8 deletions
diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs index f6c34ca4d819..d6e9bab114b8 100644 --- a/rust/kernel/sync/lock.rs +++ b/rust/kernel/sync/lock.rs @@ -6,8 +6,13 @@ //! spinlocks, raw spinlocks) to be provided with minimal effort. use super::LockClassKey; -use crate::{init::PinInit, pin_init, str::CStr, types::Opaque, types::ScopeGuard}; -use core::{cell::UnsafeCell, marker::PhantomData, marker::PhantomPinned}; +use crate::{ + init::PinInit, + pin_init, + str::CStr, + types::{NotThreadSafe, Opaque, ScopeGuard}, +}; +use core::{cell::UnsafeCell, marker::PhantomPinned}; use macros::pin_data; pub mod mutex; @@ -139,7 +144,7 @@ impl<T: ?Sized, B: Backend> Lock<T, B> { pub struct Guard<'a, T: ?Sized, B: Backend> { pub(crate) lock: &'a Lock<T, B>, pub(crate) state: B::GuardState, - _not_send: PhantomData<*mut ()>, + _not_send: NotThreadSafe, } // SAFETY: `Guard` is sync when the data protected by the lock is also sync. @@ -191,7 +196,7 @@ impl<'a, T: ?Sized, B: Backend> Guard<'a, T, B> { Self { lock, state, - _not_send: PhantomData, + _not_send: NotThreadSafe, } } } diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs index 55dff7e088bf..278c623de0c6 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -4,10 +4,12 @@ //! //! C header: [`include/linux/sched.h`](srctree/include/linux/sched.h). -use crate::types::Opaque; +use crate::{ + bindings, + types::{NotThreadSafe, Opaque}, +}; use core::{ ffi::{c_int, c_long, c_uint}, - marker::PhantomData, ops::Deref, ptr, }; @@ -106,7 +108,7 @@ impl Task { pub unsafe fn current() -> impl Deref<Target = Task> { struct TaskRef<'a> { task: &'a Task, - _not_send: PhantomData<*mut ()>, + _not_send: NotThreadSafe, } impl Deref for TaskRef<'_> { @@ -125,7 +127,7 @@ impl Task { // that `TaskRef` is not `Send`, we know it cannot be transferred to another thread // (where it could potentially outlive the caller). task: unsafe { &*ptr.cast() }, - _not_send: PhantomData, + _not_send: NotThreadSafe, } } diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index 9e7ca066355c..3238ffaab031 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -532,3 +532,24 @@ unsafe impl AsBytes for str {} // does not have any uninitialized portions either. unsafe impl<T: AsBytes> AsBytes for [T] {} unsafe impl<T: AsBytes, const N: usize> AsBytes for [T; N] {} + +/// Zero-sized type to mark types not [`Send`]. +/// +/// Add this type as a field to your struct if your type should not be sent to a different task. +/// Since [`Send`] is an auto trait, adding a single field that is `!Send` will ensure that the +/// whole type is `!Send`. +/// +/// If a type is `!Send` it is impossible to give control over an instance of the type to another +/// task. This is useful to include in types that store or reference task-local information. A file +/// descriptor is an example of such task-local information. +/// +/// This type also makes the type `!Sync`, which prevents immutable access to the value from +/// several threads in parallel. +pub type NotThreadSafe = PhantomData<*mut ()>; + +/// Used to construct instances of type [`NotThreadSafe`] similar to how `PhantomData` is +/// constructed. +/// +/// [`NotThreadSafe`]: type@NotThreadSafe +#[allow(non_upper_case_globals)] +pub const NotThreadSafe: NotThreadSafe = PhantomData; |