Skip to content

[trace]: Add task naming capability to tracing infrastructure #4147

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: main
Choose a base branch
from

Conversation

kat-perez
Copy link

@kat-perez kat-perez commented Apr 29, 2025

This change adds a TaskTracker to the tracing infrastructure. The name and ID of a task are now stored in TaskHeader and a new function called spawn_named is added to assign a name to the task for viewing in SystemView.

///
/// Contains the task's unique identifier and optional name.
#[derive(Clone)]
pub struct TrackedTask {
Copy link
Contributor

@bugadani bugadani Apr 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll have a better chance with this PR if you store this data in the task headers, instead of wasting 12-16K RAM.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bugadani Thanks for the review. I've updated my implementation to move the task information to TaskHeader and have used a LinkedList instead to keep track of all active tasks.

@kat-perez kat-perez requested a review from bugadani May 6, 2025 15:56
@kat-perez kat-perez changed the title add a task registry to tracing infrastructure feat(tracing): Add task naming capability to tracing infrastructure May 7, 2025
Copy link
Member

@lulf lulf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good in general, I've left some comments on the API.

Also, would it make sense to move more of this into the 'trace.rs'?

///
/// # Returns
/// Result indicating whether the spawn was successful
#[cfg(feature = "rtos-trace")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this should be feature = "trace" ?


/// When rtos-trace is disabled, spawn_named falls back to regular spawn.
/// This maintains API compatibility while optimizing out the name parameter.
#[cfg(not(feature = "rtos-trace"))]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this should be feature = "trace" ?

Comment on lines 242 to 305
pub fn get_all_active_tasks() -> impl Iterator<Item = TaskRef> + 'static {
struct TaskIterator<'a> {
tracker: &'a TaskTracker,
current: *mut TaskHeader,
}

impl<'a> Iterator for TaskIterator<'a> {
type Item = TaskRef;

fn next(&mut self) -> Option<Self::Item> {
if self.current.is_null() {
return None;
}

let task = unsafe { TaskRef::from_ptr(self.current) };
self.current = unsafe { (*self.current).all_tasks_next.load(Ordering::Acquire) };

Some(task)
}
}

TaskIterator {
tracker: &TASK_TRACKER,
current: TASK_TRACKER.head.load(Ordering::Acquire),
}
}

/// Get all active tasks, filtered by a predicate function
#[cfg(feature = "trace")]
pub fn filter_active_tasks<F>(predicate: F) -> impl Iterator<Item = TaskRef> + 'static
where
F: Fn(&TaskRef) -> bool + 'static,
{
get_all_active_tasks().filter(move |task| predicate(task))
}

/// Count the number of active tasks
#[cfg(feature = "trace")]
pub fn count_active_tasks() -> usize {
let mut count = 0;
TASK_TRACKER.for_each(|_| count += 1);
count
}

/// Perform an action on each active task
#[cfg(feature = "trace")]
pub fn with_all_active_tasks<F>(f: F)
where
F: FnMut(TaskRef),
{
TASK_TRACKER.for_each(f);
}

/// Get tasks by name
#[cfg(feature = "trace")]
pub fn get_tasks_by_name(name: &'static str) -> impl Iterator<Item = TaskRef> + 'static {
filter_active_tasks(move |task| task.name() == Some(name))
}

/// Get tasks by ID
#[cfg(feature = "trace")]
pub fn get_task_by_id(id: u32) -> Option<TaskRef> {
filter_active_tasks(move |task| task.id() == id).next()
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does these need to be public, or can they be internal? I'm a bit confused by the 'scattered' API, which makes it a bit hard to verify that it's all safe.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They can be internal. I will change them to private and update the unused public functions instead.

@jamesmunns
Copy link
Contributor

I do want to take a look at this, if we end up merging #4035, it might make sense to re-use cordyceps for the intrusive linked list of (named) tasks

@kat-perez
Copy link
Author

@lulf

Also, would it make sense to move more of this into the 'trace.rs'?

Yeah, I can define a trait instead in trace.rs which extends Spawner since the spawn_named function is used exclusively for SystemView at the moment

@kat-perez kat-perez changed the title feat(tracing): Add task naming capability to tracing infrastructure [trace]: Add task naming capability to tracing infrastructure May 8, 2025
@kat-perez
Copy link
Author

@lulf @jamesmunns Updated PR to move more of the functionality into trace.rs, please review. Thanks!

@kat-perez kat-perez requested a review from lulf May 8, 2025 21:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants