Revert "BACKPORT: FROMLIST: task: rust: rework how current is accessed"
This reverts commit 98c8011159.
Bug: 429146594
Change-Id: Ib6968a1a63aafb9fea3e485c39d451b70cf320b4
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
This commit is contained in:
+17
-97
@@ -7,7 +7,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
bindings,
|
bindings,
|
||||||
ffi::{c_int, c_long, c_uint},
|
ffi::{c_int, c_long, c_uint},
|
||||||
mm::MmWithUser,
|
|
||||||
types::{NotThreadSafe, Opaque},
|
types::{NotThreadSafe, Opaque},
|
||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
@@ -33,16 +32,8 @@ pub const TASK_NORMAL: c_uint = bindings::TASK_NORMAL as c_uint;
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! current {
|
macro_rules! current {
|
||||||
() => {
|
() => {
|
||||||
// SAFETY: This expression creates a temporary value that is dropped at the end of the
|
// SAFETY: Deref + addr-of below create a temporary `TaskRef` that cannot outlive the
|
||||||
// caller's scope. The following mechanisms ensure that the resulting `&CurrentTask` cannot
|
// caller.
|
||||||
// leave current task context:
|
|
||||||
//
|
|
||||||
// * To return to userspace, the caller must leave the current scope.
|
|
||||||
// * Operations such as `begin_new_exec()` are necessarily unsafe and the caller of
|
|
||||||
// `begin_new_exec()` is responsible for safety.
|
|
||||||
// * Rust abstractions for things such as a `kthread_use_mm()` scope must require the
|
|
||||||
// closure to be `Send`, so the `NotThreadSafe` field of `CurrentTask` ensures that the
|
|
||||||
// `&CurrentTask` cannot cross the scope in either direction.
|
|
||||||
unsafe { &*$crate::task::Task::current() }
|
unsafe { &*$crate::task::Task::current() }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -85,7 +76,7 @@ macro_rules! current {
|
|||||||
/// impl State {
|
/// impl State {
|
||||||
/// fn new() -> Self {
|
/// fn new() -> Self {
|
||||||
/// Self {
|
/// Self {
|
||||||
/// creator: ARef::from(&**current!()),
|
/// creator: current!().into(),
|
||||||
/// index: 0,
|
/// index: 0,
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
@@ -105,44 +96,6 @@ unsafe impl Send for Task {}
|
|||||||
// synchronised by C code (e.g., `signal_pending`).
|
// synchronised by C code (e.g., `signal_pending`).
|
||||||
unsafe impl Sync for Task {}
|
unsafe impl Sync for Task {}
|
||||||
|
|
||||||
/// Represents the [`Task`] in the `current` global.
|
|
||||||
///
|
|
||||||
/// This type exists to provide more efficient operations that are only valid on the current task.
|
|
||||||
/// For example, to retrieve the pid-namespace of a task, you must use rcu protection unless it is
|
|
||||||
/// the current task.
|
|
||||||
///
|
|
||||||
/// # Invariants
|
|
||||||
///
|
|
||||||
/// Each value of this type must only be accessed from the task context it was created within.
|
|
||||||
///
|
|
||||||
/// Of course, every thread is in a different task context, but for the purposes of this invariant,
|
|
||||||
/// these operations also permanently leave the task context:
|
|
||||||
///
|
|
||||||
/// * Returning to userspace from system call context.
|
|
||||||
/// * Calling `release_task()`.
|
|
||||||
/// * Calling `begin_new_exec()` in a binary format loader.
|
|
||||||
///
|
|
||||||
/// Other operations temporarily create a new sub-context:
|
|
||||||
///
|
|
||||||
/// * Calling `kthread_use_mm()` creates a new context, and `kthread_unuse_mm()` returns to the
|
|
||||||
/// old context.
|
|
||||||
///
|
|
||||||
/// This means that a `CurrentTask` obtained before a `kthread_use_mm()` call may be used again
|
|
||||||
/// once `kthread_unuse_mm()` is called, but it must not be used between these two calls.
|
|
||||||
/// Conversely, a `CurrentTask` obtained between a `kthread_use_mm()`/`kthread_unuse_mm()` pair
|
|
||||||
/// must not be used after `kthread_unuse_mm()`.
|
|
||||||
#[repr(transparent)]
|
|
||||||
pub struct CurrentTask(Task, NotThreadSafe);
|
|
||||||
|
|
||||||
// Make all `Task` methods available on `CurrentTask`.
|
|
||||||
impl Deref for CurrentTask {
|
|
||||||
type Target = Task;
|
|
||||||
#[inline]
|
|
||||||
fn deref(&self) -> &Task {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The type of process identifiers (PIDs).
|
/// The type of process identifiers (PIDs).
|
||||||
pub type Pid = bindings::pid_t;
|
pub type Pid = bindings::pid_t;
|
||||||
|
|
||||||
@@ -169,29 +122,28 @@ impl Task {
|
|||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// Callers must ensure that the returned object is only used to access a [`CurrentTask`]
|
/// Callers must ensure that the returned object doesn't outlive the current task/thread.
|
||||||
/// within the task context that was active when this function was called. For more details,
|
pub unsafe fn current() -> impl Deref<Target = Task> {
|
||||||
/// see the invariants section for [`CurrentTask`].
|
struct TaskRef<'a> {
|
||||||
pub unsafe fn current() -> impl Deref<Target = CurrentTask> {
|
task: &'a Task,
|
||||||
struct TaskRef {
|
_not_send: NotThreadSafe,
|
||||||
task: *const CurrentTask,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for TaskRef {
|
impl Deref for TaskRef<'_> {
|
||||||
type Target = CurrentTask;
|
type Target = Task;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
// SAFETY: The returned reference borrows from this `TaskRef`, so it cannot outlive
|
self.task
|
||||||
// the `TaskRef`, which the caller of `Task::current()` has promised will not
|
|
||||||
// outlive the task/thread for which `self.task` is the `current` pointer. Thus, it
|
|
||||||
// is okay to return a `CurrentTask` reference here.
|
|
||||||
unsafe { &*self.task }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let current = Task::current_raw();
|
||||||
TaskRef {
|
TaskRef {
|
||||||
// CAST: The layout of `struct task_struct` and `CurrentTask` is identical.
|
// SAFETY: If the current thread is still running, the current task is valid. Given
|
||||||
task: Task::current_raw().cast(),
|
// that `TaskRef` is not `Send`, we know it cannot be transferred to another thread
|
||||||
|
// (where it could potentially outlive the caller).
|
||||||
|
task: unsafe { &*current.cast() },
|
||||||
|
_not_send: NotThreadSafe,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,38 +269,6 @@ impl Task {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CurrentTask {
|
|
||||||
/// Access the address space of the current task.
|
|
||||||
///
|
|
||||||
/// This function does not touch the refcount of the mm.
|
|
||||||
#[inline]
|
|
||||||
pub fn mm(&self) -> Option<&MmWithUser> {
|
|
||||||
// SAFETY: The `mm` field of `current` is not modified from other threads, so reading it is
|
|
||||||
// not a data race.
|
|
||||||
let mm = unsafe { (*self.as_ptr()).mm };
|
|
||||||
|
|
||||||
if mm.is_null() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SAFETY: If `current->mm` is non-null, then it references a valid mm with a non-zero
|
|
||||||
// value of `mm_users`. Furthermore, the returned `&MmWithUser` borrows from this
|
|
||||||
// `CurrentTask`, so it cannot escape the scope in which the current pointer was obtained.
|
|
||||||
//
|
|
||||||
// This is safe even if `kthread_use_mm()`/`kthread_unuse_mm()` are used. There are two
|
|
||||||
// relevant cases:
|
|
||||||
// * If the `&CurrentTask` was created before `kthread_use_mm()`, then it cannot be
|
|
||||||
// accessed during the `kthread_use_mm()`/`kthread_unuse_mm()` scope due to the
|
|
||||||
// `NotThreadSafe` field of `CurrentTask`.
|
|
||||||
// * If the `&CurrentTask` was created within a `kthread_use_mm()`/`kthread_unuse_mm()`
|
|
||||||
// scope, then the `&CurrentTask` cannot escape that scope, so the returned `&MmWithUser`
|
|
||||||
// also cannot escape that scope.
|
|
||||||
// In either case, it's not possible to read `current->mm` and keep using it after the
|
|
||||||
// scope is ended with `kthread_unuse_mm()`.
|
|
||||||
Some(unsafe { MmWithUser::from_raw(mm) })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SAFETY: The type invariants guarantee that `Task` is always refcounted.
|
// SAFETY: The type invariants guarantee that `Task` is always refcounted.
|
||||||
unsafe impl crate::types::AlwaysRefCounted for Task {
|
unsafe impl crate::types::AlwaysRefCounted for Task {
|
||||||
fn inc_ref(&self) {
|
fn inc_ref(&self) {
|
||||||
|
|||||||
Reference in New Issue
Block a user