|
82 | 82 | #![allow(unused)]
|
83 | 83 |
|
84 | 84 | use core::cell::UnsafeCell;
|
85 |
| -use core::sync::atomic::{AtomicUsize, Ordering}; |
| 85 | +use core::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; |
86 | 86 |
|
87 | 87 | use rtos_trace::TaskInfo;
|
88 | 88 |
|
89 |
| -use crate::raw::{SyncExecutor, TaskHeader, TaskRef, TaskTracker}; |
| 89 | +use crate::raw::{SyncExecutor, TaskHeader, TaskRef}; |
90 | 90 | use crate::spawner::{SpawnError, SpawnToken, Spawner};
|
91 | 91 |
|
92 | 92 | /// Extension trait adding tracing capabilities to the Spawner
|
@@ -139,6 +139,76 @@ impl TraceExt for Spawner {
|
139 | 139 | #[cfg(feature = "trace")]
|
140 | 140 | pub static TASK_TRACKER: TaskTracker = TaskTracker::new();
|
141 | 141 |
|
| 142 | +/// A thread-safe tracker for all tasks in the system |
| 143 | +/// |
| 144 | +/// This struct uses an intrusive linked list approach to track all tasks |
| 145 | +/// without additional memory allocations. It maintains a global list of |
| 146 | +/// tasks that can be traversed to find all currently existing tasks. |
| 147 | +#[cfg(feature = "trace")] |
| 148 | +pub struct TaskTracker { |
| 149 | + head: AtomicPtr<TaskHeader>, |
| 150 | +} |
| 151 | + |
| 152 | +#[cfg(feature = "trace")] |
| 153 | +impl TaskTracker { |
| 154 | + /// Creates a new empty task tracker |
| 155 | + /// |
| 156 | + /// Initializes a tracker with no tasks in its list. |
| 157 | + pub const fn new() -> Self { |
| 158 | + Self { |
| 159 | + head: AtomicPtr::new(core::ptr::null_mut()), |
| 160 | + } |
| 161 | + } |
| 162 | + |
| 163 | + /// Adds a task to the tracker |
| 164 | + /// |
| 165 | + /// This method inserts a task at the head of the intrusive linked list. |
| 166 | + /// The operation is thread-safe and lock-free, using atomic operations |
| 167 | + /// to ensure consistency even when called from different contexts. |
| 168 | + /// |
| 169 | + /// # Arguments |
| 170 | + /// * `task` - The task reference to add to the tracker |
| 171 | + pub fn add(&self, task: TaskRef) { |
| 172 | + let task_ptr = task.as_ptr() as *mut TaskHeader; |
| 173 | + |
| 174 | + loop { |
| 175 | + let current_head = self.head.load(Ordering::Acquire); |
| 176 | + unsafe { |
| 177 | + (*task_ptr).all_tasks_next.store(current_head, Ordering::Relaxed); |
| 178 | + } |
| 179 | + |
| 180 | + if self |
| 181 | + .head |
| 182 | + .compare_exchange(current_head, task_ptr, Ordering::Release, Ordering::Relaxed) |
| 183 | + .is_ok() |
| 184 | + { |
| 185 | + break; |
| 186 | + } |
| 187 | + } |
| 188 | + } |
| 189 | + |
| 190 | + /// Performs an operation on each task in the tracker |
| 191 | + /// |
| 192 | + /// This method traverses the entire list of tasks and calls the provided |
| 193 | + /// function for each task. This allows inspecting or processing all tasks |
| 194 | + /// in the system without modifying the tracker's structure. |
| 195 | + /// |
| 196 | + /// # Arguments |
| 197 | + /// * `f` - A function to call for each task in the tracker |
| 198 | + pub fn for_each<F>(&self, mut f: F) |
| 199 | + where |
| 200 | + F: FnMut(TaskRef), |
| 201 | + { |
| 202 | + let mut current = self.head.load(Ordering::Acquire); |
| 203 | + while !current.is_null() { |
| 204 | + let task = unsafe { TaskRef::from_ptr(current) }; |
| 205 | + f(task); |
| 206 | + |
| 207 | + current = unsafe { (*current).all_tasks_next.load(Ordering::Acquire) }; |
| 208 | + } |
| 209 | + } |
| 210 | +} |
| 211 | + |
142 | 212 | #[cfg(not(feature = "rtos-trace"))]
|
143 | 213 | extern "Rust" {
|
144 | 214 | /// This callback is called when the executor begins polling. This will always
|
|
0 commit comments