Skip to content

Commit 0cd6892

Browse files
committed
zephyr: Change from Arc to declaration on Work Queues
Instead of allocating work queues, and hoping they don't get freed, instead move to a static declaration. This is facilitated by a macro `define_work_queue` that makes it easy to declare these at the top level. Signed-off-by: David Brown <[email protected]>
1 parent 555ea2e commit 0cd6892

File tree

3 files changed

+202
-196
lines changed

3 files changed

+202
-196
lines changed

samples/bench/src/lib.rs

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ use alloc::collections::vec_deque::VecDeque;
1616
use alloc::vec;
1717
use executor::AsyncTests;
1818
use static_cell::StaticCell;
19-
use zephyr::kobj_define;
19+
use zephyr::define_work_queue;
2020
use zephyr::raw::k_yield;
2121
use zephyr::sync::{PinWeak, SpinMutex};
2222
use zephyr::time::NoWait;
23-
use zephyr::work::{SimpleAction, Work, WorkQueueBuilder};
23+
use zephyr::work::{SimpleAction, Work};
2424
use zephyr::{
2525
kconfig::CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC,
2626
printkln,
@@ -80,7 +80,7 @@ extern "C" fn rust_main() {
8080
spin_bench();
8181
sem_bench();
8282

83-
let simple = Simple::new(tester.workq.clone());
83+
let simple = Simple::new(tester.workq);
8484
let mut num = 6;
8585
while num < 250 {
8686
simple.run(num, TOTAL_ITERS / num);
@@ -147,7 +147,7 @@ struct ThreadTests {
147147
high_command: Sender<Command>,
148148

149149
/// A work queue for the main runners.
150-
workq: Arc<WorkQueue>,
150+
workq: &'static WorkQueue,
151151

152152
/// The test also all return their result to the main. The threads Send, the main running
153153
/// receives.
@@ -163,15 +163,7 @@ impl ThreadTests {
163163
let (low_send, low_recv) = bounded(1);
164164
let (high_send, high_recv) = bounded(1);
165165

166-
let workq = Arc::new(
167-
WorkQueueBuilder::new()
168-
.set_priority(5)
169-
.set_no_yield(true)
170-
.start(WORK_STACK.init_once(()).unwrap()),
171-
);
172-
173-
// Leak the workqueue so it doesn't get dropped.
174-
let _ = Arc::into_raw(workq.clone());
166+
let workq = WORKQ.start();
175167

176168
let mut result = Self {
177169
sems: &SEMS,
@@ -581,20 +573,20 @@ enum TestResult {
581573

582574
/// The Simple test just does a ping pong test using manually submitted work.
583575
struct Simple {
584-
workq: Arc<WorkQueue>,
576+
workq: &'static WorkQueue,
585577
}
586578

587579
impl Simple {
588-
fn new(workq: Arc<WorkQueue>) -> Self {
580+
fn new(workq: &'static WorkQueue) -> Self {
589581
Self { workq }
590582
}
591583

592584
fn run(&self, workers: usize, iterations: usize) {
593585
// printkln!("Running Simple");
594-
let main = Work::new(SimpleMain::new(workers * iterations, self.workq.clone()));
586+
let main = Work::new(SimpleMain::new(workers * iterations, self.workq));
595587

596588
let children: VecDeque<_> = (0..workers)
597-
.map(|n| Work::new(SimpleWorker::new(main.clone(), self.workq.clone(), n)))
589+
.map(|n| Work::new(SimpleWorker::new(main.clone(), self.workq, n)))
598590
.collect();
599591

600592
let mut locked = main.action().locked.lock().unwrap();
@@ -603,7 +595,7 @@ impl Simple {
603595

604596
let start = now();
605597
// Fire off main, which will run everything.
606-
Work::submit_to_queue(main.clone(), &self.workq).unwrap();
598+
Work::submit_to_queue(main.clone(), self.workq).unwrap();
607599

608600
// And wait for the completion semaphore.
609601
main.action().done.take(Forever).unwrap();
@@ -642,12 +634,12 @@ impl Simple {
642634
/// A simple worker. When run, it submits the main worker to do the next work.
643635
struct SimpleWorker {
644636
main: PinWeak<Work<SimpleMain>>,
645-
workq: Arc<WorkQueue>,
637+
workq: &'static WorkQueue,
646638
_id: usize,
647639
}
648640

649641
impl SimpleWorker {
650-
fn new(main: Pin<Arc<Work<SimpleMain>>>, workq: Arc<WorkQueue>, id: usize) -> Self {
642+
fn new(main: Pin<Arc<Work<SimpleMain>>>, workq: &'static WorkQueue, id: usize) -> Self {
651643
Self {
652644
main: PinWeak::downgrade(main),
653645
workq,
@@ -660,7 +652,7 @@ impl SimpleAction for SimpleWorker {
660652
fn act(self: Pin<&Self>) {
661653
// Each time we are run, fire the main worker back up.
662654
let main = self.main.upgrade().unwrap();
663-
Work::submit_to_queue(main.clone(), &self.workq).unwrap();
655+
Work::submit_to_queue(main.clone(), self.workq).unwrap();
664656
}
665657
}
666658

@@ -670,7 +662,7 @@ impl SimpleAction for SimpleWorker {
670662
struct SimpleMain {
671663
/// All of the work items.
672664
locked: SpinMutex<Locked>,
673-
workq: Arc<WorkQueue>,
665+
workq: &'static WorkQueue,
674666
done: Semaphore,
675667
}
676668

@@ -690,12 +682,12 @@ impl SimpleAction for SimpleMain {
690682
lock.count -= 1;
691683
drop(lock);
692684

693-
Work::submit_to_queue(worker.clone(), &self.workq).unwrap();
685+
Work::submit_to_queue(worker.clone(), self.workq).unwrap();
694686
}
695687
}
696688

697689
impl SimpleMain {
698-
fn new(count: usize, workq: Arc<WorkQueue>) -> Self {
690+
fn new(count: usize, workq: &'static WorkQueue) -> Self {
699691
Self {
700692
locked: SpinMutex::new(Locked::new(count)),
701693
done: Semaphore::new(0, 1),
@@ -812,9 +804,7 @@ impl<'a> BenchTimer<'a> {
812804
}
813805
}
814806

815-
kobj_define! {
816-
static WORK_STACK: ThreadStack<WORK_STACK_SIZE>;
817-
}
807+
define_work_queue!(WORKQ, WORK_STACK_SIZE, priority = 5, no_yield = true);
818808

819809
static SEMS: [Semaphore; NUM_THREADS] = [const { Semaphore::new(0, u32::MAX) }; NUM_THREADS];
820810
static BACK_SEMS: [Semaphore; NUM_THREADS] = [const { Semaphore::new(0, u32::MAX) }; NUM_THREADS];

zephyr/src/lib.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,10 @@
3939
//! level operation that is still quite useful in regular code.
4040
//! - [`timer`]: Rust interfaces to Zephyr timers. These timers can be used either by registering a
4141
//! callback, or polled or waited for for an elapsed time.
42-
//! - [`work`]: Zephyr work queues for Rust. The [`work::WorkQueueBuilder`] and resulting
42+
//! - [`work`]: Zephyr work queues for Rust. The [`define_work_queue`] macro and resulting
4343
//! [`work::WorkQueue`] allow creation of Zephyr work queues to be used from Rust. The
4444
//! [`work::Work`] item had an action that will be invoked by the work queue, and can be manually
4545
//! submitted when needed.
46-
//! - [`kio`]: An implementation of an async executor built around triggerable work queues in
47-
//! Zephyr. Although there is a bit more overhead to this executor, it is compatible with many of
48-
//! the Zephyr synchronization types, and many of these [`sys::sync::Semaphore`], and
49-
//! [`sync::channel`] will provide `_async` variants of most of the blocking operations. These
50-
//! will return a `Future`, and can be used from async code started by the [`spawn`] function.
51-
//! In addition, because Zephyr's work queues do not work well with Zephyr's Mutex type, this is
52-
//! also a [`kio::sync::Mutex`] type that works with async.
5346
//! - [`logging`]: A logging backend for Rust on Zephyr. This will log to either `printk` or
5447
//! through Zephyr's logging framework.
5548
//!

0 commit comments

Comments
 (0)