diff --git a/embassy/src/executor/timer.rs b/embassy/src/executor/timer.rs index 05c14b88..56236a05 100644 --- a/embassy/src/executor/timer.rs +++ b/embassy/src/executor/timer.rs @@ -7,16 +7,21 @@ use crate::time::{Duration, Instant}; pub struct Timer { expires_at: Instant, + yielded_once: bool, } impl Timer { pub fn at(expires_at: Instant) -> Self { - Self { expires_at } + Self { + expires_at, + yielded_once: false, + } } pub fn after(duration: Duration) -> Self { Self { expires_at: Instant::now() + duration, + yielded_once: false, } } } @@ -25,11 +30,12 @@ impl Unpin for Timer {} impl Future for Timer { type Output = (); - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - if self.expires_at <= Instant::now() { + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + if self.yielded_once && self.expires_at <= Instant::now() { Poll::Ready(()) } else { unsafe { super::register_timer(self.expires_at, cx.waker()) }; + self.yielded_once = true; Poll::Pending } } diff --git a/examples/src/bin/executor_fairness_test.rs b/examples/src/bin/executor_fairness_test.rs new file mode 100644 index 00000000..9b2c1bd2 --- /dev/null +++ b/examples/src/bin/executor_fairness_test.rs @@ -0,0 +1,74 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +#[path = "../example_common.rs"] +mod example_common; +use example_common::*; + +use core::task::Poll; +use cortex_m_rt::entry; +use defmt::panic; +use embassy::executor::{task, Executor}; +use embassy::time::{Duration, Instant, Timer}; +use embassy::util::Forever; +use embassy_nrf::pac; +use embassy_nrf::{interrupt, rtc}; +use nrf52840_hal::clocks; + +#[task] +async fn run1() { + loop { + info!("DING DONG"); + Timer::after(Duration::from_ticks(16000)).await; + } +} + +#[task] +async fn run2() { + loop { + Timer::at(Instant::from_ticks(0)).await; + } +} + +#[task] +async fn run3() { + futures::future::poll_fn(|cx| { + cx.waker().wake_by_ref(); + Poll::<()>::Pending + }) + .await; +} + +static RTC: Forever> = Forever::new(); +static ALARM: Forever> = Forever::new(); +static EXECUTOR: Forever = Forever::new(); + +#[entry] +fn main() -> ! { + info!("Hello World!"); + + let p = unwrap!(embassy_nrf::pac::Peripherals::take()); + + clocks::Clocks::new(p.CLOCK) + .enable_ext_hfosc() + .set_lfclk_src_external(clocks::LfOscConfiguration::NoExternalNoBypass) + .start_lfclk(); + + let rtc = RTC.put(rtc::RTC::new(p.RTC1, interrupt::take!(RTC1))); + rtc.start(); + + unsafe { embassy::time::set_clock(rtc) }; + + let alarm = ALARM.put(rtc.alarm0()); + let executor = EXECUTOR.put(Executor::new_with_alarm(alarm, cortex_m::asm::sev)); + + unwrap!(executor.spawn(run1())); + unwrap!(executor.spawn(run2())); + unwrap!(executor.spawn(run3())); + + loop { + executor.run(); + cortex_m::asm::wfe(); + } +}