Skip to content

Commit 0e5eb50

Browse files
authored
Merge pull request #1845 from hermit-os/async-executor
feat: use async-executor
2 parents 7144572 + 0324aee commit 0e5eb50

File tree

7 files changed

+109
-46
lines changed

7 files changed

+109
-46
lines changed

Cargo.lock

Lines changed: 64 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ virtio = { package = "virtio-spec", version = "0.3", optional = true, features =
110110
ahash = { version = "0.8", default-features = false }
111111
align-address = "0.3"
112112
anstyle = { version = "1", default-features = false }
113+
async-executor = { git = "https://github.com/hermit-os/async-executor.git", branch = "no_std", default-features = false, features = ["static"] }
113114
async-lock = { version = "3.4.1", default-features = false }
114115
async-trait = "0.1.89"
115116
bit_field = "0.10"

src/arch/aarch64/kernel/core_local.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
use alloc::boxed::Box;
2-
use alloc::collections::vec_deque::VecDeque;
32
use core::arch::asm;
4-
use core::cell::{Cell, RefCell, RefMut};
3+
use core::cell::Cell;
54
use core::ptr;
65
use core::sync::atomic::Ordering;
76

7+
use async_executor::StaticExecutor;
88
#[cfg(feature = "smp")]
99
use hermit_sync::InterruptTicketMutex;
10+
use hermit_sync::{RawRwSpinLock, RawSpinMutex};
1011

1112
use super::CPU_ONLINE;
1213
use super::interrupts::{IRQ_COUNTERS, IrqStatistics};
13-
use crate::executor::task::AsyncTask;
1414
#[cfg(feature = "smp")]
1515
use crate::scheduler::SchedulerInput;
1616
use crate::scheduler::{CoreId, PerCoreScheduler};
@@ -23,8 +23,8 @@ pub(crate) struct CoreLocal {
2323
scheduler: Cell<*mut PerCoreScheduler>,
2424
/// Interface to the interrupt counters
2525
irq_statistics: &'static IrqStatistics,
26-
/// Queue of async tasks
27-
async_tasks: RefCell<VecDeque<AsyncTask>>,
26+
/// The core-local async executor.
27+
ex: StaticExecutor<RawSpinMutex, RawRwSpinLock>,
2828
/// Queues to handle incoming requests from the other cores
2929
#[cfg(feature = "smp")]
3030
pub scheduler_input: InterruptTicketMutex<SchedulerInput>,
@@ -46,7 +46,7 @@ impl CoreLocal {
4646
core_id,
4747
scheduler: Cell::new(ptr::null_mut()),
4848
irq_statistics,
49-
async_tasks: RefCell::new(VecDeque::new()),
49+
ex: StaticExecutor::new(),
5050
#[cfg(feature = "smp")]
5151
scheduler_input: InterruptTicketMutex::new(SchedulerInput::new()),
5252
};
@@ -96,8 +96,8 @@ pub(crate) fn core_scheduler() -> &'static mut PerCoreScheduler {
9696
unsafe { CoreLocal::get().scheduler.get().as_mut().unwrap() }
9797
}
9898

99-
pub(crate) fn async_tasks() -> RefMut<'static, VecDeque<AsyncTask>> {
100-
CoreLocal::get().async_tasks.borrow_mut()
99+
pub(crate) fn ex() -> &'static StaticExecutor<RawSpinMutex, RawRwSpinLock> {
100+
&CoreLocal::get().ex
101101
}
102102

