mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-23 20:22:51 +01:00
Now with new monotonic trait and crate
This commit is contained in:
parent
b57ef0bf9d
commit
ebf2f058a4
12 changed files with 135 additions and 59 deletions
|
@ -58,6 +58,7 @@ required-features = ["__v7"]
|
||||||
cortex-m = "0.7.0"
|
cortex-m = "0.7.0"
|
||||||
cortex-m-rtic-macros = { path = "macros", version = "0.6.0-alpha.0" }
|
cortex-m-rtic-macros = { path = "macros", version = "0.6.0-alpha.0" }
|
||||||
rtic-core = { git = "https://github.com/rtic-rs/rtic-core", branch = "new_monotonic" }
|
rtic-core = { git = "https://github.com/rtic-rs/rtic-core", branch = "new_monotonic" }
|
||||||
|
rtic-monotonic = { git = "https://github.com/rtic-rs/rtic-monotonic", branch = "master" }
|
||||||
#rtic-core = "0.3.1"
|
#rtic-core = "0.3.1"
|
||||||
heapless = "0.5.0"
|
heapless = "0.5.0"
|
||||||
bare-metal = "1.0.0"
|
bare-metal = "1.0.0"
|
||||||
|
|
|
@ -104,13 +104,35 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let app_name = &app.name;
|
||||||
|
let app_path = quote! {crate::#app_name};
|
||||||
|
|
||||||
let monotonic_imports: Vec<_> = app
|
let monotonic_imports: Vec<_> = app
|
||||||
.monotonics
|
.monotonics
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, monotonic)| {
|
.map(|(_, monotonic)| {
|
||||||
let name = &monotonic.ident;
|
let name = &monotonic.ident;
|
||||||
let ty = &monotonic.ty;
|
let ty = &monotonic.ty;
|
||||||
quote!(pub type #name = #ty;)
|
let mangled_name = util::mangle_monotonic_type(&name.to_string());
|
||||||
|
let ident = util::monotonic_ident(&name.to_string());
|
||||||
|
quote! {
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub type #mangled_name = #ty;
|
||||||
|
|
||||||
|
pub mod #name {
|
||||||
|
pub fn now() -> rtic::time::Instant<#app_path::#mangled_name> {
|
||||||
|
rtic::export::interrupt::free(|_| {
|
||||||
|
use rtic::Monotonic as _;
|
||||||
|
use rtic::time::Clock as _;
|
||||||
|
if let Ok(v) = unsafe{ (&*#app_path::#ident.as_ptr()).try_now() } {
|
||||||
|
v
|
||||||
|
} else {
|
||||||
|
unreachable!("Your monotonic is not infallible!")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> CodegenResult {
|
||||||
let app_path = quote! {crate::#app_name};
|
let app_path = quote! {crate::#app_name};
|
||||||
let locals_new = locals_new.iter();
|
let locals_new = locals_new.iter();
|
||||||
let call_init = Some(
|
let call_init = Some(
|
||||||
quote!(let (late, monotonics) = #app_path::#name(#(#locals_new,)* #name::Context::new(core.into()));),
|
quote!(let (late, mut monotonics) = #app_path::#name(#(#locals_new,)* #name::Context::new(core.into()));),
|
||||||
);
|
);
|
||||||
|
|
||||||
root_init.push(module::codegen(
|
root_init.push(module::codegen(
|
||||||
|
|
|
@ -126,7 +126,7 @@ pub fn codegen(
|
||||||
.monotonics
|
.monotonics
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, monotonic)| {
|
.map(|(_, monotonic)| {
|
||||||
let mono = &monotonic.ident;
|
let mono = util::mangle_monotonic_type(&monotonic.ident.to_string());
|
||||||
quote! {#app_path::#mono}
|
quote! {#app_path::#mono}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -234,6 +234,7 @@ pub fn codegen(
|
||||||
let tq = util::tq_ident(&monotonic.ident.to_string());
|
let tq = util::tq_ident(&monotonic.ident.to_string());
|
||||||
let t = util::schedule_t_ident();
|
let t = util::schedule_t_ident();
|
||||||
let m = &monotonic.ident;
|
let m = &monotonic.ident;
|
||||||
|
let m_mangled = util::mangle_monotonic_type(&monotonic.ident.to_string());
|
||||||
let m_isr = &monotonic.args.binds;
|
let m_isr = &monotonic.args.binds;
|
||||||
let enum_ = util::interrupt_ident();
|
let enum_ = util::interrupt_ident();
|
||||||
|
|
||||||
|
@ -242,9 +243,10 @@ pub fn codegen(
|
||||||
items.push(quote!(pub use #m::spawn_at;));
|
items.push(quote!(pub use #m::spawn_at;));
|
||||||
}
|
}
|
||||||
|
|
||||||
let (unmask, pend) = if &*m_isr.to_string() == "SysTick" {
|
let (enable_interrupt, pend) = if &*m_isr.to_string() == "SysTick" {
|
||||||
(
|
(
|
||||||
quote!(core::mem::transmute::<_, cortex_m::peripheral::SYST>(()).disable_interrupt()),
|
quote!(core::mem::transmute::<_, cortex_m::peripheral::SYST>(())
|
||||||
|
.enable_interrupt()),
|
||||||
quote!(cortex_m::peripheral::SCB::set_pendst()),
|
quote!(cortex_m::peripheral::SCB::set_pendst()),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -263,16 +265,16 @@ pub fn codegen(
|
||||||
#(,#args)*
|
#(,#args)*
|
||||||
) -> Result<(), #ty>
|
) -> Result<(), #ty>
|
||||||
where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint,
|
where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint,
|
||||||
D::T: Into<<#app_path::#m as rtic::time::Clock>::T>,
|
D::T: Into<<#app_path::#m_mangled as rtic::time::Clock>::T>,
|
||||||
{
|
{
|
||||||
let instant = <#app_path::#m as rtic::Monotonic>::now();
|
let instant = #app_path::#m::now();
|
||||||
|
|
||||||
spawn_at(instant + duration, #(,#untupled)*)
|
spawn_at(instant + duration, #(,#untupled)*)
|
||||||
}
|
}
|
||||||
|
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
pub fn spawn_at(
|
pub fn spawn_at(
|
||||||
instant: rtic::time::Instant<#app_path::#m>
|
instant: rtic::time::Instant<#app_path::#m_mangled>
|
||||||
#(,#args)*
|
#(,#args)*
|
||||||
) -> Result<(), #ty> {
|
) -> Result<(), #ty> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -296,7 +298,7 @@ pub fn codegen(
|
||||||
|
|
||||||
rtic::export::interrupt::free(|_| #app_path::#tq.enqueue_unchecked(
|
rtic::export::interrupt::free(|_| #app_path::#tq.enqueue_unchecked(
|
||||||
nr,
|
nr,
|
||||||
|| #unmask,
|
|| #enable_interrupt,
|
||||||
|| #pend,
|
|| #pend,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use proc_macro2::TokenStream as TokenStream2;
|
use proc_macro2::{Span, TokenStream as TokenStream2};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use rtic_syntax::ast::App;
|
use rtic_syntax::ast::App;
|
||||||
|
use syn::Index;
|
||||||
|
|
||||||
use crate::{analyze::Analysis, codegen::util};
|
use crate::{analyze::Analysis, codegen::util};
|
||||||
|
|
||||||
|
@ -25,12 +26,17 @@ pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (monotonic, _) in app.monotonics.iter() {
|
for (i, (monotonic, _)) in app.monotonics.iter().enumerate() {
|
||||||
stmts.push(quote!(#monotonic::reset();));
|
let idx = Index {
|
||||||
}
|
index: i as u32,
|
||||||
|
span: Span::call_site(),
|
||||||
|
};
|
||||||
|
stmts.push(quote!(monotonics.#idx.reset();));
|
||||||
|
|
||||||
// Forget the monotonics so they won't be dropped.
|
// Store the monotonic
|
||||||
stmts.push(quote!(core::mem::forget(monotonics);));
|
let name = util::monotonic_ident(&monotonic.to_string());
|
||||||
|
stmts.push(quote!(#name.as_mut_ptr().write(monotonics.#idx);));
|
||||||
|
}
|
||||||
|
|
||||||
// Enable the interrupts -- this completes the `init`-ialization phase
|
// Enable the interrupts -- this completes the `init`-ialization phase
|
||||||
stmts.push(quote!(rtic::export::interrupt::enable();));
|
stmts.push(quote!(rtic::export::interrupt::enable();));
|
||||||
|
|
|
@ -77,14 +77,17 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize monotonic's interrupts
|
// Initialize monotonic's interrupts
|
||||||
for (priority, name) in app
|
for (ident, priority, name) in app
|
||||||
.monotonics
|
.monotonics
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, monotonic)| (&monotonic.args.priority, &monotonic.args.binds))
|
.map(|(ident, monotonic)| (ident, &monotonic.args.priority, &monotonic.args.binds))
|
||||||
{
|
{
|
||||||
// Compile time assert that this priority is supported by the device
|
// Compile time assert that this priority is supported by the device
|
||||||
stmts.push(quote!(let _ = [(); ((1 << #nvic_prio_bits) - #priority as usize)];));
|
stmts.push(quote!(let _ = [(); ((1 << #nvic_prio_bits) - #priority as usize)];));
|
||||||
|
|
||||||
|
let app_name = &app.name;
|
||||||
|
let app_path = quote! {crate::#app_name};
|
||||||
|
let mono_type = util::mangle_monotonic_type(&ident.to_string());
|
||||||
|
|
||||||
if &*name.to_string() == "SysTick" {
|
if &*name.to_string() == "SysTick" {
|
||||||
stmts.push(quote!(
|
stmts.push(quote!(
|
||||||
|
@ -92,6 +95,12 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
rtic::export::SystemHandler::SysTick,
|
rtic::export::SystemHandler::SysTick,
|
||||||
rtic::export::logical2hw(#priority, #nvic_prio_bits),
|
rtic::export::logical2hw(#priority, #nvic_prio_bits),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Always enable monotonic interrupts if they should never be off
|
||||||
|
if !#app_path::#mono_type::DISABLE_INTERRUPT_ON_EMPTY_QUEUE {
|
||||||
|
core::mem::transmute::<_, cortex_m::peripheral::SYST>(())
|
||||||
|
.enable_interrupt();
|
||||||
|
}
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
// NOTE this also checks that the interrupt exists in the `Interrupt` enumeration
|
// NOTE this also checks that the interrupt exists in the `Interrupt` enumeration
|
||||||
|
@ -101,10 +110,13 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
#rt_err::#interrupt::#name,
|
#rt_err::#interrupt::#name,
|
||||||
rtic::export::logical2hw(#priority, #nvic_prio_bits),
|
rtic::export::logical2hw(#priority, #nvic_prio_bits),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Always enable monotonic interrupts if they should never be off
|
||||||
|
if !#app_path::#mono_type::DISABLE_INTERRUPT_ON_EMPTY_QUEUE {
|
||||||
|
rtic::export::NVIC::unmask(#app_path::#rt_err::#interrupt::#name);
|
||||||
|
}
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE we do not unmask the interrupt as this is part of the monotonic to keep track of
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's no user `#[idle]` then optimize returning from interrupt handlers
|
// If there's no user `#[idle]` then optimize returning from interrupt handlers
|
||||||
|
|
|
@ -62,7 +62,7 @@ pub fn codegen(
|
||||||
|
|
||||||
for (_, monotonic) in &app.monotonics {
|
for (_, monotonic) in &app.monotonics {
|
||||||
let instants = util::monotonic_instants_ident(name, &monotonic.ident);
|
let instants = util::monotonic_instants_ident(name, &monotonic.ident);
|
||||||
let m = &monotonic.ident;
|
let m = util::mangle_monotonic_type(&monotonic.ident.to_string());
|
||||||
|
|
||||||
let uninit = mk_uninit();
|
let uninit = mk_uninit();
|
||||||
mod_app.push(quote!(
|
mod_app.push(quote!(
|
||||||
|
|
|
@ -42,7 +42,10 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
|
||||||
let monotonic_name = monotonic.ident.to_string();
|
let monotonic_name = monotonic.ident.to_string();
|
||||||
let tq = util::tq_ident(&monotonic_name);
|
let tq = util::tq_ident(&monotonic_name);
|
||||||
let t = util::schedule_t_ident();
|
let t = util::schedule_t_ident();
|
||||||
let m = &monotonic.ident;
|
let m = util::mangle_monotonic_type(&monotonic_name);
|
||||||
|
let m_ident = util::monotonic_ident(&monotonic_name);
|
||||||
|
let app_name = &app.name;
|
||||||
|
let app_path = quote! {crate::#app_name};
|
||||||
|
|
||||||
// Static variables and resource proxy
|
// Static variables and resource proxy
|
||||||
{
|
{
|
||||||
|
@ -63,6 +66,15 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
));
|
));
|
||||||
|
|
||||||
|
let mono = util::monotonic_ident(&monotonic_name);
|
||||||
|
let doc = &format!("Storage for {}", monotonic_name);
|
||||||
|
let mono_ty = quote!(core::mem::MaybeUninit<#m>);
|
||||||
|
|
||||||
|
items.push(quote!(
|
||||||
|
#[doc = #doc]
|
||||||
|
static mut #mono: #mono_ty = core::mem::MaybeUninit::uninit();
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timer queue handler
|
// Timer queue handler
|
||||||
|
@ -100,8 +112,8 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let bound_interrupt = &monotonic.args.binds;
|
let bound_interrupt = &monotonic.args.binds;
|
||||||
let enable_isr = if &*bound_interrupt.to_string() == "SysTick" {
|
let disable_isr = if &*bound_interrupt.to_string() == "SysTick" {
|
||||||
quote!(core::mem::transmute::<_, cortex_m::peripheral::SYST>(()).enable_interrupt())
|
quote!(core::mem::transmute::<_, cortex_m::peripheral::SYST>(()).disable_interrupt())
|
||||||
} else {
|
} else {
|
||||||
quote!(rtic::export::NVIC::mask(#rt_err::#enum_::#bound_interrupt))
|
quote!(rtic::export::NVIC::mask(#rt_err::#enum_::#bound_interrupt))
|
||||||
};
|
};
|
||||||
|
@ -111,7 +123,8 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
unsafe fn #bound_interrupt() {
|
unsafe fn #bound_interrupt() {
|
||||||
while let Some((task, index)) = rtic::export::interrupt::free(|_| #tq.dequeue(
|
while let Some((task, index)) = rtic::export::interrupt::free(|_| #tq.dequeue(
|
||||||
|| #enable_isr,
|
|| #disable_isr,
|
||||||
|
&mut *#app_path::#m_ident.as_mut_ptr(),
|
||||||
))
|
))
|
||||||
{
|
{
|
||||||
match task {
|
match task {
|
||||||
|
|
|
@ -239,6 +239,16 @@ pub fn tq_ident(name: &str) -> Ident {
|
||||||
Ident::new(&format!("TQ_{}", name), Span::call_site())
|
Ident::new(&format!("TQ_{}", name), Span::call_site())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generates an identifier for monotonic timer storage
|
||||||
|
pub fn monotonic_ident(name: &str) -> Ident {
|
||||||
|
Ident::new(&format!("MONOTONIC_STORAGE_{}", name), Span::call_site())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates an identifier for monotonic timer storage
|
||||||
|
pub fn mangle_monotonic_type(name: &str) -> Ident {
|
||||||
|
Ident::new(&format!("MonotonicMangled{}", name), Span::call_site())
|
||||||
|
}
|
||||||
|
|
||||||
/// The name to get better RT flag errors
|
/// The name to get better RT flag errors
|
||||||
pub fn rt_err_ident() -> Ident {
|
pub fn rt_err_ident() -> Ident {
|
||||||
Ident::new(
|
Ident::new(
|
||||||
|
|
|
@ -16,7 +16,7 @@ pub use cortex_m::{
|
||||||
use heapless::spsc::SingleCore;
|
use heapless::spsc::SingleCore;
|
||||||
pub use heapless::{consts, i::Queue as iQueue, spsc::Queue};
|
pub use heapless::{consts, i::Queue as iQueue, spsc::Queue};
|
||||||
pub use heapless::{i::BinaryHeap as iBinaryHeap, BinaryHeap};
|
pub use heapless::{i::BinaryHeap as iBinaryHeap, BinaryHeap};
|
||||||
pub use rtic_core::monotonic::Monotonic;
|
pub use rtic_monotonic as monotonic;
|
||||||
|
|
||||||
pub type SCFQ<N> = Queue<u8, N, u8, SingleCore>;
|
pub type SCFQ<N> = Queue<u8, N, u8, SingleCore>;
|
||||||
pub type SCRQ<T, N> = Queue<(T, u8), N, u8, SingleCore>;
|
pub type SCRQ<T, N> = Queue<(T, u8), N, u8, SingleCore>;
|
||||||
|
@ -116,7 +116,7 @@ where
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn assert_monotonic<T>()
|
pub fn assert_monotonic<T>()
|
||||||
where
|
where
|
||||||
T: Monotonic,
|
T: monotonic::Monotonic,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,10 +37,8 @@
|
||||||
|
|
||||||
use cortex_m::{interrupt::InterruptNumber, peripheral::NVIC};
|
use cortex_m::{interrupt::InterruptNumber, peripheral::NVIC};
|
||||||
pub use cortex_m_rtic_macros::app;
|
pub use cortex_m_rtic_macros::app;
|
||||||
pub use rtic_core::{
|
pub use rtic_core::{prelude as mutex_prelude, Exclusive, Mutex};
|
||||||
monotonic::{self, embedded_time as time, Monotonic},
|
pub use rtic_monotonic::{self, embedded_time as time, Monotonic};
|
||||||
prelude as mutex_prelude, Exclusive, Mutex,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod export;
|
pub mod export;
|
||||||
|
|
70
src/tq.rs
70
src/tq.rs
|
@ -1,4 +1,7 @@
|
||||||
use crate::{time::Instant, Monotonic};
|
use crate::{
|
||||||
|
time::{Clock, Instant},
|
||||||
|
Monotonic,
|
||||||
|
};
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
use heapless::{binary_heap::Min, ArrayLength, BinaryHeap};
|
use heapless::{binary_heap::Min, ArrayLength, BinaryHeap};
|
||||||
|
|
||||||
|
@ -42,7 +45,7 @@ where
|
||||||
})
|
})
|
||||||
.unwrap_or(true);
|
.unwrap_or(true);
|
||||||
if if_heap_max_greater_than_nr {
|
if if_heap_max_greater_than_nr {
|
||||||
if is_empty {
|
if Mono::DISABLE_INTERRUPT_ON_EMPTY_QUEUE && is_empty {
|
||||||
// mem::transmute::<_, SYST>(()).enable_interrupt();
|
// mem::transmute::<_, SYST>(()).enable_interrupt();
|
||||||
enable_interrupt();
|
enable_interrupt();
|
||||||
}
|
}
|
||||||
|
@ -61,44 +64,53 @@ where
|
||||||
self.0.is_empty()
|
self.0.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn unwrapper<T, E>(val: Result<T, E>) -> T {
|
||||||
|
if let Ok(v) = val {
|
||||||
|
v
|
||||||
|
} else {
|
||||||
|
unreachable!("Your monotonic is not infallible")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Dequeue a task from the TimerQueue
|
/// Dequeue a task from the TimerQueue
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn dequeue<F>(&mut self, disable_interrupt: F) -> Option<(Task, u8)>
|
pub fn dequeue<F>(&mut self, disable_interrupt: F, mono: &mut Mono) -> Option<(Task, u8)>
|
||||||
where
|
where
|
||||||
F: FnOnce(),
|
F: FnOnce(),
|
||||||
{
|
{
|
||||||
unsafe {
|
mono.clear_compare_flag();
|
||||||
Mono::clear_compare();
|
|
||||||
|
|
||||||
if let Some(instant) = self.0.peek().map(|p| p.instant) {
|
if let Some(instant) = self.0.peek().map(|p| p.instant) {
|
||||||
if instant < Mono::now() {
|
if instant < Self::unwrapper(Clock::try_now(mono)) {
|
||||||
// task became ready
|
// task became ready
|
||||||
let nr = self.0.pop_unchecked();
|
let nr = unsafe { self.0.pop_unchecked() };
|
||||||
|
|
||||||
|
Some((nr.task, nr.index))
|
||||||
|
} else {
|
||||||
|
// TODO: Fix this hack...
|
||||||
|
// Extract the compare time.
|
||||||
|
mono.set_compare(*instant.duration_since_epoch().integer());
|
||||||
|
|
||||||
|
// Double check that the instant we set is really in the future, else
|
||||||
|
// dequeue. If the monotonic is fast enough it can happen that from the
|
||||||
|
// read of now to the set of the compare, the time can overflow. This is to
|
||||||
|
// guard against this.
|
||||||
|
if instant < Self::unwrapper(Clock::try_now(mono)) {
|
||||||
|
let nr = unsafe { self.0.pop_unchecked() };
|
||||||
|
|
||||||
Some((nr.task, nr.index))
|
Some((nr.task, nr.index))
|
||||||
} else {
|
} else {
|
||||||
// TODO: Fix this hack...
|
None
|
||||||
// Extract the compare time.
|
|
||||||
Mono::set_compare(*instant.duration_since_epoch().integer());
|
|
||||||
|
|
||||||
// Double check that the instant we set is really in the future, else
|
|
||||||
// dequeue. If the monotonic is fast enough it can happen that from the
|
|
||||||
// read of now to the set of the compare, the time can overflow. This is to
|
|
||||||
// guard against this.
|
|
||||||
if instant < Mono::now() {
|
|
||||||
let nr = self.0.pop_unchecked();
|
|
||||||
|
|
||||||
Some((nr.task, nr.index))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// The queue is empty, disable the interrupt.
|
|
||||||
disable_interrupt();
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// The queue is empty, disable the interrupt.
|
||||||
|
if Mono::DISABLE_INTERRUPT_ON_EMPTY_QUEUE {
|
||||||
|
disable_interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue