5
5
//! C header: [`include/linux/sched.h`](../../../../include/linux/sched.h).
6
6
7
7
use crate :: { bindings, types:: Opaque } ;
8
- use core:: ptr;
8
+ use core:: { marker:: PhantomData , ops:: Deref , ptr} ;
9
+
10
+ /// Returns the currently running task.
11
+ #[ macro_export]
12
+ macro_rules! current {
13
+ ( ) => {
14
+ // SAFETY: Deref + addr-of below create a temporary `TaskRef` that cannot outlive the
15
+ // caller.
16
+ unsafe { & * $crate:: task:: Task :: current( ) }
17
+ } ;
18
+ }
9
19
10
20
/// Wraps the kernel's `struct task_struct`.
11
21
///
@@ -15,6 +25,42 @@ use core::ptr;
15
25
///
16
26
/// Instances of this type are always ref-counted, that is, a call to `get_task_struct` ensures
17
27
/// that the allocation remains valid at least until the matching call to `put_task_struct`.
28
+ ///
29
+ /// # Examples
30
+ ///
31
+ /// The following is an example of getting the PID of the current thread with zero additional cost
32
+ /// when compared to the C version:
33
+ ///
34
+ /// ```
35
+ /// let pid = current!().pid();
36
+ /// ```
37
+ ///
38
+ /// Getting the PID of the current process, also zero additional cost:
39
+ ///
40
+ /// ```
41
+ /// let pid = current!().group_leader().pid();
42
+ /// ```
43
+ ///
44
+ /// Getting the current task and storing it in some struct. The reference count is automatically
45
+ /// incremented when creating `State` and decremented when it is dropped:
46
+ ///
47
+ /// ```
48
+ /// use kernel::{task::Task, types::ARef};
49
+ ///
50
+ /// struct State {
51
+ /// creator: ARef<Task>,
52
+ /// index: u32,
53
+ /// }
54
+ ///
55
+ /// impl State {
56
+ /// fn new() -> Self {
57
+ /// Self {
58
+ /// creator: current!().into(),
59
+ /// index: 0,
60
+ /// }
61
+ /// }
62
+ /// }
63
+ /// ```
18
64
#[ repr( transparent) ]
19
65
pub struct Task ( pub ( crate ) Opaque < bindings:: task_struct > ) ;
20
66
@@ -27,6 +73,46 @@ unsafe impl Sync for Task {}
27
73
type Pid = bindings:: pid_t ;
28
74
29
75
impl Task {
76
+ /// Returns a task reference for the currently executing task/thread.
77
+ ///
78
+ /// The recommended way to get the current task/thread is to use the
79
+ /// [`current`](crate::current) macro because it is safe.
80
+ ///
81
+ /// # Safety
82
+ ///
83
+ /// Callers must ensure that the returned object doesn't outlive the current task/thread.
84
+ pub unsafe fn current ( ) -> impl Deref < Target = Task > {
85
+ pub struct TaskRef < ' a > {
86
+ task : & ' a Task ,
87
+ _not_send : PhantomData < * mut ( ) > ,
88
+ }
89
+
90
+ impl Deref for TaskRef < ' _ > {
91
+ type Target = Task ;
92
+
93
+ fn deref ( & self ) -> & Self :: Target {
94
+ self . task
95
+ }
96
+ }
97
+
98
+ impl From < TaskRef < ' _ > > for crate :: types:: ARef < Task > {
99
+ fn from ( t : TaskRef < ' _ > ) -> Self {
100
+ t. deref ( ) . into ( )
101
+ }
102
+ }
103
+
104
+ // SAFETY: Just an FFI call with no additional safety requirements.
105
+ let ptr = unsafe { bindings:: get_current ( ) } ;
106
+
107
+ TaskRef {
108
+ // SAFETY: If the current thread is still running, the current task is valid. Given
109
+ // that `TaskRef` is not `Send`, we know it cannot be transferred to another thread
110
+ // (where it could potentially outlive the caller).
111
+ task : unsafe { & * ptr. cast ( ) } ,
112
+ _not_send : PhantomData ,
113
+ }
114
+ }
115
+
30
116
/// Returns the group leader of the given task.
31
117
pub fn group_leader ( & self ) -> & Task {
32
118
// SAFETY: By the type invariant, we know that `self.0` is a valid task. Valid tasks always
0 commit comments