1*313c4281SWedson Almeida Filho // SPDX-License-Identifier: GPL-2.0 2*313c4281SWedson Almeida Filho 3*313c4281SWedson Almeida Filho //! Tasks (threads and processes). 4*313c4281SWedson Almeida Filho //! 5*313c4281SWedson Almeida Filho //! C header: [`include/linux/sched.h`](../../../../include/linux/sched.h). 6*313c4281SWedson Almeida Filho 7*313c4281SWedson Almeida Filho use crate::{bindings, types::Opaque}; 8*313c4281SWedson Almeida Filho use core::ptr; 9*313c4281SWedson Almeida Filho 10*313c4281SWedson Almeida Filho /// Wraps the kernel's `struct task_struct`. 11*313c4281SWedson Almeida Filho /// 12*313c4281SWedson Almeida Filho /// # Invariants 13*313c4281SWedson Almeida Filho /// 14*313c4281SWedson Almeida Filho /// All instances are valid tasks created by the C portion of the kernel. 15*313c4281SWedson Almeida Filho /// 16*313c4281SWedson Almeida Filho /// Instances of this type are always ref-counted, that is, a call to `get_task_struct` ensures 17*313c4281SWedson Almeida Filho /// that the allocation remains valid at least until the matching call to `put_task_struct`. 18*313c4281SWedson Almeida Filho #[repr(transparent)] 19*313c4281SWedson Almeida Filho pub struct Task(pub(crate) Opaque<bindings::task_struct>); 20*313c4281SWedson Almeida Filho 21*313c4281SWedson Almeida Filho // SAFETY: It's OK to access `Task` through references from other threads because we're either 22*313c4281SWedson Almeida Filho // accessing properties that don't change (e.g., `pid`, `group_leader`) or that are properly 23*313c4281SWedson Almeida Filho // synchronised by C code (e.g., `signal_pending`). 24*313c4281SWedson Almeida Filho unsafe impl Sync for Task {} 25*313c4281SWedson Almeida Filho 26*313c4281SWedson Almeida Filho /// The type of process identifiers (PIDs). 27*313c4281SWedson Almeida Filho type Pid = bindings::pid_t; 28*313c4281SWedson Almeida Filho 29*313c4281SWedson Almeida Filho impl Task { 30*313c4281SWedson Almeida Filho /// Returns the group leader of the given task. 31*313c4281SWedson Almeida Filho pub fn group_leader(&self) -> &Task { 32*313c4281SWedson Almeida Filho // SAFETY: By the type invariant, we know that `self.0` is a valid task. Valid tasks always 33*313c4281SWedson Almeida Filho // have a valid group_leader. 34*313c4281SWedson Almeida Filho let ptr = unsafe { *ptr::addr_of!((*self.0.get()).group_leader) }; 35*313c4281SWedson Almeida Filho 36*313c4281SWedson Almeida Filho // SAFETY: The lifetime of the returned task reference is tied to the lifetime of `self`, 37*313c4281SWedson Almeida Filho // and given that a task has a reference to its group leader, we know it must be valid for 38*313c4281SWedson Almeida Filho // the lifetime of the returned task reference. 39*313c4281SWedson Almeida Filho unsafe { &*ptr.cast() } 40*313c4281SWedson Almeida Filho } 41*313c4281SWedson Almeida Filho 42*313c4281SWedson Almeida Filho /// Returns the PID of the given task. 43*313c4281SWedson Almeida Filho pub fn pid(&self) -> Pid { 44*313c4281SWedson Almeida Filho // SAFETY: By the type invariant, we know that `self.0` is a valid task. Valid tasks always 45*313c4281SWedson Almeida Filho // have a valid pid. 46*313c4281SWedson Almeida Filho unsafe { *ptr::addr_of!((*self.0.get()).pid) } 47*313c4281SWedson Almeida Filho } 48*313c4281SWedson Almeida Filho 49*313c4281SWedson Almeida Filho /// Determines whether the given task has pending signals. 50*313c4281SWedson Almeida Filho pub fn signal_pending(&self) -> bool { 51*313c4281SWedson Almeida Filho // SAFETY: By the type invariant, we know that `self.0` is valid. 52*313c4281SWedson Almeida Filho unsafe { bindings::signal_pending(self.0.get()) != 0 } 53*313c4281SWedson Almeida Filho } 54*313c4281SWedson Almeida Filho 55*313c4281SWedson Almeida Filho /// Wakes up the task. 56*313c4281SWedson Almeida Filho pub fn wake_up(&self) { 57*313c4281SWedson Almeida Filho // SAFETY: By the type invariant, we know that `self.0.get()` is non-null and valid. 58*313c4281SWedson Almeida Filho // And `wake_up_process` is safe to be called for any valid task, even if the task is 59*313c4281SWedson Almeida Filho // running. 60*313c4281SWedson Almeida Filho unsafe { bindings::wake_up_process(self.0.get()) }; 61*313c4281SWedson Almeida Filho } 62*313c4281SWedson Almeida Filho } 63*313c4281SWedson Almeida Filho 64*313c4281SWedson Almeida Filho // SAFETY: The type invariants guarantee that `Task` is always ref-counted. 65*313c4281SWedson Almeida Filho unsafe impl crate::types::AlwaysRefCounted for Task { 66*313c4281SWedson Almeida Filho fn inc_ref(&self) { 67*313c4281SWedson Almeida Filho // SAFETY: The existence of a shared reference means that the refcount is nonzero. 68*313c4281SWedson Almeida Filho unsafe { bindings::get_task_struct(self.0.get()) }; 69*313c4281SWedson Almeida Filho } 70*313c4281SWedson Almeida Filho 71*313c4281SWedson Almeida Filho unsafe fn dec_ref(obj: ptr::NonNull<Self>) { 72*313c4281SWedson Almeida Filho // SAFETY: The safety requirements guarantee that the refcount is nonzero. 73*313c4281SWedson Almeida Filho unsafe { bindings::put_task_struct(obj.cast().as_ptr()) } 74*313c4281SWedson Almeida Filho } 75*313c4281SWedson Almeida Filho } 76