Skip to main content

strat9_kernel/ostd/
task.rs

1//! Task abstraction layer
2//!
3//! Provides safe abstractions for task/thread operations including:
4//! - Task reference counting
5//! - Task context access
6//! - Task lifecycle management
7//!
8//! Inspired by Theseus Task and Asterinas thread abstractions.
9
10#![allow(unsafe_code)]
11
12extern crate alloc;
13
14use alloc::sync::Arc;
15use core::sync::atomic::{AtomicU32, AtomicUsize, Ordering};
16
17/// Unique task identifier
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
19#[repr(transparent)]
20pub struct TaskId(u32);
21
22impl TaskId {
23    /// Creates a new TaskId
24    pub const fn new(id: u32) -> Self {
25        Self(id)
26    }
27
28    /// Returns the raw ID value
29    pub const fn as_u32(&self) -> u32 {
30        self.0
31    }
32
33    /// Returns the raw ID value as usize
34    pub const fn as_usize(&self) -> usize {
35        self.0 as usize
36    }
37}
38
39impl From<u32> for TaskId {
40    /// Performs the from operation.
41    fn from(id: u32) -> Self {
42        Self::new(id)
43    }
44}
45
46impl From<TaskId> for u32 {
47    /// Performs the from operation.
48    fn from(id: TaskId) -> u32 {
49        id.0
50    }
51}
52
53impl core::fmt::Display for TaskId {
54    /// Performs the fmt operation.
55    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
56        write!(f, "Task #{}", self.0)
57    }
58}
59
60/// Task state enumeration
61#[derive(Debug, Clone, Copy, PartialEq, Eq)]
62pub enum TaskState {
63    /// Task is runnable
64    Runnable,
65    /// Task is blocked/sleeping
66    Blocked,
67    /// Task is sleeping
68    Sleeping,
69    /// Task is stopped
70    Stopped,
71    /// Task is exiting
72    Exiting,
73    /// Task is idle
74    Idle,
75}
76
77/// Reference-counted task handle
78///
79/// Similar to Theseus's TaskRef, this provides safe reference counting
80/// for task structures.
81pub struct TaskRef {
82    /// Raw task pointer (must be valid for the lifetime of the process)
83    task_ptr: *mut TaskInner,
84    /// Reference count tracker
85    ref_count: Arc<AtomicUsize>,
86}
87
88// SAFETY: TaskRef can be sent between threads if the underlying task supports it
89unsafe impl Send for TaskRef {}
90// SAFETY: TaskRef can be shared between threads
91unsafe impl Sync for TaskRef {}
92
93impl TaskRef {
94    /// Creates a new TaskRef from a raw task pointer
95    ///
96    /// # Safety
97    ///
98    /// - The task_ptr must be valid for the lifetime of the process
99    /// - The caller must ensure proper synchronization
100    pub unsafe fn new(task_ptr: *mut TaskInner) -> Self {
101        Self {
102            task_ptr,
103            ref_count: Arc::new(AtomicUsize::new(1)),
104        }
105    }
106
107    /// Returns a reference to the inner task
108    ///
109    /// # Safety
110    ///
111    /// The caller must ensure the task is still valid
112    pub unsafe fn as_ref(&self) -> &TaskInner {
113        &*self.task_ptr
114    }
115
116    /// Returns a mutable reference to the inner task
117    ///
118    /// # Safety
119    ///
120    /// The caller must ensure exclusive access to the task
121    pub unsafe fn as_mut(&mut self) -> &mut TaskInner {
122        &mut *self.task_ptr
123    }
124
125    /// Clones the TaskRef
126    pub fn clone(&self) -> Self {
127        self.ref_count.fetch_add(1, Ordering::Relaxed);
128        Self {
129            task_ptr: self.task_ptr,
130            ref_count: Arc::clone(&self.ref_count),
131        }
132    }
133
134    /// Returns the reference count
135    pub fn ref_count(&self) -> usize {
136        self.ref_count.load(Ordering::Relaxed)
137    }
138
139    /// Returns true if this is the last reference
140    pub fn is_last_ref(&self) -> bool {
141        self.ref_count.load(Ordering::Relaxed) == 1
142    }
143}
144
145impl Drop for TaskRef {
146    /// Performs the drop operation.
147    fn drop(&mut self) {
148        if self.ref_count.fetch_sub(1, Ordering::Release) == 1 {
149            // Last reference - task can be cleaned up
150            // SAFETY: We're the last reference, so we can safely access the task
151            unsafe {
152                (*self.task_ptr).on_last_ref();
153            }
154        }
155    }
156}
157
158impl Clone for TaskRef {
159    /// Performs the clone operation.
160    fn clone(&self) -> Self {
161        self.clone()
162    }
163}
164
165/// Internal task structure
166///
167/// Contains the core task data that is shared via TaskRef.
168pub struct TaskInner {
169    /// Task ID
170    id: TaskId,
171    /// Task name
172    name: spin::Mutex<Option<alloc::string::String>>,
173    /// Task state
174    state: AtomicU32,
175    /// CPU affinity (which CPUs this task can run on)
176    cpu_affinity: AtomicUsize,
177    /// Priority (lower = higher priority)
178    priority: AtomicU32,
179}
180
181impl TaskInner {
182    /// Creates a new TaskInner
183    pub fn new(id: TaskId) -> Self {
184        Self {
185            id,
186            name: spin::Mutex::new(None),
187            state: AtomicU32::new(TaskState::Runnable as u32),
188            cpu_affinity: AtomicUsize::new(usize::MAX), // All CPUs
189            priority: AtomicU32::new(0),
190        }
191    }
192
193    /// Returns the task ID
194    pub fn id(&self) -> TaskId {
195        self.id
196    }
197
198    /// Returns the task name
199    pub fn name(&self) -> Option<alloc::string::String> {
200        self.name.lock().clone()
201    }
202
203    /// Sets the task name
204    pub fn set_name(&self, name: alloc::string::String) {
205        *self.name.lock() = Some(name);
206    }
207
208    /// Returns the current task state
209    pub fn state(&self) -> TaskState {
210        match self.state.load(Ordering::Relaxed) {
211            0 => TaskState::Runnable,
212            1 => TaskState::Blocked,
213            2 => TaskState::Sleeping,
214            3 => TaskState::Stopped,
215            4 => TaskState::Exiting,
216            5 => TaskState::Idle,
217            _ => TaskState::Runnable,
218        }
219    }
220
221    /// Sets the task state
222    pub fn set_state(&self, state: TaskState) {
223        self.state.store(state as u32, Ordering::Relaxed);
224    }
225
226    /// Returns the CPU affinity mask
227    pub fn cpu_affinity(&self) -> usize {
228        self.cpu_affinity.load(Ordering::Relaxed)
229    }
230
231    /// Sets the CPU affinity mask
232    pub fn set_cpu_affinity(&self, mask: usize) {
233        self.cpu_affinity.store(mask, Ordering::Relaxed);
234    }
235
236    /// Returns the task priority
237    pub fn priority(&self) -> u32 {
238        self.priority.load(Ordering::Relaxed)
239    }
240
241    /// Sets the task priority
242    pub fn set_priority(&self, priority: u32) {
243        self.priority.store(priority, Ordering::Relaxed);
244    }
245
246    /// Called when the last TaskRef is dropped
247    ///
248    /// Override this in implementations to handle cleanup.
249    pub fn on_last_ref(&self) {
250        // Default: do nothing
251        // Implementations should override to free resources
252    }
253}
254
255/// Gets the current task
256///
257/// Returns None if called before the task system is initialized.
258pub fn current_task() -> Option<TaskRef> {
259    // TODO: Integrate with the actual process/task system
260    // For now, return None as a placeholder
261    None
262}
263
264/// Task options for spawning new tasks
265pub struct TaskOptions {
266    name: Option<alloc::string::String>,
267    cpu_affinity: Option<usize>,
268    priority: Option<u32>,
269}
270
271impl TaskOptions {
272    /// Creates new task options with default values
273    pub fn new() -> Self {
274        Self {
275            name: None,
276            cpu_affinity: None,
277            priority: None,
278        }
279    }
280
281    /// Sets the task name
282    pub fn name(mut self, name: alloc::string::String) -> Self {
283        self.name = Some(name);
284        self
285    }
286
287    /// Sets the CPU affinity
288    pub fn cpu_affinity(mut self, affinity: usize) -> Self {
289        self.cpu_affinity = Some(affinity);
290        self
291    }
292
293    /// Sets the task priority
294    pub fn priority(mut self, priority: u32) -> Self {
295        self.priority = Some(priority);
296        self
297    }
298}
299
300impl Default for TaskOptions {
301    /// Builds a default instance.
302    fn default() -> Self {
303        Self::new()
304    }
305}