#![allow(unused)]
use core::cell::UnsafeCell;
use core::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
#[cfg(feature = "rtos-trace")]
use rtos_trace::TaskInfo;
use crate::raw::{SyncExecutor, TaskHeader, TaskRef};
use crate::spawner::{SpawnError, SpawnToken, Spawner};
#[cfg(feature = "rtos-trace")]
pub(crate) static TASK_TRACKER: TaskTracker = TaskTracker::new();
#[cfg(feature = "rtos-trace")]
pub(crate) struct TaskTracker {
head: AtomicPtr<TaskHeader>,
}
#[cfg(feature = "rtos-trace")]
impl TaskTracker {
pub const fn new() -> Self {
Self {
head: AtomicPtr::new(core::ptr::null_mut()),
}
}
pub fn add(&self, task: TaskRef) {
let task_ptr = task.as_ptr();
loop {
let current_head = self.head.load(Ordering::Acquire);
unsafe {
(*task_ptr).all_tasks_next.store(current_head, Ordering::Relaxed);
}
if self
.head
.compare_exchange(current_head, task_ptr.cast_mut(), Ordering::Release, Ordering::Relaxed)
.is_ok()
{
break;
}
}
}
pub fn for_each<F>(&self, mut f: F)
where
F: FnMut(TaskRef),
{
let mut current = self.head.load(Ordering::Acquire);
while !current.is_null() {
let task = unsafe { TaskRef::from_ptr(current) };
f(task);
current = unsafe { (*current).all_tasks_next.load(Ordering::Acquire) };
}
}
}
#[cfg(feature = "trace")]
unsafe extern "Rust" {
fn _embassy_trace_poll_start(executor_id: u32);
fn _embassy_trace_task_new(executor_id: u32, task_id: u32);
fn _embassy_trace_task_end(executor_id: u32, task_id: u32);
fn _embassy_trace_task_exec_begin(executor_id: u32, task_id: u32);
fn _embassy_trace_task_exec_end(excutor_id: u32, task_id: u32);
fn _embassy_trace_task_ready_begin(executor_id: u32, task_id: u32);
fn _embassy_trace_executor_idle(executor_id: u32);
}
#[inline]
pub(crate) fn poll_start(executor: &SyncExecutor) {
#[cfg(feature = "trace")]
unsafe {
_embassy_trace_poll_start(executor as *const _ as u32)
}
}
#[inline]
pub(crate) fn task_new(executor: &SyncExecutor, task: &TaskRef) {
#[cfg(feature = "trace")]
unsafe {
_embassy_trace_task_new(executor as *const _ as u32, task.as_ptr() as u32)
}
#[cfg(feature = "rtos-trace")]
{
rtos_trace::trace::task_new(task.as_ptr() as u32);
let name = task.metadata().name().unwrap_or("unnamed task\0");
let info = rtos_trace::TaskInfo {
name,
priority: 0,
stack_base: 0,
stack_size: 0,
};
rtos_trace::trace::task_send_info(task.id(), info);
}
#[cfg(feature = "rtos-trace")]
TASK_TRACKER.add(*task);
}
#[inline]
pub(crate) fn task_end(executor: *const SyncExecutor, task: &TaskRef) {
#[cfg(feature = "trace")]
unsafe {
_embassy_trace_task_end(executor as u32, task.as_ptr() as u32)
}
}
#[inline]
pub(crate) fn task_ready_begin(executor: &SyncExecutor, task: &TaskRef) {
#[cfg(feature = "trace")]
unsafe {
_embassy_trace_task_ready_begin(executor as *const _ as u32, task.as_ptr() as u32)
}
#[cfg(feature = "rtos-trace")]
rtos_trace::trace::task_ready_begin(task.as_ptr() as u32);
}
#[inline]
pub(crate) fn task_exec_begin(executor: &SyncExecutor, task: &TaskRef) {
#[cfg(feature = "trace")]
unsafe {
_embassy_trace_task_exec_begin(executor as *const _ as u32, task.as_ptr() as u32)
}
#[cfg(feature = "rtos-trace")]
rtos_trace::trace::task_exec_begin(task.as_ptr() as u32);
}
#[inline]
pub(crate) fn task_exec_end(executor: &SyncExecutor, task: &TaskRef) {
#[cfg(feature = "trace")]
unsafe {
_embassy_trace_task_exec_end(executor as *const _ as u32, task.as_ptr() as u32)
}
#[cfg(feature = "rtos-trace")]
rtos_trace::trace::task_exec_end();
}
#[inline]
pub(crate) fn executor_idle(executor: &SyncExecutor) {
#[cfg(feature = "trace")]
unsafe {
_embassy_trace_executor_idle(executor as *const _ as u32)
}
#[cfg(feature = "rtos-trace")]
rtos_trace::trace::system_idle();
}
#[cfg(feature = "rtos-trace")]
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),
}
}
#[cfg(feature = "rtos-trace")]
fn with_all_active_tasks<F>(f: F)
where
F: FnMut(TaskRef),
{
TASK_TRACKER.for_each(f);
}
#[cfg(feature = "rtos-trace")]
impl rtos_trace::RtosTraceOSCallbacks for crate::raw::SyncExecutor {
fn task_list() {
with_all_active_tasks(|task| {
let info = rtos_trace::TaskInfo {
name: task.metadata().name().unwrap_or("unnamed task\0"),
priority: 0,
stack_base: 0,
stack_size: 0,
};
rtos_trace::trace::task_send_info(task.id(), info);
});
}
fn time() -> u64 {
const fn gcd(a: u64, b: u64) -> u64 {
if b == 0 { a } else { gcd(b, a % b) }
}
const GCD_1M: u64 = gcd(embassy_time_driver::TICK_HZ, 1_000_000);
embassy_time_driver::now() * (1_000_000 / GCD_1M) / (embassy_time_driver::TICK_HZ / GCD_1M)
}
}
#[cfg(feature = "rtos-trace")]
rtos_trace::global_os_callbacks! {SyncExecutor}