From: Wedson Almeida Filho <wedsonaf@gmail.com>
To: rust-for-linux@vger.kernel.org
Cc: "Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
linux-kernel@vger.kernel.org,
"Wedson Almeida Filho" <walmeida@microsoft.com>,
"Ingo Molnar" <mingo@redhat.com>,
"Peter Zijlstra" <peterz@infradead.org>
Subject: [PATCH v2 10/13] rust: introduce `current`
Date: Wed, 5 Apr 2023 14:51:08 -0300 [thread overview]
Message-ID: <20230405175111.5974-10-wedsonaf@gmail.com> (raw)
In-Reply-To: <20230405175111.5974-1-wedsonaf@gmail.com>
From: Wedson Almeida Filho <walmeida@microsoft.com>
This allows Rust code to get a reference to the current task without
having to increment the refcount, but still guaranteeing memory safety.
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Wedson Almeida Filho <walmeida@microsoft.com>
---
v1 -> v2: Make `current` a macro to prevent it from escaping the caller
rust/helpers.c | 6 +++
rust/kernel/prelude.rs | 2 +
rust/kernel/task.rs | 93 +++++++++++++++++++++++++++++++++++++++++-
3 files changed, 100 insertions(+), 1 deletion(-)
diff --git a/rust/helpers.c b/rust/helpers.c
index 58a194042c86..96441744030e 100644
--- a/rust/helpers.c
+++ b/rust/helpers.c
@@ -100,6 +100,12 @@ bool rust_helper_refcount_dec_and_test(refcount_t *r)
}
EXPORT_SYMBOL_GPL(rust_helper_refcount_dec_and_test);
+struct task_struct *rust_helper_get_current(void)
+{
+ return current;
+}
+EXPORT_SYMBOL_GPL(rust_helper_get_current);
+
void rust_helper_get_task_struct(struct task_struct *t)
{
get_task_struct(t);
diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
index fcdc511d2ce8..c28587d68ebc 100644
--- a/rust/kernel/prelude.rs
+++ b/rust/kernel/prelude.rs
@@ -36,3 +36,5 @@ pub use super::error::{code::*, Error, Result};
pub use super::{str::CStr, ThisModule};
pub use super::init::{InPlaceInit, Init, PinInit};
+
+pub use super::current;
diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs
index 8d7a8222990f..468387a5f7eb 100644
--- a/rust/kernel/task.rs
+++ b/rust/kernel/task.rs
@@ -5,7 +5,17 @@
//! C header: [`include/linux/sched.h`](../../../../include/linux/sched.h).
use crate::bindings;
-use core::{cell::UnsafeCell, ptr};
+use core::{cell::UnsafeCell, marker::PhantomData, ops::Deref, ptr};
+
+/// 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`.
///
@@ -13,6 +23,42 @@ use core::{cell::UnsafeCell, ptr};
///
/// Instances of this type are always ref-counted, 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) UnsafeCell<bindings::task_struct>);
@@ -25,6 +71,24 @@ unsafe impl Sync for Task {}
type Pid = bindings::pid_t;
impl Task {
+ /// Returns a task reference for the currently executing task/thread.
+ ///
+ /// # Safety
+ ///
+ /// Callers must ensure that the returned [`TaskRef`] doesn't outlive the current task/thread.
+ pub unsafe fn current<'a>() -> TaskRef<'a> {
+ // 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: PhantomData,
+ }
+ }
+
/// 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 valid.
@@ -69,3 +133,30 @@ unsafe impl crate::types::AlwaysRefCounted for Task {
unsafe { bindings::put_task_struct(obj.cast().as_ptr()) }
}
}
+
+/// A wrapper for a shared reference to [`Task`] that isn't [`Send`].
+///
+/// We make this explicitly not [`Send`] so that we can use it to represent the current thread
+/// without having to increment/decrement the task's reference count.
+///
+/// # Invariants
+///
+/// The wrapped [`Task`] remains valid for the lifetime of the object.
+pub struct TaskRef<'a> {
+ task: &'a Task,
+ _not_send: PhantomData<*mut ()>,
+}
+
+impl Deref for TaskRef<'_> {
+ type Target = Task;
+
+ fn deref(&self) -> &Self::Target {
+ self.task
+ }
+}
+
+impl From<TaskRef<'_>> for crate::types::ARef<Task> {
+ fn from(t: TaskRef<'_>) -> Self {
+ t.deref().into()
+ }
+}
--
2.34.1
next prev parent reply other threads:[~2023-04-05 17:53 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-05 17:50 [PATCH v2 01/13] rust: sync: introduce `LockClassKey` Wedson Almeida Filho
2023-04-05 17:51 ` [PATCH v2 02/13] rust: sync: introduce `Lock` and `Guard` Wedson Almeida Filho
2023-04-05 17:51 ` [PATCH v2 03/13] rust: lock: introduce `Mutex` Wedson Almeida Filho
2023-04-05 18:03 ` Greg KH
2023-04-05 18:04 ` Greg KH
2023-04-05 19:18 ` Peter Zijlstra
2023-04-05 20:21 ` Wedson Almeida Filho
2023-04-05 20:29 ` Peter Zijlstra
2023-04-05 20:40 ` Wedson Almeida Filho
2023-04-05 20:49 ` Peter Zijlstra
2023-04-06 8:38 ` David Laight
2023-04-06 11:21 ` Marco Elver
2023-04-06 16:25 ` Miguel Ojeda
2023-04-06 16:45 ` Miguel Ojeda
2023-04-05 17:51 ` [PATCH v2 04/13] locking/spinlock: introduce spin_lock_init_with_key Wedson Almeida Filho
2023-04-05 17:51 ` [PATCH v2 05/13] rust: lock: introduce `SpinLock` Wedson Almeida Filho
2023-04-05 17:51 ` [PATCH v2 06/13] rust: lock: add support for `Lock::lock_irqsave` Wedson Almeida Filho
2023-04-05 17:51 ` [PATCH v2 07/13] rust: lock: implement `IrqSaveBackend` for `SpinLock` Wedson Almeida Filho
2023-04-05 17:51 ` [PATCH v2 08/13] rust: introduce `ARef` Wedson Almeida Filho
2023-04-07 21:59 ` Benno Lossin
2023-04-08 4:28 ` Wedson Almeida Filho
2023-04-05 17:51 ` [PATCH v2 09/13] rust: add basic `Task` Wedson Almeida Filho
2023-04-05 17:51 ` Wedson Almeida Filho [this message]
2023-04-07 22:36 ` [PATCH v2 10/13] rust: introduce `current` Benno Lossin
2023-04-08 3:54 ` Wedson Almeida Filho
2023-04-05 17:51 ` [PATCH v2 11/13] rust: lock: add `Guard::do_unlocked` Wedson Almeida Filho
2023-04-05 17:51 ` [PATCH v2 12/13] rust: sync: introduce `CondVar` Wedson Almeida Filho
2023-04-05 17:51 ` [PATCH v2 13/13] rust: sync: introduce `LockedBy` Wedson Almeida Filho
2023-04-07 21:00 ` Benno Lossin
2023-04-08 4:11 ` Wedson Almeida Filho
2023-04-08 7:52 ` Benno Lossin
2023-04-05 18:00 ` [PATCH v2 01/13] rust: sync: introduce `LockClassKey` Greg KH
2023-04-05 20:05 ` Wedson Almeida Filho
2023-04-05 20:21 ` Gary Guo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230405175111.5974-10-wedsonaf@gmail.com \
--to=wedsonaf@gmail.com \
--cc=alex.gaynor@gmail.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=gary@garyguo.net \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=ojeda@kernel.org \
--cc=peterz@infradead.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=walmeida@microsoft.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.