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:
@@ -7,7 +7,6 @@
|
||||
use crate::{
|
||||
bindings,
|
||||
ffi::{c_int, c_long, c_uint},
|
||||
mm::MmWithUser,
|
||||
types::{NotThreadSafe, Opaque},
|
||||
};
|
||||
use core::{
|
||||
@@ -33,16 +32,8 @@ pub const TASK_NORMAL: c_uint = bindings::TASK_NORMAL as c_uint;
|
||||
#[macro_export]
|
||||
macro_rules! current {
|
||||
() => {
|
||||
// SAFETY: This expression creates a temporary value that is dropped at the end of the
|
||||
// caller's scope. The following mechanisms ensure that the resulting `&CurrentTask` cannot
|
||||
// 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.
|
||||
// SAFETY: Deref + addr-of below create a temporary `TaskRef` that cannot outlive the
|
||||
// caller.
|
||||
unsafe { &*$crate::task::Task::current() }
|
||||
};
|
||||
}
|
||||
@@ -85,7 +76,7 @@ macro_rules! current {
|
||||
/// impl State {
|
||||
/// fn new() -> Self {
|
||||
/// Self {
|
||||
/// creator: ARef::from(&**current!()),
|
||||
/// creator: current!().into(),
|
||||
/// index: 0,
|
||||
/// }
|
||||
/// }
|
||||
@@ -105,44 +96,6 @@ unsafe impl Send for Task {}
|
||||
// synchronised by C code (e.g., `signal_pending`).
|
||||
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).
|
||||
pub type Pid = bindings::pid_t;
|
||||
|
||||
@@ -169,29 +122,28 @@ impl Task {
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Callers must ensure that the returned object is only used to access a [`CurrentTask`]
|
||||
/// within the task context that was active when this function was called. For more details,
|
||||
/// see the invariants section for [`CurrentTask`].
|
||||
pub unsafe fn current() -> impl Deref<Target = CurrentTask> {
|
||||
struct TaskRef {
|
||||
task: *const CurrentTask,
|
||||
/// 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 = CurrentTask;
|
||||
impl Deref for TaskRef<'_> {
|
||||
type Target = Task;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
// SAFETY: The returned reference borrows from this `TaskRef`, so it cannot outlive
|
||||
// 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 }
|
||||
self.task
|
||||
}
|
||||
}
|
||||
|
||||
let current = Task::current_raw();
|
||||
TaskRef {
|
||||
// CAST: The layout of `struct task_struct` and `CurrentTask` is identical.
|
||||
task: Task::current_raw().cast(),
|
||||
// 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 { &*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.
|
||||
unsafe impl crate::types::AlwaysRefCounted for Task {
|
||||
fn inc_ref(&self) {
|
||||
|
||||
Reference in New Issue
Block a user