Refactor the refactor refactor

This commit is contained in:
Dániel Buga 2024-12-10 22:16:43 +01:00
parent d9e5ab4a1a
commit 5a3bf93b8a
No known key found for this signature in database
4 changed files with 39 additions and 60 deletions

View File

@ -60,14 +60,14 @@ fn main() -> Result<(), Box<dyn Error>> {
println!("cargo:rustc-check-cfg=cfg(single_queue)"); println!("cargo:rustc-check-cfg=cfg(single_queue)");
println!("cargo:rustc-check-cfg=cfg(generic_timers)"); println!("cargo:rustc-check-cfg=cfg(generic_timers)");
if cfg!(feature = "integrated-timers") { if cfg!(feature = "generic-queue") {
println!("cargo:rustc-cfg=generic_timers");
println!("cargo:rustc-cfg=single_queue");
} else {
println!("cargo:rustc-cfg=integrated_timers"); println!("cargo:rustc-cfg=integrated_timers");
if cfg!(feature = "single-queue") { if cfg!(feature = "single-queue") {
println!("cargo:rustc-cfg=single_queue"); println!("cargo:rustc-cfg=single_queue");
} }
} else {
println!("cargo:rustc-cfg=generic_timers");
println!("cargo:rustc-cfg=single_queue");
} }
Ok(()) Ok(())

View File

@ -75,6 +75,9 @@ impl Alarm {
} }
pub(super) struct EmbassyTimer { pub(super) struct EmbassyTimer {
#[cfg(single_queue)]
pub(crate) inner: crate::timer_queue::TimerQueue,
alarms: [Alarm; MAX_SUPPORTED_ALARM_COUNT], alarms: [Alarm; MAX_SUPPORTED_ALARM_COUNT],
available_timers: Locked<Option<&'static mut [Timer]>>, available_timers: Locked<Option<&'static mut [Timer]>>,
} }
@ -97,6 +100,8 @@ macro_rules! alarms {
const MAX_SUPPORTED_ALARM_COUNT: usize = 7; const MAX_SUPPORTED_ALARM_COUNT: usize = 7;
embassy_time_driver::time_driver_impl!(static DRIVER: EmbassyTimer = EmbassyTimer { embassy_time_driver::time_driver_impl!(static DRIVER: EmbassyTimer = EmbassyTimer {
#[cfg(single_queue)]
inner: crate::timer_queue::TimerQueue::new(Priority::max()),
alarms: alarms!(0, 1, 2, 3, 4, 5, 6), alarms: alarms!(0, 1, 2, 3, 4, 5, 6),
available_timers: Locked::new(None), available_timers: Locked::new(None),
}); });
@ -129,7 +134,7 @@ impl EmbassyTimer {
} }
fn on_interrupt(&self, id: usize) { fn on_interrupt(&self, id: usize) {
let ctx = self.alarms[id].inner.with(|alarm| { let _ctx = self.alarms[id].inner.with(|alarm| {
if let AlarmState::Initialized(timer) = &mut alarm.state { if let AlarmState::Initialized(timer) = &mut alarm.state {
timer.clear_interrupt(); timer.clear_interrupt();
alarm.callback.get() alarm.callback.get()
@ -141,7 +146,14 @@ impl EmbassyTimer {
} }
}); });
TIMER_QUEUE_DRIVER.handle_alarm(ctx); #[cfg(all(integrated_timers, not(single_queue)))]
{
let executor = unsafe { &*_ctx.cast::<crate::executor::InnerExecutor>() };
executor.timer_queue.dispatch();
}
#[cfg(single_queue)]
self.inner.dispatch();
} }
/// Returns `true` if the timer was armed, `false` if the timestamp is in /// Returns `true` if the timer was armed, `false` if the timestamp is in
@ -238,6 +250,22 @@ impl Driver for EmbassyTimer {
fn now(&self) -> u64 { fn now(&self) -> u64 {
now().ticks() now().ticks()
} }
fn schedule_wake(&self, at: u64, waker: &core::task::Waker) {
#[cfg(not(single_queue))]
unsafe {
let task = embassy_executor::raw::task_from_waker(waker);
// FIXME: this is UB, use Exposed Provenance API (or something better) when
// available. Expose provenance in `InnerExecutor::init`, and use it here.
let executor = &*(task.executor().unwrap_unchecked()
as *const embassy_executor::raw::Executor)
.cast::<crate::executor::InnerExecutor>();
executor.timer_queue.schedule_wake(at, waker);
}
#[cfg(single_queue)]
self.inner.schedule_wake(at, waker);
}
} }
#[cold] #[cold]
@ -249,31 +277,6 @@ fn not_enough_timers() -> ! {
panic!("There are not enough timers to allocate a new alarm. Call esp_hal_embassy::init() with the correct number of timers, or consider either using the single-queue feature or disabling integrated-timers."); panic!("There are not enough timers to allocate a new alarm. Call esp_hal_embassy::init() with the correct number of timers, or consider either using the single-queue feature or disabling integrated-timers.");
} }
pub(crate) struct TimerQueueDriver {
#[cfg(single_queue)]
pub(crate) inner: crate::timer_queue::TimerQueue,
}
impl TimerQueueDriver {
const fn new() -> Self {
Self {
#[cfg(single_queue)]
inner: crate::timer_queue::TimerQueue::new(Priority::max()),
}
}
fn handle_alarm(&self, _ctx: *const ()) {
#[cfg(all(integrated_timers, not(single_queue)))]
{
let executor = unsafe { &*_ctx.cast::<crate::executor::InnerExecutor>() };
executor.timer_queue.dispatch();
}
#[cfg(single_queue)]
self.inner.dispatch();
}
}
pub(crate) fn set_up_alarm(priority: Priority, _ctx: *mut ()) -> AlarmHandle { pub(crate) fn set_up_alarm(priority: Priority, _ctx: *mut ()) -> AlarmHandle {
let alarm = unsafe { let alarm = unsafe {
DRIVER DRIVER
@ -284,5 +287,3 @@ pub(crate) fn set_up_alarm(priority: Priority, _ctx: *mut ()) -> AlarmHandle {
DRIVER.set_callback_ctx(alarm, _ctx); DRIVER.set_callback_ctx(alarm, _ctx);
alarm alarm
} }
embassy_time_queue_driver::timer_queue_impl!(static TIMER_QUEUE_DRIVER: TimerQueueDriver = TimerQueueDriver::new());

View File

@ -66,33 +66,11 @@ impl TimerQueue {
} }
} }
impl embassy_time_queue_driver::TimerQueue for crate::time_driver::TimerQueueDriver {
fn schedule_wake(&'static self, at: u64, waker: &core::task::Waker) {
#[cfg(integrated_timers)]
let waker = embassy_executor::raw::task_from_waker(waker);
#[cfg(not(single_queue))]
unsafe {
// FIXME: this is UB, use Exposed Provenance API (or something better) when
// available. Expose provenance in `InnerExecutor::init`, and use it here.
let executor = &*(waker.executor().unwrap_unchecked()
as *const embassy_executor::raw::Executor)
.cast::<crate::executor::InnerExecutor>();
executor.timer_queue.schedule_wake(at, waker);
}
#[cfg(single_queue)]
self.inner.schedule_wake(at, waker);
}
}
#[cfg(integrated_timers)] #[cfg(integrated_timers)]
mod adapter { mod adapter {
use core::cell::RefCell; use core::cell::RefCell;
use embassy_executor::raw; type Q = embassy_time_queue_driver::queue_integrated::Queue;
type Q = embassy_time_queue_driver::queue_integrated::TimerQueue;
/// A simple wrapper around a `Queue` to provide interior mutability. /// A simple wrapper around a `Queue` to provide interior mutability.
pub struct RefCellQueue { pub struct RefCellQueue {
@ -109,7 +87,7 @@ mod adapter {
/// Schedules a task to run at a specific time, and returns whether any /// Schedules a task to run at a specific time, and returns whether any
/// changes were made. /// changes were made.
pub fn schedule_wake(&self, at: u64, waker: raw::TaskRef) -> bool { pub fn schedule_wake(&self, at: u64, waker: &core::task::Waker) -> bool {
self.inner.borrow_mut().schedule_wake(at, waker) self.inner.borrow_mut().schedule_wake(at, waker)
} }
@ -126,7 +104,7 @@ mod adapter {
} }
impl super::TimerQueue { impl super::TimerQueue {
pub fn schedule_wake(&self, at: u64, task: raw::TaskRef) { pub fn schedule_wake(&self, at: u64, task: &core::task::Waker) {
if self.inner.lock(|q| q.schedule_wake(at, task)) { if self.inner.lock(|q| q.schedule_wake(at, task)) {
self.dispatch(); self.dispatch();
} }

View File

@ -1,9 +1,9 @@
//! Embassy executor benchmark, used to try out optimization ideas. //! Embassy executor benchmark, used to try out optimization ideas.
//% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 //% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: esp-hal-embassy/integrated-timers
// FEATURES: esp-hal-embassy/integrated-timers esp-hal-embassy/single-queue
// FEATURES: // FEATURES:
// FEATURES: esp-hal-embassy/single-queue
//% FEATURES: esp-hal-embassy/generic-queue
#![no_std] #![no_std]
#![no_main] #![no_main]