aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src/raw/trace.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-executor/src/raw/trace.rs')
-rw-r--r--embassy-executor/src/raw/trace.rs74
1 files changed, 72 insertions, 2 deletions
diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs
index eb960f721..b59da0526 100644
--- a/embassy-executor/src/raw/trace.rs
+++ b/embassy-executor/src/raw/trace.rs
@@ -82,11 +82,11 @@
82#![allow(unused)] 82#![allow(unused)]
83 83
84use core::cell::UnsafeCell; 84use core::cell::UnsafeCell;
85use core::sync::atomic::{AtomicUsize, Ordering}; 85use core::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
86 86
87use rtos_trace::TaskInfo; 87use rtos_trace::TaskInfo;
88 88
89use crate::raw::{SyncExecutor, TaskHeader, TaskRef, TaskTracker}; 89use crate::raw::{SyncExecutor, TaskHeader, TaskRef};
90use crate::spawner::{SpawnError, SpawnToken, Spawner}; 90use crate::spawner::{SpawnError, SpawnToken, Spawner};
91 91
92/// Extension trait adding tracing capabilities to the Spawner 92/// Extension trait adding tracing capabilities to the Spawner
@@ -139,6 +139,76 @@ impl TraceExt for Spawner {
139#[cfg(feature = "trace")] 139#[cfg(feature = "trace")]
140pub static TASK_TRACKER: TaskTracker = TaskTracker::new(); 140pub 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")]
148pub struct TaskTracker {
149 head: AtomicPtr<TaskHeader>,
150}
151
152#[cfg(feature = "trace")]
153impl 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#[cfg(not(feature = "rtos-trace"))] 212#[cfg(not(feature = "rtos-trace"))]
143extern "Rust" { 213extern "Rust" {
144 /// This callback is called when the executor begins polling. This will always 214 /// This callback is called when the executor begins polling. This will always