diff options
author | 2022-06-10 20:08:46 +0200 | |
---|---|---|
committer | 2022-08-03 11:30:32 +0200 | |
commit | b2ec1fa65118813b400cf806e3ff492ea41f49ca (patch) | |
tree | a9e9e71a7f696ad2832392054af12cc0019756d7 /macros/src/codegen | |
parent | 13ccd92e630e2d2a477b5062a995a0fb1a2b7a28 (diff) | |
download | rtic-b2ec1fa65118813b400cf806e3ff492ea41f49ca.tar.gz rtic-b2ec1fa65118813b400cf806e3ff492ea41f49ca.tar.zst rtic-b2ec1fa65118813b400cf806e3ff492ea41f49ca.zip |
Example running, timeout and delay futures available
Diffstat (limited to 'macros/src/codegen')
-rw-r--r-- | macros/src/codegen/dispatchers.rs | 128 | ||||
-rw-r--r-- | macros/src/codegen/module.rs | 34 | ||||
-rw-r--r-- | macros/src/codegen/monotonic.rs | 251 | ||||
-rw-r--r-- | macros/src/codegen/software_tasks.rs | 30 | ||||
-rw-r--r-- | macros/src/codegen/timer_queue.rs | 36 | ||||
-rw-r--r-- | macros/src/codegen/util.rs | 9 |
6 files changed, 434 insertions, 54 deletions
diff --git a/macros/src/codegen/dispatchers.rs b/macros/src/codegen/dispatchers.rs index a90a97c7..e6caa781 100644 --- a/macros/src/codegen/dispatchers.rs +++ b/macros/src/codegen/dispatchers.rs @@ -5,7 +5,7 @@ use rtic_syntax::ast::App; use crate::{analyze::Analysis, check::Extra, codegen::util}; /// Generates task dispatchers -pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStream2> { +pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream2> { let mut items = vec![]; let interrupts = &analysis.interrupts; @@ -64,6 +64,9 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea static #rq: rtic::RacyCell<#rq_ty> = rtic::RacyCell::new(#rq_expr); )); + let device = &extra.device; + let enum_ = util::interrupt_ident(); + let interrupt = util::suffixed(&interrupts[&level].0.to_string()); let arms = channel .tasks .iter() @@ -73,37 +76,124 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea let fq = util::fq_ident(name); let inputs = util::inputs_ident(name); let (_, tupled, pats, _) = util::regroup_inputs(&task.inputs); + let exec_name = util::internal_task_ident(name, "EXEC"); - quote!( - #(#cfgs)* - #t::#name => { - let #tupled = - (&*#inputs - .get()) - .get_unchecked(usize::from(index)) - .as_ptr() - .read(); - (&mut *#fq.get_mut()).split().0.enqueue_unchecked(index); - let priority = &rtic::export::Priority::new(PRIORITY); - #name( - #name::Context::new(priority) - #(,#pats)* - ) - } - ) + if task.is_async { + let executor_run_ident = util::executor_run_ident(name); + + quote!( + #(#cfgs)* + #t::#name => { + if !(&mut *#exec_name.get_mut()).is_running() { + let #tupled = + (&*#inputs + .get()) + .get_unchecked(usize::from(index)) + .as_ptr() + .read(); + (&mut *#fq.get_mut()).split().0.enqueue_unchecked(index); + + let priority = &rtic::export::Priority::new(PRIORITY); + (&mut *#exec_name.get_mut()).spawn(#name(#name::Context::new(priority), #(,#pats)*)); + #executor_run_ident.store(true, core::sync::atomic::Ordering::Relaxed); + } else { + retry_queue.push_unchecked((#t::#name, index)); + } + } + ) + } else { + quote!( + #(#cfgs)* + #t::#name => { + let #tupled = + (&*#inputs + .get()) + .get_unchecked(usize::from(index)) + .as_ptr() + .read(); + (&mut *#fq.get_mut()).split().0.enqueue_unchecked(index); + let priority = &rtic::export::Priority::new(PRIORITY); + #name( + #name::Context::new(priority) + #(,#pats)* + ) + } + ) + } }) .collect::<Vec<_>>(); + for (name, task) in app.software_tasks.iter() { + if task.is_async { + let type_name = util::internal_task_ident(name, "F"); + let exec_name = util::internal_task_ident(name, "EXEC"); + + stmts.push(quote!( + type #type_name = impl core::future::Future + 'static; + static #exec_name: + rtic::RacyCell<rtic::export::executor::AsyncTaskExecutor<#type_name>> = + rtic::RacyCell::new(rtic::export::executor::AsyncTaskExecutor::new()); + )); + } + } + + let n_executors: usize = app + .software_tasks + .iter() + .map(|(_, task)| if task.is_async { 1 } else { 0 }) + .sum(); + + // TODO: This `retry_queue` comes from the current design of the dispatcher queue handling. + // To remove this we would need to redesign how the dispatcher handles queues, and this can + // be done as an optimization later. + // + // The core issue is that we should only dequeue the ready queue if the exexutor associated + // to the task is not running. As it is today this queue is blindly dequeued, see the + // `while let Some(...) = (&mut *#rq.get_mut())...` a few lines down. The current "hack" is + // to just requeue the executor run if it should not have been dequeued. This needs however + // to be done after the ready queue has been exhausted. + if n_executors > 0 { + stmts.push(quote!( + let mut retry_queue: rtic::export::Vec<_, #n_executors> = rtic::export::Vec::new(); + )); + } + stmts.push(quote!( while let Some((task, index)) = (&mut *#rq.get_mut()).split().1.dequeue() { match task { #(#arms)* } } + + while let Some((task, index)) = retry_queue.pop() { + rtic::export::interrupt::free(|_| { + (&mut *#rq.get_mut()).enqueue_unchecked((task, index)); + }); + } )); + for (name, _task) in app.software_tasks.iter().filter_map(|(name, task)| { + if task.is_async { + Some((name, task)) + } else { + None + } + }) { + let exec_name = util::internal_task_ident(name, "EXEC"); + + let executor_run_ident = util::executor_run_ident(name); + stmts.push(quote!( + if #executor_run_ident.load(core::sync::atomic::Ordering::Relaxed) { + #executor_run_ident.store(false, core::sync::atomic::Ordering::Relaxed); + (&mut *#exec_name.get_mut()).poll(|| { + #executor_run_ident.store(true, core::sync::atomic::Ordering::Release); + rtic::pend(#device::#enum_::#interrupt); + }); + } + )); + } + let doc = format!("Interrupt handler to dispatch tasks at priority {}", level); - let interrupt = util::suffixed(&interrupts[&level].0.to_string()); let attribute = &interrupts[&level].1.attrs; items.push(quote!( #[allow(non_snake_case)] diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs index fd8137fa..29f27662 100644 --- a/macros/src/codegen/module.rs +++ b/macros/src/codegen/module.rs @@ -54,14 +54,6 @@ pub fn codegen( Context::Idle | Context::HardwareTask(_) | Context::SoftwareTask(_) => {} } - // if ctxt.has_locals(app) { - // let ident = util::locals_ident(ctxt, app); - // module_items.push(quote!( - // #[doc(inline)] - // pub use super::#ident as Locals; - // )); - // } - if ctxt.has_local_resources(app) { let ident = util::local_resources_ident(ctxt, app); let lt = if local_resources_tick { @@ -133,6 +125,7 @@ pub fn codegen( )); module_items.push(quote!( + #[doc(inline)] pub use super::#internal_monotonics_ident as Monotonics; )); } @@ -193,6 +186,7 @@ pub fn codegen( module_items.push(quote!( #(#cfgs)* + #[doc(inline)] pub use super::#internal_context_name as Context; )); @@ -225,6 +219,8 @@ pub fn codegen( #(#cfgs)* /// Spawns the task directly + #[allow(non_snake_case)] + #[doc(hidden)] pub fn #internal_spawn_ident(#(#args,)*) -> Result<(), #ty> { let input = #tupled; @@ -239,7 +235,6 @@ pub fn codegen( rtic::export::interrupt::free(|_| { (&mut *#rq.get_mut()).enqueue_unchecked((#t::#name, index)); }); - rtic::pend(#device::#enum_::#interrupt); Ok(()) @@ -252,6 +247,7 @@ pub fn codegen( module_items.push(quote!( #(#cfgs)* + #[doc(inline)] pub use super::#internal_spawn_ident as spawn; )); @@ -294,15 +290,21 @@ pub fn codegen( if monotonic.args.default { module_items.push(quote!( + #[doc(inline)] pub use #m::spawn_after; + #[doc(inline)] pub use #m::spawn_at; + #[doc(inline)] pub use #m::SpawnHandle; )); } module_items.push(quote!( pub mod #m { + #[doc(inline)] pub use super::super::#internal_spawn_after_ident as spawn_after; + #[doc(inline)] pub use super::super::#internal_spawn_at_ident as spawn_at; + #[doc(inline)] pub use super::super::#internal_spawn_handle_ident as SpawnHandle; } )); @@ -316,6 +318,7 @@ pub fn codegen( marker: u32, } + #(#cfgs)* impl core::fmt::Debug for #internal_spawn_handle_ident { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct(#spawn_handle_string).finish() @@ -327,7 +330,7 @@ pub fn codegen( pub fn cancel(self) -> Result<#ty, ()> { rtic::export::interrupt::free(|_| unsafe { let tq = &mut *#tq.get_mut(); - if let Some((_task, index)) = tq.cancel_marker(self.marker) { + if let Some((_task, index)) = tq.cancel_task_marker(self.marker) { // Get the message let msg = (&*#inputs .get()) @@ -362,11 +365,12 @@ pub fn codegen( let tq = (&mut *#tq.get_mut()); - tq.update_marker(self.marker, marker, instant, || #pend).map(|_| #name::#m::SpawnHandle { marker }) + tq.update_task_marker(self.marker, marker, instant, || #pend).map(|_| #name::#m::SpawnHandle { marker }) }) } } + #(#cfgs)* /// Spawns the task after a set duration relative to the current time /// @@ -407,10 +411,10 @@ pub fn codegen( rtic::export::interrupt::free(|_| { let marker = #tq_marker.get().read(); - let nr = rtic::export::NotReady { - instant, - index, + let nr = rtic::export::TaskNotReady { task: #t::#name, + index, + instant, marker, }; @@ -418,7 +422,7 @@ pub fn codegen( let tq = &mut *#tq.get_mut(); - tq.enqueue_unchecked( + tq.enqueue_task_unchecked( nr, || #enable_interrupt, || #pend, diff --git a/macros/src/codegen/monotonic.rs b/macros/src/codegen/monotonic.rs new file mode 100644 index 00000000..685502ed --- /dev/null +++ b/macros/src/codegen/monotonic.rs @@ -0,0 +1,251 @@ +use proc_macro2::TokenStream as TokenStream2; +use quote::quote; +use rtic_syntax::ast::App; + +use crate::{analyze::Analysis, check::Extra, codegen::util}; + +/// Generates monotonic module dispatchers +pub fn codegen(app: &App, _analysis: &Analysis, _extra: &Extra) -> TokenStream2 { + let mut monotonic_parts: Vec<_> = Vec::new(); + + let tq_marker = util::timer_queue_marker_ident(); + + for (_, monotonic) in &app.monotonics { + // let instants = util::monotonic_instants_ident(name, &monotonic.ident); + let monotonic_name = monotonic.ident.to_string(); + + let tq = util::tq_ident(&monotonic_name); + let m = &monotonic.ident; + let m_ident = util::monotonic_ident(&monotonic_name); + let m_isr = &monotonic.args.binds; + let enum_ = util::interrupt_ident(); + let name_str = &m.to_string(); + let ident = util::monotonic_ident(name_str); + let doc = &format!( + "This module holds the static implementation for `{}::now()`", + name_str + ); + + let (enable_interrupt, pend) = if &*m_isr.to_string() == "SysTick" { + ( + quote!(core::mem::transmute::<_, rtic::export::SYST>(()).enable_interrupt()), + quote!(rtic::export::SCB::set_pendst()), + ) + } else { + let rt_err = util::rt_err_ident(); + ( + quote!(rtic::export::NVIC::unmask(#rt_err::#enum_::#m_isr)), + quote!(rtic::pend(#rt_err::#enum_::#m_isr)), + ) + }; + + let default_monotonic = if monotonic.args.default { + quote!( + #[doc(inline)] + pub use #m::now; + #[doc(inline)] + pub use #m::delay; + #[doc(inline)] + pub use #m::timeout_at; + #[doc(inline)] + pub use #m::timeout_after; + ) + } else { + quote!() + }; + + monotonic_parts.push(quote! { + #default_monotonic + + #[doc = #doc] + #[allow(non_snake_case)] + pub mod #m { + + /// Read the current time from this monotonic + pub fn now() -> <super::super::#m as rtic::Monotonic>::Instant { + rtic::export::interrupt::free(|_| { + use rtic::Monotonic as _; + if let Some(m) = unsafe{ &mut *super::super::#ident.get_mut() } { + m.now() + } else { + <super::super::#m as rtic::Monotonic>::zero() + } + }) + } + + fn enqueue_waker( + instant: <super::super::#m as rtic::Monotonic>::Instant, + waker: core::task::Waker + ) -> Result<u32, ()> { + unsafe { + rtic::export::interrupt::free(|_| { + let marker = super::super::#tq_marker.get().read(); + super::super::#tq_marker.get_mut().write(marker.wrapping_add(1)); + + let nr = rtic::export::WakerNotReady { + waker, + instant, + marker, + }; + + let tq = &mut *super::super::#tq.get_mut(); + + tq.enqueue_waker( + nr, + || #enable_interrupt, + || #pend, + (&mut *super::super::#m_ident.get_mut()).as_mut()).map(|_| marker) + }) + } + } + + /// Delay + #[inline(always)] + #[allow(non_snake_case)] + pub fn delay(duration: <super::super::#m as rtic::Monotonic>::Duration) + -> DelayFuture { + let until = now() + duration; + DelayFuture { until, tq_marker: None } + } + + /// Delay future. + #[allow(non_snake_case)] + #[allow(non_camel_case_types)] + pub struct DelayFuture { + until: <super::super::#m as rtic::Monotonic>::Instant, + tq_marker: Option<u32>, + } + + impl core::future::Future for DelayFuture { + type Output = Result<(), ()>; + + fn poll( + mut self: core::pin::Pin<&mut Self>, + cx: &mut core::task::Context<'_> + ) -> core::task::Poll<Self::Output> { + let mut s = self.as_mut(); + let now = now(); + + if now >= s.until { + core::task::Poll::Ready(Ok(())) + } else { + if s.tq_marker.is_some() { + core::task::Poll::Pending + } else { + match enqueue_waker(s.until, cx.waker().clone()) { + Ok(marker) => { + s.tq_marker = Some(marker); + core::task::Poll::Pending + }, + Err(()) => core::task::Poll::Ready(Err(())), + } + } + } + } + } + + /// Timeout future. + #[allow(non_snake_case)] + #[allow(non_camel_case_types)] + pub struct TimeoutFuture<F: core::future::Future> { + future: F, + until: <super::super::#m as rtic::Monotonic>::Instant, + tq_marker: Option<u32>, + } + + /// Timeout after + #[allow(non_snake_case)] + #[inline(always)] + pub fn timeout_after<F: core::future::Future>( + future: F, + duration: <super::super::#m as rtic::Monotonic>::Duration + ) -> TimeoutFuture<F> { + let until = now() + duration; + TimeoutFuture { + future, + until, + tq_marker: None, + } + } + + /// Timeout at + #[allow(non_snake_case)] + #[inline(always)] + pub fn timeout_at<F: core::future::Future>( + future: F, + instant: <super::super::#m as rtic::Monotonic>::Instant + ) -> TimeoutFuture<F> { + TimeoutFuture { + future, + until: instant, + tq_marker: None, + } + } + + impl<F> core::future::Future for TimeoutFuture<F> + where + F: core::future::Future, + { + type Output = Result<Result<F::Output, super::TimeoutError>, ()>; + + fn poll( + self: core::pin::Pin<&mut Self>, + cx: &mut core::task::Context<'_> + ) -> core::task::Poll<Self::Output> { + let now = now(); + + // SAFETY: We don't move the underlying pinned value. + let mut s = unsafe { self.get_unchecked_mut() }; + let future = unsafe { core::pin::Pin::new_unchecked(&mut s.future) }; + + match future.poll(cx) { + core::task::Poll::Ready(r) => { + if let Some(marker) = s.tq_marker { + rtic::export::interrupt::free(|_| unsafe { + let tq = &mut *super::super::#tq.get_mut(); + tq.cancel_waker_marker(marker); + }); + } + + core::task::Poll::Ready(Ok(Ok(r))) + } + core::task::Poll::Pending => { + if now >= s.until { + // Timeout + core::task::Poll::Ready(Ok(Err(super::TimeoutError))) + } else if s.tq_marker.is_none() { + match enqueue_waker(s.until, cx.waker().clone()) { + Ok(marker) => { + s.tq_marker = Some(marker); + core::task::Poll::Pending + }, + Err(()) => core::task::Poll::Ready(Err(())), // TQ full + } + } else { + core::task::Poll::Pending + } + } + } + } + } + } + }); + } + + if monotonic_parts.is_empty() { + quote!() + } else { + quote!( + pub use rtic::Monotonic as _; + + /// Holds static methods for each monotonic. + pub mod monotonics { + /// A timeout error. + #[derive(Debug)] + pub struct TimeoutError; + + #(#monotonic_parts)* + } + ) + } +} diff --git a/macros/src/codegen/software_tasks.rs b/macros/src/codegen/software_tasks.rs index 78f6c961..6d08a221 100644 --- a/macros/src/codegen/software_tasks.rs +++ b/macros/src/codegen/software_tasks.rs @@ -27,13 +27,8 @@ pub fn codegen( let mut root = vec![]; let mut user_tasks = vec![]; - // Async tasks - for (name, task) in app.software_tasks.iter().filter(|(_, task)| task.is_async) { - // todo - } - - // Non-async tasks - for (name, task) in app.software_tasks.iter().filter(|(_, task)| !task.is_async) { + // Any task + for (name, task) in app.software_tasks.iter() { let inputs = &task.inputs; let (_, _, _, input_ty) = util::regroup_inputs(inputs); @@ -87,6 +82,7 @@ pub fn codegen( let uninit = mk_uninit(); let inputs_ident = util::inputs_ident(name); + mod_app.push(quote!( #uninit // /// Buffer that holds the inputs of a task @@ -96,6 +92,18 @@ pub fn codegen( static #inputs_ident: rtic::RacyCell<[core::mem::MaybeUninit<#input_ty>; #cap_lit]> = rtic::RacyCell::new([#(#elems,)*]); )); + if task.is_async { + let executor_ident = util::executor_run_ident(name); + mod_app.push(quote!( + #[allow(non_camel_case_types)] + #[allow(non_upper_case_globals)] + #[doc(hidden)] + static #executor_ident: core::sync::atomic::AtomicBool = + core::sync::atomic::AtomicBool::new(false); + )); + } + + let inputs = &task.inputs; // `${task}Resources` let mut shared_needs_lt = false; @@ -131,11 +139,17 @@ pub fn codegen( let attrs = &task.attrs; let cfgs = &task.cfgs; let stmts = &task.stmts; + let async_marker = if task.is_async { + quote!(async) + } else { + quote!() + }; + user_tasks.push(quote!( #(#attrs)* #(#cfgs)* #[allow(non_snake_case)] - fn #name(#context: #name::Context #(,#inputs)*) { + #async_marker fn #name(#context: #name::Context #(,#inputs)*) { use rtic::Mutex as _; use rtic::mutex::prelude::*; diff --git a/macros/src/codegen/timer_queue.rs b/macros/src/codegen/timer_queue.rs index 32e288c5..513f78af 100644 --- a/macros/src/codegen/timer_queue.rs +++ b/macros/src/codegen/timer_queue.rs @@ -1,9 +1,8 @@ +use crate::{analyze::Analysis, check::Extra, codegen::util}; use proc_macro2::TokenStream as TokenStream2; use quote::quote; use rtic_syntax::ast::App; -use crate::{analyze::Analysis, check::Extra, codegen::util}; - /// Generates timer queues and timer queue handlers #[allow(clippy::too_many_lines)] pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStream2> { @@ -67,8 +66,14 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea .iter() .map(|(_name, task)| task.args.capacity as usize) .sum(); - let n = util::capacity_literal(cap); - let tq_ty = quote!(rtic::export::TimerQueue<#mono_type, #t, #n>); + let n_task = util::capacity_literal(cap); + let n_worker: usize = app + .software_tasks + .iter() + .map(|(_name, task)| task.is_async as usize) + .sum(); + let n_worker = util::capacity_literal(n_worker); + let tq_ty = quote!(rtic::export::TimerQueue<#mono_type, #t, #n_task, #n_worker>); // For future use // let doc = format!(" RTIC internal: {}:{}", file!(), line!()); @@ -76,8 +81,12 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea #[doc(hidden)] #[allow(non_camel_case_types)] #[allow(non_upper_case_globals)] - static #tq: rtic::RacyCell<#tq_ty> = - rtic::RacyCell::new(rtic::export::TimerQueue(rtic::export::SortedLinkedList::new_u16())); + static #tq: rtic::RacyCell<#tq_ty> = rtic::RacyCell::new( + rtic::export::TimerQueue { + task_queue: rtic::export::SortedLinkedList::new_u16(), + waker_queue: rtic::export::SortedLinkedList::new_u16(), + } + ); )); let mono = util::monotonic_ident(&monotonic_name); @@ -118,7 +127,9 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea quote!( #(#cfgs)* #t::#name => { - rtic::export::interrupt::free(|_| (&mut *#rq.get_mut()).split().0.enqueue_unchecked((#rqt::#name, index))); + rtic::export::interrupt::free(|_| + (&mut *#rq.get_mut()).split().0.enqueue_unchecked((#rqt::#name, index)) + ); #pend } @@ -137,7 +148,7 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea #[no_mangle] #[allow(non_snake_case)] unsafe fn #bound_interrupt() { - while let Some((task, index)) = rtic::export::interrupt::free(|_| + while let Some(task_or_waker) = rtic::export::interrupt::free(|_| if let Some(mono) = (&mut *#m_ident.get_mut()).as_mut() { (&mut *#tq.get_mut()).dequeue(|| #disable_isr, mono) } else { @@ -146,8 +157,13 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea core::hint::unreachable_unchecked() }) { - match task { - #(#arms)* + match task_or_waker { + rtic::export::TaskOrWaker::Waker(waker) => waker.wake(), + rtic::export::TaskOrWaker::Task((task, index)) => { + match task { + #(#arms)* + } + } } } diff --git a/macros/src/codegen/util.rs b/macros/src/codegen/util.rs index 0a3edc20..a0a59090 100644 --- a/macros/src/codegen/util.rs +++ b/macros/src/codegen/util.rs @@ -67,6 +67,11 @@ pub fn inputs_ident(task: &Ident) -> Ident { mark_internal_name(&format!("{}_INPUTS", task)) } +/// Generates an identifier for the `EXECUTOR_RUN` atomics (`async` API) +pub fn executor_run_ident(task: &Ident) -> Ident { + mark_internal_name(&format!("{}_EXECUTOR_RUN", task)) +} + /// Generates an identifier for the `INSTANTS` buffer (`schedule` API) pub fn monotonic_instants_ident(task: &Ident, monotonic: &Ident) -> Ident { mark_internal_name(&format!("{}_{}_INSTANTS", task, monotonic)) @@ -222,7 +227,7 @@ pub fn rq_ident(priority: u8) -> Ident { /// Generates an identifier for the `enum` of `schedule`-able tasks pub fn schedule_t_ident() -> Ident { - Ident::new("SCHED_T", Span::call_site()) + mark_internal_name("SCHED_T") } /// Generates an identifier for the `enum` of `spawn`-able tasks @@ -230,7 +235,7 @@ pub fn schedule_t_ident() -> Ident { /// This identifier needs the same structure as the `RQ` identifier because there's one ready queue /// for each of these `T` enums pub fn spawn_t_ident(priority: u8) -> Ident { - Ident::new(&format!("P{}_T", priority), Span::call_site()) + mark_internal_name(&format!("P{}_T", priority)) } /// Suffixed identifier |