103103
pub(crate) fn set_core_scheduler(scheduler: *mut PerCoreScheduler) {

src/arch/riscv64/kernel/core_local.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
use alloc::boxed::Box;
2-
use alloc::collections::vec_deque::VecDeque;
32
use core::arch::asm;
4-
use core::cell::{Cell, RefCell, RefMut};
3+
use core::cell::Cell;
54
use core::ptr;
65
use core::sync::atomic::Ordering;
76

7+
use async_executor::StaticExecutor;
88
#[cfg(feature = "smp")]
99
use hermit_sync::InterruptTicketMutex;
10+
use hermit_sync::{RawRwSpinLock, RawSpinMutex};
1011

1112
use crate::arch::riscv64::kernel::CPU_ONLINE;
12-
use crate::executor::task::AsyncTask;
1313
#[cfg(feature = "smp")]
1414
use crate::scheduler::SchedulerInput;
1515
use crate::scheduler::{CoreId, PerCoreScheduler};
@@ -21,8 +21,8 @@ pub struct CoreLocal {
2121
scheduler: Cell<*mut PerCoreScheduler>,
2222
/// start address of the kernel stack
2323
pub kernel_stack: Cell<u64>,
24-
/// Queue of async tasks
25-
async_tasks: RefCell<VecDeque<AsyncTask>>,
24+
/// The core-local async executor.
25+
ex: StaticExecutor<RawSpinMutex, RawRwSpinLock>,
2626
/// Queues to handle incoming requests from the other cores
2727
#[cfg(feature = "smp")]
2828
pub scheduler_input: InterruptTicketMutex<SchedulerInput>,
@@ -41,7 +41,7 @@ impl CoreLocal {
4141
core_id,
4242
scheduler: Cell::new(ptr::null_mut()),
4343
kernel_stack: Cell::new(0),
44-
async_tasks: RefCell::new(VecDeque::new()),
44+
ex: StaticExecutor::new(),
4545
#[cfg(feature = "smp")]
4646
scheduler_input: InterruptTicketMutex::new(SchedulerInput::new()),
4747
};
@@ -84,6 +84,6 @@ pub fn set_core_scheduler(scheduler: *mut PerCoreScheduler) {
8484
CoreLocal::get().scheduler.set(scheduler);
8585
}
8686

87-
pub(crate) fn async_tasks() -> RefMut<'static, VecDeque<AsyncTask>> {
88-
CoreLocal::get().async_tasks.borrow_mut()
87+
pub(crate) fn ex() -> &'static StaticExecutor<RawSpinMutex, RawRwSpinLock> {
88+
&CoreLocal::get().ex
8989
}

src/arch/x86_64/kernel/core_local.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
use alloc::boxed::Box;
2-
use alloc::collections::vec_deque::VecDeque;
32
use core::arch::asm;
4-
use core::cell::{Cell, RefCell, RefMut};
3+
use core::cell::Cell;
54
#[cfg(feature = "smp")]
65
use core::sync::atomic::AtomicBool;
76
use core::sync::atomic::Ordering;
87
use core::{mem, ptr};
98

9+
use async_executor::StaticExecutor;
1010
#[cfg(feature = "smp")]
1111
use hermit_sync::InterruptTicketMutex;
12+
use hermit_sync::{RawRwSpinLock, RawSpinMutex};
1213
use x86_64::VirtAddr;
1314
use x86_64::registers::model_specific::GsBase;
1415
use x86_64::structures::tss::TaskStateSegment;
1516

1617
use super::CPU_ONLINE;
1718
use super::interrupts::{IRQ_COUNTERS, IrqStatistics};
18-
use crate::executor::task::AsyncTask;
1919
#[cfg(feature = "smp")]
2020
use crate::scheduler::SchedulerInput;
2121
use crate::scheduler::{CoreId, PerCoreScheduler};
@@ -32,8 +32,8 @@ pub(crate) struct CoreLocal {
3232
pub kernel_stack: Cell<*mut u8>,
3333
/// Interface to the interrupt counters
3434
irq_statistics: &'static IrqStatistics,
35-
/// Queue of async tasks
36-
async_tasks: RefCell<VecDeque<AsyncTask>>,
35+
/// The core-local async executor.
36+
ex: StaticExecutor<RawSpinMutex, RawRwSpinLock>,
3737
#[cfg(feature = "smp")]
3838
pub hlt: AtomicBool,
3939
/// Queues to handle incoming requests from the other cores
@@ -61,7 +61,7 @@ impl CoreLocal {
6161
tss: Cell::new(ptr::null_mut()),
6262
kernel_stack: Cell::new(ptr::null_mut()),
6363
irq_statistics,
64-
async_tasks: RefCell::new(VecDeque::new()),
64+
ex: StaticExecutor::new(),
6565
#[cfg(feature = "smp")]
6666
hlt: AtomicBool::new(false),
6767
#[cfg(feature = "smp")]
@@ -110,8 +110,8 @@ pub(crate) fn core_scheduler() -> &'static mut PerCoreScheduler {
110110
unsafe { CoreLocal::get().scheduler.get().as_mut().unwrap() }
111111
}
112112

113-
pub(crate) fn async_tasks() -> RefMut<'static, VecDeque<AsyncTask>> {
114-
CoreLocal::get().async_tasks.borrow_mut()
113+
pub(crate) fn ex() -> &'static StaticExecutor<RawSpinMutex, RawRwSpinLock> {
114+
&CoreLocal::get().ex
115115
}
116116

117117
pub(crate) fn set_core_scheduler(scheduler: *mut PerCoreScheduler) {

src/executor/mod.rs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use hermit_sync::without_interrupts;
1919
#[cfg(any(feature = "tcp", feature = "udp"))]
2020
use smoltcp::time::Instant;
2121

22-
use crate::arch::core_local::*;
22+
use crate::arch::core_local;
2323
use crate::errno::Errno;
2424
use crate::executor::task::AsyncTask;
2525
use crate::io;
@@ -94,16 +94,13 @@ impl Wake for TaskNotify {
9494
}
9595

9696
pub(crate) fn run() {
97-
let mut cx = Context::from_waker(Waker::noop());
98-
9997
without_interrupts(|| {
100-
// FIXME(mkroening): Not all tasks register wakers and never sleep
101-
for _ in 0..({ async_tasks().len() }) {
102-
let mut task = { async_tasks().pop_front().unwrap() };
103-
trace!("Run async task {}", task.id());
104-
105-
if task.poll(&mut cx).is_pending() {
106-
async_tasks().push_back(task);
98+
// FIXME: We currently have no more than 3 tasks at a time, so this is fine.
99+
// Ideally, we would set this value to 200, but the network task currently immediately wakes up again.
100+
// This would lead to the network task being polled 200 times back to back, slowing things down considerably.
101+
for _ in 0..3 {
102+
if !core_local::ex().try_tick() {
103+
break;
107104
}
108105
}
109106
});
@@ -118,7 +115,7 @@ pub(crate) fn spawn<F>(future: F)
118115
where
119116
F: Future<Output = ()> + Send + 'static,
120117
{
121-
without_interrupts(|| async_tasks().push_back(AsyncTask::new(future)));
118+
core_local::ex().spawn(AsyncTask::new(future)).detach();
122119
}
123120

124121
pub fn init() {
@@ -177,7 +174,7 @@ where
177174
} else {
178175
None
179176
};
180-
core_scheduler().add_network_timer(
177+
core_local::core_scheduler().add_network_timer(
181178
delay.map(|d| crate::arch::processor::get_timer_ticks() + d),
182179
);
183180
}
@@ -203,7 +200,7 @@ where
203200
} else {
204201
None
205202
};
206-
core_scheduler().add_network_timer(
203+
core_local::core_scheduler().add_network_timer(
207204
delay.map(|d| crate::arch::processor::get_timer_ticks() + d),
208205
);
209206
}
@@ -230,7 +227,7 @@ where
230227
};
231228

232229
if delay.unwrap_or(10_000_000) > 10_000 {
233-
core_scheduler().add_network_timer(
230+
core_local::core_scheduler().add_network_timer(
234231
delay.map(|d| crate::arch::processor::get_timer_ticks() + d),
235232
);
236233
let wakeup_time =

src/executor/task.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use core::sync::atomic::{AtomicU32, Ordering};
88
use core::task::{Context, Poll};
99

1010
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
11-
pub(crate) struct AsyncTaskId(u32);
11+
struct AsyncTaskId(u32);
1212

1313
impl fmt::Display for AsyncTaskId {
1414
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -25,22 +25,23 @@ impl AsyncTaskId {
2525

2626
pub(crate) struct AsyncTask {
2727
id: AsyncTaskId,
28-
future: Pin<Box<dyn Future<Output = ()>>>,
28+
future: Pin<Box<dyn Future<Output = ()> + Send>>,
2929
}
3030

3131
impl AsyncTask {
32-
pub fn new(future: impl Future<Output = ()> + 'static) -> AsyncTask {
32+
pub fn new(future: impl Future<Output = ()> + Send + 'static) -> AsyncTask {
3333
AsyncTask {
3434
id: AsyncTaskId::new(),
3535
future: Box::pin(future),
3636
}
3737
}
38+
}
3839

39-
pub fn id(&self) -> AsyncTaskId {
40-
self.id
41-
}
40+
impl Future for AsyncTask {
41+
type Output = ();
4242

43-
pub fn poll(&mut self, context: &mut Context<'_>) -> Poll<()> {
44-
self.future.as_mut().poll(context)
43+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
44+
trace!("Run async task {}", self.id);
45+
self.as_mut().future.as_mut().poll(cx)
4546
}
4647
}

0 commit comments

Comments
 (0)