This introduces a new marker type for types that shouldn't be thread safe. By adding a field of this type to a struct, it becomes non-Send and non-Sync, which means that it cannot be accessed in any way from threads other than the one it was created on. This is useful for APIs that require globals such as `current` to remain constant while the value exists. We update two existing users in the Kernel to use this helper: * `Task::current()` - moving the return type of this value to a different thread would not be safe as you can no longer be guaranteed that the `current` pointer remains valid. * Lock guards. Mutexes and spinlocks should be unlocked on the same thread as where they were locked, so we enforce this using the Send trait. There are also additional users in later patches of this patchset. See [1] and [2] for the discussion that led to the introduction of this patch. Link: https://lore.kernel.org/all/nFDPJFnzE9Q5cqY7FwSMByRH2OAn_BpI4H53NQfWIlN6I2qfmAqnkp2wRqn0XjMO65OyZY4h6P4K2nAGKJpAOSzksYXaiAK_FoH_8QbgBI4=@proton.me/ [1] Link: https://lore.kernel.org/all/nFDPJFnzE9Q5cqY7FwSMByRH2OAn_BpI4H53NQfWIlN6I2qfmAqnkp2wRqn0XjMO65OyZY4h6P4K2nAGKJpAOSzksYXaiAK_FoH_8QbgBI4=@proton.me/ [2] Suggested-by: Benno Lossin <benno.lossin@proton.me> Reviewed-by: Benno Lossin <benno.lossin@proton.me> Reviewed-by: Trevor Gross <tmgross@umich.edu> Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com> Reviewed-by: Björn Roy Baron <bjorn3_gh@protonmail.com> Reviewed-by: Gary Guo <gary@garyguo.net> Signed-off-by: Alice Ryhl <aliceryhl@google.com> Link: https://lore.kernel.org/r/20240915-alice-file-v10-1-88484f7a3dcf@google.com Signed-off-by: Christian Brauner <brauner@kernel.org>
179 lines
6.2 KiB
Rust
179 lines
6.2 KiB
Rust
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
//! Tasks (threads and processes).
|
|
//!
|
|
//! C header: [`include/linux/sched.h`](srctree/include/linux/sched.h).
|
|
|
|
use crate::{
|
|
bindings,
|
|
types::{NotThreadSafe, Opaque},
|
|
};
|
|
use core::{
|
|
ffi::{c_int, c_long, c_uint},
|
|
ops::Deref,
|
|
ptr,
|
|
};
|
|
|
|
/// A sentinel value used for infinite timeouts.
|
|
pub const MAX_SCHEDULE_TIMEOUT: c_long = c_long::MAX;
|
|
|
|
/// Bitmask for tasks that are sleeping in an interruptible state.
|
|
pub const TASK_INTERRUPTIBLE: c_int = bindings::TASK_INTERRUPTIBLE as c_int;
|
|
/// Bitmask for tasks that are sleeping in an uninterruptible state.
|
|
pub const TASK_UNINTERRUPTIBLE: c_int = bindings::TASK_UNINTERRUPTIBLE as c_int;
|
|
/// Convenience constant for waking up tasks regardless of whether they are in interruptible or
|
|
/// uninterruptible sleep.
|
|
pub const TASK_NORMAL: c_uint = bindings::TASK_NORMAL as c_uint;
|
|
|
|
/// Returns the currently running task.
|
|
#[macro_export]
|
|
macro_rules! current {
|
|
() => {
|
|
// SAFETY: Deref + addr-of below create a temporary `TaskRef` that cannot outlive the
|
|
// caller.
|
|
unsafe { &*$crate::task::Task::current() }
|
|
};
|
|
}
|
|
|
|
/// Wraps the kernel's `struct task_struct`.
|
|
///
|
|
/// # Invariants
|
|
///
|
|
/// All instances are valid tasks created by the C portion of the kernel.
|
|
///
|
|
/// Instances of this type are always refcounted, that is, a call to `get_task_struct` ensures
|
|
/// that the allocation remains valid at least until the matching call to `put_task_struct`.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// The following is an example of getting the PID of the current thread with zero additional cost
|
|
/// when compared to the C version:
|
|
///
|
|
/// ```
|
|
/// let pid = current!().pid();
|
|
/// ```
|
|
///
|
|
/// Getting the PID of the current process, also zero additional cost:
|
|
///
|
|
/// ```
|
|
/// let pid = current!().group_leader().pid();
|
|
/// ```
|
|
///
|
|
/// Getting the current task and storing it in some struct. The reference count is automatically
|
|
/// incremented when creating `State` and decremented when it is dropped:
|
|
///
|
|
/// ```
|
|
/// use kernel::{task::Task, types::ARef};
|
|
///
|
|
/// struct State {
|
|
/// creator: ARef<Task>,
|
|
/// index: u32,
|
|
/// }
|
|
///
|
|
/// impl State {
|
|
/// fn new() -> Self {
|
|
/// Self {
|
|
/// creator: current!().into(),
|
|
/// index: 0,
|
|
/// }
|
|
/// }
|
|
/// }
|
|
/// ```
|
|
#[repr(transparent)]
|
|
pub struct Task(pub(crate) Opaque<bindings::task_struct>);
|
|
|
|
// SAFETY: By design, the only way to access a `Task` is via the `current` function or via an
|
|
// `ARef<Task>` obtained through the `AlwaysRefCounted` impl. This means that the only situation in
|
|
// which a `Task` can be accessed mutably is when the refcount drops to zero and the destructor
|
|
// runs. It is safe for that to happen on any thread, so it is ok for this type to be `Send`.
|
|
unsafe impl Send for Task {}
|
|
|
|
// SAFETY: It's OK to access `Task` through shared references from other threads because we're
|
|
// either accessing properties that don't change (e.g., `pid`, `group_leader`) or that are properly
|
|
// synchronised by C code (e.g., `signal_pending`).
|
|
unsafe impl Sync for Task {}
|
|
|
|
/// The type of process identifiers (PIDs).
|
|
type Pid = bindings::pid_t;
|
|
|
|
impl Task {
|
|
/// Returns a task reference for the currently executing task/thread.
|
|
///
|
|
/// The recommended way to get the current task/thread is to use the
|
|
/// [`current`] macro because it is safe.
|
|
///
|
|
/// # Safety
|
|
///
|
|
/// Callers must ensure that the returned object doesn't outlive the current task/thread.
|
|
pub unsafe fn current() -> impl Deref<Target = Task> {
|
|
struct TaskRef<'a> {
|
|
task: &'a Task,
|
|
_not_send: NotThreadSafe,
|
|
}
|
|
|
|
impl Deref for TaskRef<'_> {
|
|
type Target = Task;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
self.task
|
|
}
|
|
}
|
|
|
|
// SAFETY: Just an FFI call with no additional safety requirements.
|
|
let ptr = unsafe { bindings::get_current() };
|
|
|
|
TaskRef {
|
|
// SAFETY: If the current thread is still running, the current task is valid. Given
|
|
// 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: NotThreadSafe,
|
|
}
|
|
}
|
|
|
|
/// Returns the group leader of the given task.
|
|
pub fn group_leader(&self) -> &Task {
|
|
// SAFETY: By the type invariant, we know that `self.0` is a valid task. Valid tasks always
|
|
// have a valid `group_leader`.
|
|
let ptr = unsafe { *ptr::addr_of!((*self.0.get()).group_leader) };
|
|
|
|
// SAFETY: The lifetime of the returned task reference is tied to the lifetime of `self`,
|
|
// and given that a task has a reference to its group leader, we know it must be valid for
|
|
// the lifetime of the returned task reference.
|
|
unsafe { &*ptr.cast() }
|
|
}
|
|
|
|
/// Returns the PID of the given task.
|
|
pub fn pid(&self) -> Pid {
|
|
// SAFETY: By the type invariant, we know that `self.0` is a valid task. Valid tasks always
|
|
// have a valid pid.
|
|
unsafe { *ptr::addr_of!((*self.0.get()).pid) }
|
|
}
|
|
|
|
/// Determines whether the given task has pending signals.
|
|
pub fn signal_pending(&self) -> bool {
|
|
// SAFETY: By the type invariant, we know that `self.0` is valid.
|
|
unsafe { bindings::signal_pending(self.0.get()) != 0 }
|
|
}
|
|
|
|
/// Wakes up the task.
|
|
pub fn wake_up(&self) {
|
|
// SAFETY: By the type invariant, we know that `self.0.get()` is non-null and valid.
|
|
// And `wake_up_process` is safe to be called for any valid task, even if the task is
|
|
// running.
|
|
unsafe { bindings::wake_up_process(self.0.get()) };
|
|
}
|
|
}
|
|
|
|
// SAFETY: The type invariants guarantee that `Task` is always refcounted.
|
|
unsafe impl crate::types::AlwaysRefCounted for Task {
|
|
fn inc_ref(&self) {
|
|
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
|
|
unsafe { bindings::get_task_struct(self.0.get()) };
|
|
}
|
|
|
|
unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
|
|
// SAFETY: The safety requirements guarantee that the refcount is nonzero.
|
|
unsafe { bindings::put_task_struct(obj.cast().as_ptr()) }
|
|
}
|
|
}
|