Skip to main content

ax_runtime/thread/lifecycle/
mod.rs

1use alloc::sync::Arc;
2use core::sync::atomic::AtomicU8;
3
4use super::*;
5
6const THREAD_START_PENDING: u8 = 0;
7const THREAD_START_ACTIVE: u8 = 1;
8const THREAD_START_ABORTED: u8 = 2;
9
10/// Scheduler thread whose resources and registry identity exist but which is
11/// not yet runnable.
12///
13/// OS layers use this move-only transaction boundary to finish private resource
14/// construction. They must call [`Self::stage`] before publishing externally
15/// visible task identity, then call [`StagedThread::activate`] after committing
16/// that identity. Dropping an unpublished value removes the scheduler record
17/// and releases context, stack, TLS, extension, and address-space resources in
18/// task context.
19pub struct PreparedThread {
20    system: &'static TaskSystem,
21    handle: Option<ThreadHandle>,
22    start: Arc<RuntimeThreadStart>,
23}
24
25/// Scheduler thread placed on a run queue but not yet activated by its OS.
26///
27/// This transaction token must be activated or dropped from task context.
28/// Completing either path wakes the staged trampoline through a task-context
29/// wait queue and is therefore not valid in a hard-interrupt handler.
30#[must_use = "staged threads must be activated or explicitly dropped to abort"]
31pub struct StagedThread {
32    handle: Option<ThreadHandle>,
33    start: Arc<RuntimeThreadStart>,
34}
35
36type KernelThreadEntry = Box<dyn FnOnce() + Send + 'static>;
37
38#[derive(Debug)]
39pub(super) struct RuntimeThreadStart {
40    state: AtomicU8,
41    wait: WaitQueue,
42}
43
44pub(super) struct RuntimeThreadData {
45    pub(super) entry: crate::task::sync::SpinLock<Option<KernelThreadEntry>>,
46    pub(super) exit_code: AtomicI32,
47    pub(super) exit_completed: AtomicBool,
48    pub(super) join_wait: WaitQueue,
49    pub(super) os_extension: Option<ThreadExtension>,
50    pub(super) start: Arc<RuntimeThreadStart>,
51    pub(super) _name: String,
52}
53
54/// OS extension borrowed through the runtime's outer scheduler extension.
55#[derive(Debug)]
56pub struct ThreadOsExtensionBorrow<'thread> {
57    _runtime: ax_task::thread::ThreadExtensionBorrow<'thread>,
58    data: usize,
59    ops: &'static ThreadExtensionOps,
60}
61
62impl ThreadOsExtensionBorrow<'_> {
63    /// Returns the OS-owned opaque value.
64    pub const fn data(&self) -> usize {
65        self.data
66    }
67
68    /// Returns the callback table used as the OS extension type identity.
69    pub const fn ops(&self) -> &'static ThreadExtensionOps {
70        self.ops
71    }
72}
73
74/// OS extension lease for current-thread lookups without an existing handle.
75#[derive(Debug)]
76pub struct ThreadOsExtensionLease {
77    _runtime: ax_task::thread::ThreadExtensionLease,
78    data: usize,
79    ops: &'static ThreadExtensionOps,
80}
81
82impl ThreadOsExtensionLease {
83    /// Returns the OS-owned opaque value.
84    pub const fn data(&self) -> usize {
85        self.data
86    }
87
88    /// Returns the callback table used as the OS extension type identity.
89    pub const fn ops(&self) -> &'static ThreadExtensionOps {
90        self.ops
91    }
92}
93
94impl RuntimeThreadData {
95    pub(super) fn new(
96        entry: KernelThreadEntry,
97        name: String,
98        os_extension: Option<ThreadExtension>,
99        start: Arc<RuntimeThreadStart>,
100    ) -> Self {
101        Self {
102            entry: crate::task::sync::SpinLock::new(Some(entry)),
103            exit_code: AtomicI32::new(0),
104            exit_completed: AtomicBool::new(false),
105            join_wait: WaitQueue::new(),
106            os_extension,
107            start,
108            _name: name,
109        }
110    }
111}
112
113mod completion;
114mod extension;
115mod publication;
116
117#[cfg(test)]
118pub(in crate::thread) use completion::extension_data_after_releasing_lease;
119pub use completion::{exit_current, join_thread, wait_thread};
120pub(in crate::thread) use completion::{
121    finish_initial_scheduler_switch, release_transferred_extension, runtime_thread_entry,
122};
123pub(in crate::thread) use extension::{RUNTIME_THREAD_EXTENSION_OPS, runtime_thread_extension};
124#[cfg(test)]
125pub(in crate::thread) use extension::{RuntimeExtensionKind, classify_runtime_extension};
126pub use extension::{current_os_extension, thread_os_extension};