@@ -12,14 +12,16 @@ use core::task::{Context, Poll, Waker};
1212use core:: time:: Duration ;
1313
1414use futures:: channel:: oneshot;
15- use futures:: task:: AtomicWaker ;
1615use spin:: Mutex ;
1716use uefi:: proto:: console:: text:: Color ;
1817
18+ use crate :: os:: executor:: event:: { Event , EventTrigger } ;
1919use crate :: os:: send_wrapper:: SendWrapper ;
2020use crate :: os:: timer:: Timer ;
2121use crate :: os:: ui:: DrawArea ;
2222
23+ pub mod event;
24+
2325type BoxFuture = SendWrapper < Pin < Box < dyn Future < Output = ( ) > + ' static > > > ;
2426
2527struct Task {
@@ -55,11 +57,9 @@ impl Wake for Task {
5557 }
5658}
5759
58- pub ( super ) type WrappedWaker = Arc < AtomicWaker > ;
59-
6060struct TimedWait {
6161 wake_at : i64 ,
62- waker : WrappedWaker ,
62+ event : EventTrigger ,
6363}
6464
6565impl PartialEq for TimedWait {
@@ -99,7 +99,7 @@ static EXECUTOR: Mutex<Executor> = Mutex::new(Executor {
9999} ) ;
100100
101101pub struct Executor {
102- wake_on_interrupt : Vec < Waker > ,
102+ wake_on_interrupt : Vec < EventTrigger > ,
103103 timed_wait : BinaryHeap < TimedWait > ,
104104 ready_tasks : VecDeque < Arc < Task > > ,
105105 tasks : Vec < Arc < Task > > ,
@@ -209,7 +209,7 @@ impl Executor {
209209 let mut do_wake = |force_interrupt_wake| {
210210 // Wake timed-waiting tasks.
211211 loop {
212- let waker = {
212+ let event = {
213213 let mut ex = EXECUTOR . lock ( ) ;
214214 let Some ( w) = ex. timed_wait . peek ( ) else {
215215 break ;
@@ -218,52 +218,53 @@ impl Executor {
218218 break ;
219219 }
220220 let w = ex. timed_wait . pop ( ) . unwrap ( ) ;
221- w. waker
221+ w. event
222222 } ;
223- waker . wake ( ) ;
223+ event . trigger ( ) ;
224224 }
225225 // Since we don't notice interrupts that happened while we are not hlt-ing,
226226 // make sure that we wake up all the interrupt-based waiting tasks every at
227227 // most INTERRUPT_MICROS micros to make it unlikely to miss interrupts.
228228 if last_interrupt_wakeup + INTERRUPT_MICROS <= Timer :: micros ( ) || force_interrupt_wake {
229229 last_interrupt_wakeup = Timer :: micros ( ) ;
230230 let to_wake = core:: mem:: take ( & mut EXECUTOR . lock ( ) . wake_on_interrupt ) ;
231- for w in to_wake {
232- w . wake ( ) ;
231+ for e in to_wake {
232+ e . trigger ( ) ;
233233 }
234234 }
235235 } ;
236236
237237 loop {
238238 do_wake ( false ) ;
239239 let task = EXECUTOR . lock ( ) . ready_tasks . pop_front ( ) ;
240- if let Some ( task) = task {
241- // It is possible for a done task to end up in the queue (if it wakes
242- // itself during execution). If that happens, we just remove it from
243- // the queue here.
244- if task. done . load ( Ordering :: Relaxed ) {
245- continue ;
246- }
247- task. in_queue . store ( false , Ordering :: Relaxed ) ;
248- let waker = Waker :: from ( task. clone ( ) ) ;
249- let mut context = Context :: from_waker ( & waker) ;
250- let mut fut = task. future . try_lock ( ) . unwrap ( ) ;
251- let begin = Timer :: micros ( ) ;
252- let done = fut. 0 . as_mut ( ) . poll ( & mut context) ;
253- let end = Timer :: micros ( ) ;
254- task. micros
255- . fetch_add ( ( end - begin) as u64 , Ordering :: Relaxed ) ;
256- if done. is_ready ( ) {
257- task. done . swap ( true , Ordering :: Relaxed ) ;
258- }
259- } else {
240+ let Some ( task) = task else {
260241 // If we don't have anything ready, sleep until the next interrupt.
261242 // SAFETY: hlt is available on all reasonable x86 processors and has no safety
262243 // requirements.
263244 unsafe {
264245 core:: arch:: asm!( "hlt" ) ;
265246 }
266247 do_wake ( true ) ;
248+ continue ;
249+ } ;
250+
251+ // It is possible for a done task to end up in the queue (if it wakes
252+ // itself during execution). If that happens, we just remove it from
253+ // the queue here.
254+ if task. done . load ( Ordering :: Relaxed ) {
255+ continue ;
256+ }
257+ task. in_queue . store ( false , Ordering :: Relaxed ) ;
258+ let waker = Waker :: from ( task. clone ( ) ) ;
259+ let mut context = Context :: from_waker ( & waker) ;
260+ let mut fut = task. future . try_lock ( ) . unwrap ( ) ;
261+ let begin = Timer :: micros ( ) ;
262+ let done = fut. 0 . as_mut ( ) . poll ( & mut context) ;
263+ let end = Timer :: micros ( ) ;
264+ task. micros
265+ . fetch_add ( ( end - begin) as u64 , Ordering :: Relaxed ) ;
266+ if done. is_ready ( ) {
267+ task. done . swap ( true , Ordering :: Relaxed ) ;
267268 }
268269 }
269270 }
@@ -283,41 +284,23 @@ impl Executor {
283284 } )
284285 }
285286
287+ // Wakes a task as soon as *any* interrupt is received.
288+ pub fn wait_for_interrupt ( ) -> impl Future < Output = ( ) > {
289+ let event = Event :: new ( ) ;
290+ EXECUTOR . lock ( ) . wake_on_interrupt . push ( event. trigger ( ) ) ;
291+ event
292+ }
293+
286294 // Note: there are no guarantees on whether the amount of time we will sleep for
287295 // will be exceeded.
288296 pub fn sleep ( time : Duration ) -> impl Future < Output = ( ) > {
289297 let tgt = Timer :: micros ( ) + time. as_micros ( ) as i64 ;
290- let mut ww = None ;
291- poll_fn ( move |cx| {
292- let now = Timer :: micros ( ) ;
293- if now >= tgt {
294- Poll :: Ready ( ( ) )
295- } else {
296- Self :: wake_at_micros ( tgt, cx. waker ( ) , & mut ww) ;
297- Poll :: Pending
298- }
299- } )
300- }
301-
302- // Wakes a task as soon as *any* interrupt is received.
303- pub ( super ) fn wake_on_interrupt ( waker : & Waker ) {
304- EXECUTOR . lock ( ) . wake_on_interrupt . push ( waker. clone ( ) ) ;
305- }
306-
307- pub ( super ) fn wake_at_micros (
308- micros : i64 ,
309- waker : & Waker ,
310- previous_waker : & mut Option < WrappedWaker > ,
311- ) {
312- if !previous_waker. is_some ( ) {
313- let w = Arc :: new ( AtomicWaker :: new ( ) ) ;
314- EXECUTOR . lock ( ) . timed_wait . push ( TimedWait {
315- wake_at : micros,
316- waker : w. clone ( ) ,
317- } ) ;
318- * previous_waker = Some ( w) ;
319- }
320- previous_waker. as_ref ( ) . unwrap ( ) . register ( waker) ;
298+ let event = Event :: new ( ) ;
299+ EXECUTOR . lock ( ) . timed_wait . push ( TimedWait {
300+ wake_at : tgt,
301+ event : event. trigger ( ) ,
302+ } ) ;
303+ event
321304 }
322305
323306 /// Spawn a new task.
0 commit comments