From 985274e06bbd48d141281a065db1e89ca481a146 Mon Sep 17 00:00:00 2001 From: Jan Niehusmann Date: Mon, 9 Sep 2024 06:41:02 +0000 Subject: [PATCH] Tidy the code a bit --- .../tests/i2c_tests/test_executor.rs | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/on-target-tests/tests/i2c_tests/test_executor.rs b/on-target-tests/tests/i2c_tests/test_executor.rs index f8b76be98..dfd1328ce 100644 --- a/on-target-tests/tests/i2c_tests/test_executor.rs +++ b/on-target-tests/tests/i2c_tests/test_executor.rs @@ -9,7 +9,7 @@ use core::{ future::Future, pin::{self, Pin}, - ptr::addr_of, + ptr, sync::atomic::{AtomicBool, Ordering}, task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, }; @@ -19,6 +19,8 @@ use once_cell::sync::OnceCell; static WOKE: AtomicBool = AtomicBool::new(false); static POLLING: AtomicBool = AtomicBool::new(false); +static VTABLE: RawWakerVTable = RawWakerVTable::new(clone_fn, wake_fn, wake_fn, drop_fn); + fn wake_fn(_data: *const ()) { if !POLLING.load(Ordering::Relaxed) { defmt::info!("waker called while not polling"); @@ -26,26 +28,21 @@ fn wake_fn(_data: *const ()) { WOKE.store(true, Ordering::Relaxed); } -const fn clone_fn(data: *const ()) -> RawWaker { - RawWaker::new(data, raw_waker_vtable()) +fn clone_fn(data: *const ()) -> RawWaker { + RawWaker::new(data, &VTABLE) } fn drop_fn(_data: *const ()) {} -const fn raw_waker_vtable() -> &'static RawWakerVTable { - const VTABLE: RawWakerVTable = RawWakerVTable::new(clone_fn, wake_fn, wake_fn, drop_fn); - &VTABLE -} - fn context() -> Context<'static> { - static DATA: () = (); - static WAKER: OnceCell = OnceCell::new(); // Safety: The functions in the vtable of this executor only modify static atomics. - let waker = WAKER.get_or_init(|| unsafe { Waker::from_raw(clone_fn(addr_of!(DATA))) }); + let waker = + WAKER.get_or_init(|| unsafe { Waker::from_raw(RawWaker::new(ptr::null(), &VTABLE)) }); // Starting from rust 1.82.0, this could be used: - // static WAKER: Waker = unsafe { Waker::from_raw(clone_fn(addr_of!(DATA))) }; + // static WAKER: Waker = unsafe { Waker::from_raw(RawWaker::new(ptr::null(), &VTABLE)) }; + // (stabilized by https://github.com/rust-lang/rust/pull/128228) Context::from_waker(waker) } @@ -56,6 +53,9 @@ fn context() -> Context<'static> { /// if the waker is properly triggered from an interrupt. /// /// This won't work as expected of multiple calls to `execute` happen concurrently. +/// +/// (Calling this function from multiple threads concurrently doesn't violate any +/// safety guarantees, but wakers may wake the wrong task, making futures stall.) pub fn execute(future: impl Future) -> T { let mut pinned: Pin<&mut _> = pin::pin!(future); if WOKE.load(Ordering::Relaxed) { @@ -70,9 +70,10 @@ pub fn execute(future: impl Future) -> T { break result; } while !WOKE.load(Ordering::Relaxed) { + // In a real executor, there should be a WFI/WFE or similar here, to avoid + // busy looping. + // As this is only a test executor, we don't care. core::hint::spin_loop(); - // TODO WFI or similar? - // But probably not important for this test executor } } }