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 v3 10/13] rust: introduce `current`
Date: Sat, 8 Apr 2023 04:53:37 -0300 [thread overview]
Message-ID: <20230408075340.25237-10-wedsonaf@gmail.com> (raw)
In-Reply-To: <20230408075340.25237-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
v2 -> v3:
- Mention `current` macro in `Task::current`
- Hide implementation of `TaskRef` inside `Task::current`
rust/helpers.c | 6 +++
rust/kernel/prelude.rs | 2 +
rust/kernel/task.rs | 88 +++++++++++++++++++++++++++++++++++++++++-
3 files changed, 95 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 d70cad131956..5269a562cb1b 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, types::Opaque};
-use core::ptr;
+use core::{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`.
///
@@ -15,6 +25,42 @@ use core::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) Opaque<bindings::task_struct>);
@@ -27,6 +73,46 @@ unsafe impl Sync for Task {}
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`](crate::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> {
+ 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()
+ }
+ }
+
+ // 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 a valid task. Valid tasks always
--
2.34.1
next prev parent reply other threads:[~2023-04-08 7:55 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-08 7:53 [PATCH v3 01/13] rust: sync: introduce `LockClassKey` Wedson Almeida Filho
2023-04-08 7:53 ` [PATCH v3 02/13] rust: sync: introduce `Lock` and `Guard` Wedson Almeida Filho
2023-04-09 16:47 ` Martin Rodriguez Reboredo
2023-04-11 3:01 ` Wedson Almeida Filho
2023-04-08 7:53 ` [PATCH v3 03/13] rust: lock: introduce `Mutex` Wedson Almeida Filho
2023-04-09 16:47 ` Martin Rodriguez Reboredo
2023-04-08 7:53 ` [PATCH v3 04/13] locking/spinlock: introduce spin_lock_init_with_key Wedson Almeida Filho
2023-04-09 16:47 ` Martin Rodriguez Reboredo
2023-04-08 7:53 ` [PATCH v3 05/13] rust: lock: introduce `SpinLock` Wedson Almeida Filho
2023-04-09 16:48 ` Martin Rodriguez Reboredo
2023-04-08 7:53 ` [PATCH v3 06/13] rust: lock: add support for `Lock::lock_irqsave` Wedson Almeida Filho
2023-04-09 16:48 ` Martin Rodriguez Reboredo
2023-04-08 7:53 ` [PATCH v3 07/13] rust: lock: implement `IrqSaveBackend` for `SpinLock` Wedson Almeida Filho
2023-04-09 16:48 ` Martin Rodriguez Reboredo
2023-04-08 7:53 ` [PATCH v3 08/13] rust: introduce `ARef` Wedson Almeida Filho
2023-04-09 16:48 ` Martin Rodriguez Reboredo
2023-04-08 7:53 ` [PATCH v3 09/13] rust: add basic `Task` Wedson Almeida Filho
2023-04-09 16:48 ` Martin Rodriguez Reboredo
2023-04-08 7:53 ` Wedson Almeida Filho [this message]
2023-04-09 16:48 ` [PATCH v3 10/13] rust: introduce `current` Martin Rodriguez Reboredo
2023-04-10 18:04 ` Benno Lossin
2023-04-11 3:08 ` Wedson Almeida Filho
2023-04-08 7:53 ` [PATCH v3 11/13] rust: lock: add `Guard::do_unlocked` Wedson Almeida Filho
2023-04-09 16:49 ` Martin Rodriguez Reboredo
2023-04-08 7:53 ` [PATCH v3 12/13] rust: sync: introduce `CondVar` Wedson Almeida Filho
2023-04-09 16:49 ` Martin Rodriguez Reboredo
2023-04-11 2:59 ` Wedson Almeida Filho
2023-04-08 7:53 ` [PATCH v3 13/13] rust: sync: introduce `LockedBy` Wedson Almeida Filho
2023-04-09 16:49 ` Martin Rodriguez Reboredo
2023-04-10 17:46 ` Boqun Feng
2023-04-10 18:13 ` Boqun Feng
2023-04-10 19:52 ` Benno Lossin
2023-04-11 2:57 ` Wedson Almeida Filho
2023-04-09 16:46 ` [PATCH v3 01/13] rust: sync: introduce `LockClassKey` Martin Rodriguez Reboredo
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=20230408075340.25237-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.