aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-02-03 04:30:11 +0100
committerDario Nieuwenhuis <[email protected]>2021-02-03 04:30:11 +0100
commit4192e526298eb02c32727c765ae6d7ad4f933e2b (patch)
treea0f6363479da755ef5048efdc31c852af5d9d1a8
parentedca627286fff5234cb91535a7d9627af0c0eeaf (diff)
Update embassy-std to new executor api
-rw-r--r--.gitignore2
-rw-r--r--embassy-std/src/lib.rs132
-rw-r--r--embassy/src/executor/mod.rs18
-rw-r--r--embassy/src/executor/raw.rs22
4 files changed, 104 insertions, 70 deletions
diff --git a/.gitignore b/.gitignore
index 25d18d5aa..784c6bac0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,3 @@
1/target 1target
2Cargo.lock 2Cargo.lock
3third_party 3third_party
diff --git a/embassy-std/src/lib.rs b/embassy-std/src/lib.rs
index 2fb814b4d..009ba028d 100644
--- a/embassy-std/src/lib.rs
+++ b/embassy-std/src/lib.rs
@@ -1,9 +1,10 @@
1use embassy::executor::Executor; 1use embassy::executor::{raw, Spawner};
2use embassy::time::TICKS_PER_SECOND; 2use embassy::time::TICKS_PER_SECOND;
3use embassy::time::{Alarm, Clock}; 3use embassy::time::{Alarm, Clock};
4use embassy::util::Forever;
5use rand_core::{OsRng, RngCore}; 4use rand_core::{OsRng, RngCore};
5use std::marker::PhantomData;
6use std::mem::MaybeUninit; 6use std::mem::MaybeUninit;
7use std::ptr;
7use std::sync::{Condvar, Mutex}; 8use std::sync::{Condvar, Mutex};
8use std::time::{Duration as StdDuration, Instant as StdInstant}; 9use std::time::{Duration as StdDuration, Instant as StdInstant};
9 10
@@ -29,7 +30,8 @@ static mut ALARM_AT: u64 = u64::MAX;
29 30
30pub struct StdAlarm; 31pub struct StdAlarm;
31impl Alarm for StdAlarm { 32impl Alarm for StdAlarm {
32 fn set_callback(&self, _callback: fn()) {} 33 fn set_callback(&self, _callback: fn(*mut ()), _ctx: *mut ()) {}
34
33 fn set(&self, timestamp: u64) { 35 fn set(&self, timestamp: u64) {
34 unsafe { ALARM_AT = timestamp } 36 unsafe { ALARM_AT = timestamp }
35 } 37 }
@@ -39,57 +41,91 @@ impl Alarm for StdAlarm {
39 } 41 }
40} 42}
41 43
42static EXECUTOR: Forever<Executor> = Forever::new(); 44struct Signaler {
43 45 mutex: Mutex<bool>,
44lazy_static::lazy_static! { 46 condvar: Condvar,
45 static ref MUTEX: Mutex<bool> = Mutex::new(false);
46 static ref CONDVAR: Condvar = Condvar::new();
47} 47}
48 48
49pub fn init() -> &'static Executor { 49impl Signaler {
50 unsafe { 50 fn new() -> Self {
51 CLOCK_ZERO.as_mut_ptr().write(StdInstant::now()); 51 Self {
52 embassy::time::set_clock(&StdClock); 52 mutex: Mutex::new(false),
53 embassy::rand::set_rand(&StdRand); 53 condvar: Condvar::new(),
54 54 }
55 EXECUTOR.put(Executor::new_with_alarm(&StdAlarm, || {
56 let mut signaled = MUTEX.lock().unwrap();
57 *signaled = true;
58 CONDVAR.notify_one();
59 }))
60 } 55 }
61}
62 56
63pub fn run(executor: &'static Executor) -> ! { 57 fn wait(&self) {
64 unsafe { 58 let mut signaled = self.mutex.lock().unwrap();
65 loop { 59 while !*signaled {
66 executor.run(); 60 let alarm_at = unsafe { ALARM_AT };
67 61 if alarm_at == u64::MAX {
68 let mut signaled = MUTEX.lock().unwrap(); 62 signaled = self.condvar.wait(signaled).unwrap();
69 while !*signaled { 63 } else {
70 let alarm_at = ALARM_AT; 64 let now = StdClock.now();
71 if alarm_at == u64::MAX { 65 if now >= alarm_at {
72 signaled = CONDVAR.wait(signaled).unwrap(); 66 break;
73 } else { 67 }
74 let now = StdClock.now(); 68
75 if now >= alarm_at { 69 let left = alarm_at - now;
76 break; 70 let dur = StdDuration::new(
77 } 71 left / (TICKS_PER_SECOND as u64),
78 72 (left % (TICKS_PER_SECOND as u64) * 1_000_000_000 / (TICKS_PER_SECOND as u64))
79 let left = alarm_at - now; 73 as u32,
80 let dur = StdDuration::new( 74 );
81 left / (TICKS_PER_SECOND as u64), 75 let (signaled2, timeout) = self.condvar.wait_timeout(signaled, dur).unwrap();
82 (left % (TICKS_PER_SECOND as u64) * 1_000_000_000 76 signaled = signaled2;
83 / (TICKS_PER_SECOND as u64)) as u32, 77 if timeout.timed_out() {
84 ); 78 break;
85 let (signaled2, timeout) = CONDVAR.wait_timeout(signaled, dur).unwrap();
86 signaled = signaled2;
87 if timeout.timed_out() {
88 break;
89 }
90 } 79 }
91 } 80 }
92 *signaled = false; 81 }
82 *signaled = false;
83 }
84
85 fn signal(ctx: *mut ()) {
86 let this = unsafe { &*(ctx as *mut Self) };
87 let mut signaled = this.mutex.lock().unwrap();
88 *signaled = true;
89 this.condvar.notify_one();
90 }
91}
92
93pub struct Executor {
94 inner: raw::Executor,
95 not_send: PhantomData<*mut ()>,
96 signaler: Signaler,
97}
98
99impl Executor {
100 pub fn new() -> Self {
101 unsafe {
102 CLOCK_ZERO.as_mut_ptr().write(StdInstant::now());
103 embassy::time::set_clock(&StdClock);
104 embassy::rand::set_rand(&StdRand);
105 }
106
107 Self {
108 inner: raw::Executor::new(Signaler::signal, ptr::null_mut()),
109 not_send: PhantomData,
110 signaler: Signaler::new(),
111 }
112 }
113
114 pub fn set_alarm(&mut self, alarm: &'static dyn Alarm) {
115 self.inner.set_alarm(alarm);
116 }
117
118 /// Runs the executor.
119 ///
120 /// This function never returns.
121 pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
122 self.inner.set_signal_ctx(&self.signaler as *const _ as _);
123
124 init(unsafe { self.inner.spawner() });
125
126 loop {
127 unsafe { self.inner.run_queued() };
128 self.signaler.wait();
93 } 129 }
94 } 130 }
95} 131}
diff --git a/embassy/src/executor/mod.rs b/embassy/src/executor/mod.rs
index 7c74fa583..6e4bded09 100644
--- a/embassy/src/executor/mod.rs
+++ b/embassy/src/executor/mod.rs
@@ -113,13 +113,6 @@ pub struct Spawner {
113} 113}
114 114
115impl Spawner { 115impl Spawner {
116 fn new(executor: &'static raw::Executor) -> Self {
117 Self {
118 executor,
119 not_send: PhantomData,
120 }
121 }
122
123 pub fn spawn<F>(&self, token: SpawnToken<F>) -> Result<(), SpawnError> { 116 pub fn spawn<F>(&self, token: SpawnToken<F>) -> Result<(), SpawnError> {
124 let task = token.raw_task; 117 let task = token.raw_task;
125 mem::forget(token); 118 mem::forget(token);
@@ -165,13 +158,6 @@ unsafe impl Sync for SendSpawner {}
165/// 158///
166/// If you want to spawn tasks from another thread, use [SendSpawner]. 159/// If you want to spawn tasks from another thread, use [SendSpawner].
167impl SendSpawner { 160impl SendSpawner {
168 fn new(executor: &'static raw::Executor) -> Self {
169 Self {
170 executor,
171 not_send: PhantomData,
172 }
173 }
174
175 pub fn spawn<F: Send>(&self, token: SpawnToken<F>) -> Result<(), SpawnError> { 161 pub fn spawn<F: Send>(&self, token: SpawnToken<F>) -> Result<(), SpawnError> {
176 let header = token.raw_task; 162 let header = token.raw_task;
177 mem::forget(token); 163 mem::forget(token);
@@ -207,7 +193,7 @@ impl Executor {
207 /// 193 ///
208 /// This function never returns. 194 /// This function never returns.
209 pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! { 195 pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
210 init(Spawner::new(&self.inner)); 196 init(unsafe { self.inner.spawner() });
211 197
212 loop { 198 loop {
213 unsafe { self.inner.run_queued() }; 199 unsafe { self.inner.run_queued() };
@@ -253,7 +239,7 @@ impl<I: OwnedInterrupt> IrqExecutor<I> {
253 pub fn start(&'static mut self, init: impl FnOnce(Spawner) + Send) { 239 pub fn start(&'static mut self, init: impl FnOnce(Spawner) + Send) {
254 self.irq.disable(); 240 self.irq.disable();
255 241
256 init(Spawner::new(&self.inner)); 242 init(unsafe { self.inner.spawner() });
257 243
258 self.irq.set_handler( 244 self.irq.set_handler(
259 |ctx| unsafe { 245 |ctx| unsafe {
diff --git a/embassy/src/executor/raw.rs b/embassy/src/executor/raw.rs
index 927b6a421..1f7e48f53 100644
--- a/embassy/src/executor/raw.rs
+++ b/embassy/src/executor/raw.rs
@@ -1,5 +1,6 @@
1use core::cell::Cell; 1use core::cell::Cell;
2use core::cmp::min; 2use core::cmp::min;
3use core::marker::PhantomData;
3use core::ptr; 4use core::ptr;
4use core::ptr::NonNull; 5use core::ptr::NonNull;
5use core::sync::atomic::{AtomicU32, Ordering}; 6use core::sync::atomic::{AtomicU32, Ordering};
@@ -67,7 +68,7 @@ impl Task {
67 } 68 }
68} 69}
69 70
70pub(crate) struct Executor { 71pub struct Executor {
71 run_queue: RunQueue, 72 run_queue: RunQueue,
72 timer_queue: TimerQueue, 73 timer_queue: TimerQueue,
73 signal_fn: fn(*mut ()), 74 signal_fn: fn(*mut ()),
@@ -76,7 +77,7 @@ pub(crate) struct Executor {
76} 77}
77 78
78impl Executor { 79impl Executor {
79 pub(crate) const fn new(signal_fn: fn(*mut ()), signal_ctx: *mut ()) -> Self { 80 pub const fn new(signal_fn: fn(*mut ()), signal_ctx: *mut ()) -> Self {
80 Self { 81 Self {
81 run_queue: RunQueue::new(), 82 run_queue: RunQueue::new(),
82 timer_queue: TimerQueue::new(), 83 timer_queue: TimerQueue::new(),
@@ -86,23 +87,27 @@ impl Executor {
86 } 87 }
87 } 88 }
88 89
89 pub(crate) fn set_alarm(&mut self, alarm: &'static dyn Alarm) { 90 pub fn set_alarm(&mut self, alarm: &'static dyn Alarm) {
90 self.alarm = Some(alarm); 91 self.alarm = Some(alarm);
91 } 92 }
92 93
94 pub fn set_signal_ctx(&mut self, signal_ctx: *mut ()) {
95 self.signal_ctx = signal_ctx;
96 }
97
93 unsafe fn enqueue(&self, item: *mut Task) { 98 unsafe fn enqueue(&self, item: *mut Task) {
94 if self.run_queue.enqueue(item) { 99 if self.run_queue.enqueue(item) {
95 (self.signal_fn)(self.signal_ctx) 100 (self.signal_fn)(self.signal_ctx)
96 } 101 }
97 } 102 }
98 103
99 pub(crate) unsafe fn spawn(&'static self, task: NonNull<Task>) { 104 pub unsafe fn spawn(&'static self, task: NonNull<Task>) {
100 let task = task.as_ref(); 105 let task = task.as_ref();
101 task.executor.set(self); 106 task.executor.set(self);
102 self.enqueue(task as *const _ as _); 107 self.enqueue(task as *const _ as _);
103 } 108 }
104 109
105 pub(crate) unsafe fn run_queued(&self) { 110 pub unsafe fn run_queued(&'static self) {
106 if self.alarm.is_some() { 111 if self.alarm.is_some() {
107 self.timer_queue.dequeue_expired(Instant::now(), |p| { 112 self.timer_queue.dequeue_expired(Instant::now(), |p| {
108 p.as_ref().enqueue(); 113 p.as_ref().enqueue();
@@ -138,6 +143,13 @@ impl Executor {
138 alarm.set(next_expiration.as_ticks()); 143 alarm.set(next_expiration.as_ticks());
139 } 144 }
140 } 145 }
146
147 pub unsafe fn spawner(&'static self) -> super::Spawner {
148 super::Spawner {
149 executor: self,
150 not_send: PhantomData,
151 }
152 }
141} 153}
142 154
143pub use super::waker::task_from_waker; 155pub use super::waker::task_from_waker;