Skip to main content

starnix_core/task/
waiter.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::task::{CurrentTask, RunState};
6use crate::vfs::{EpollEventHandler, FdNumber};
7use bitflags::bitflags;
8use futures::stream::AbortHandle;
9use rustc_hash::FxHashMap;
10use slab::Slab;
11use smallvec::SmallVec;
12use starnix_lifecycle::AtomicCounter;
13use starnix_sync::{
14    EventHandlerReadyQueueLock, EventWaitGuard, InterruptibleEvent, LockDepMutex, NotifyKind,
15    ObjectWaitGuard, ObjectWaiter, PortEvent, PortWaitResult, PortWaiterCallbacksLock,
16    PortWaiterWaitQueuesLock, WaitQueueImplLock, WaiterEventHandlerLock,
17};
18use starnix_types::ownership::debug_assert_no_local_temp_ref;
19use starnix_uapi::error;
20use starnix_uapi::errors::{EINTR, Errno};
21use starnix_uapi::signals::{SIGKILL, SigSet, Signal};
22use starnix_uapi::vfs::FdEvents;
23use std::collections::VecDeque;
24use std::sync::{Arc, Weak};
25use syncio::zxio::zxio_signals_t;
26use syncio::{ZxioSignals, ZxioWeak};
27
28#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
29pub enum ReadyItemKey {
30    FdNumber(FdNumber),
31    Usize(usize),
32}
33
34impl From<FdNumber> for ReadyItemKey {
35    fn from(v: FdNumber) -> Self {
36        Self::FdNumber(v)
37    }
38}
39
40impl From<usize> for ReadyItemKey {
41    fn from(v: usize) -> Self {
42        Self::Usize(v)
43    }
44}
45
46#[derive(Debug, Copy, Clone)]
47pub struct ReadyItem {
48    pub key: ReadyItemKey,
49    pub events: FdEvents,
50}
51
52#[derive(Clone)]
53pub enum EventHandler {
54    /// Does nothing.
55    ///
56    /// It is up to the waiter to synchronize itself with the notifier if
57    /// synchronization is needed.
58    None,
59
60    /// Enqueues an event to a ready list.
61    ///
62    /// This event handler naturally synchronizes the notifier and notifee
63    /// because of the lock acquired/released when enqueuing the event.
64    Enqueue {
65        key: ReadyItemKey,
66        queue: Arc<LockDepMutex<VecDeque<ReadyItem>, EventHandlerReadyQueueLock>>,
67        sought_events: FdEvents,
68    },
69
70    /// Wraps another EventHandler and only triggers it once. Further .handle() calls are ignored.
71    ///
72    /// This is intended for cases like BinderFileObject which need to register
73    /// the same EventHandler on multiple wait queues.
74    HandleOnce(Arc<LockDepMutex<Option<EventHandler>, WaiterEventHandlerLock>>),
75
76    /// This handler is an epoll.
77    Epoll(EpollEventHandler),
78}
79
80impl EventHandler {
81    pub fn handle(self, events: FdEvents) {
82        match self {
83            Self::None => {}
84            Self::Enqueue { key, queue, sought_events } => {
85                let events = events & sought_events;
86                queue.lock().push_back(ReadyItem { key, events });
87            }
88            Self::HandleOnce(inner) => {
89                if let Some(inner) = inner.lock().take() {
90                    inner.handle(events);
91                }
92            }
93            Self::Epoll(e) => e.handle(events),
94        }
95    }
96}
97
98pub struct ZxioSignalHandler {
99    pub zxio: ZxioWeak,
100    pub get_events_from_zxio_signals: fn(zxio_signals_t) -> FdEvents,
101}
102
103// The counter is incremented as each handle is signaled; when the counter reaches the handle
104// count, the event handler is called with the given events.
105pub struct ManyZxHandleSignalHandler {
106    pub count: usize,
107    pub counter: Arc<AtomicCounter<usize>>,
108    pub expected_signals: zx::Signals,
109    pub events: FdEvents,
110}
111
112pub enum SignalHandlerInner {
113    None,
114    Zxio(ZxioSignalHandler),
115    ZxHandle(fn(zx::Signals) -> FdEvents),
116    ManyZxHandle(ManyZxHandleSignalHandler),
117}
118
119pub struct SignalHandler {
120    pub inner: SignalHandlerInner,
121    pub event_handler: EventHandler,
122    pub err_code: Option<Errno>,
123}
124
125impl SignalHandler {
126    fn handle(self, signals: zx::Signals) -> Option<Errno> {
127        let SignalHandler { inner, event_handler, err_code } = self;
128        let events = match inner {
129            SignalHandlerInner::None => None,
130            SignalHandlerInner::Zxio(ZxioSignalHandler { zxio, get_events_from_zxio_signals }) => {
131                if let Some(zxio) = zxio.upgrade() {
132                    Some(get_events_from_zxio_signals(zxio.wait_end(signals)))
133                } else {
134                    None
135                }
136            }
137            SignalHandlerInner::ZxHandle(get_events_from_zx_signals) => {
138                Some(get_events_from_zx_signals(signals))
139            }
140            SignalHandlerInner::ManyZxHandle(signal_handler) => {
141                if signals.contains(signal_handler.expected_signals) {
142                    let new_count = signal_handler.counter.next() + 1;
143                    assert!(new_count <= signal_handler.count);
144                    if new_count == signal_handler.count {
145                        Some(signal_handler.events)
146                    } else {
147                        None
148                    }
149                } else {
150                    None
151                }
152            }
153        };
154        if let Some(events) = events {
155            event_handler.handle(events)
156        }
157        err_code
158    }
159}
160
161pub enum WaitCallback {
162    SignalHandler(SignalHandler),
163    EventHandler(EventHandler),
164}
165
166struct WaitCancelerQueue {
167    wait_queue: Weak<LockDepMutex<WaitQueueImpl, WaitQueueImplLock>>,
168    waiter: WaiterRef,
169    wait_key: WaitKey,
170    waiter_id: WaitEntryId,
171}
172
173struct WaitCancelerZxio {
174    zxio: ZxioWeak,
175    inner: PortWaitCanceler,
176}
177
178struct WaitCancelerPort {
179    inner: PortWaitCanceler,
180}
181
182enum WaitCancelerInner {
183    Zxio(WaitCancelerZxio),
184    Queue(WaitCancelerQueue),
185    Port(WaitCancelerPort),
186}
187
188enum NotifiableRef {
189    Port(Arc<PortWaiter>),
190    Event(Arc<InterruptibleEvent>),
191    AbortHandle(Arc<AbortHandle>),
192}
193
194const WAIT_CANCELER_COMMON_SIZE: usize = 2;
195
196/// Return values for wait_async methods.
197///
198/// Calling `cancel` will cancel any running wait.
199///
200/// Does not implement `Clone` or `Copy` so that only a single canceler exists
201/// per wait.
202pub struct WaitCanceler {
203    cancellers: smallvec::SmallVec<[WaitCancelerInner; WAIT_CANCELER_COMMON_SIZE]>,
204}
205
206impl WaitCanceler {
207    fn new_inner(inner: WaitCancelerInner) -> Self {
208        Self { cancellers: smallvec::smallvec![inner] }
209    }
210
211    pub fn new_noop() -> Self {
212        Self { cancellers: Default::default() }
213    }
214
215    pub fn new_zxio(zxio: ZxioWeak, inner: PortWaitCanceler) -> Self {
216        Self::new_inner(WaitCancelerInner::Zxio(WaitCancelerZxio { zxio, inner }))
217    }
218
219    pub fn new_port(inner: PortWaitCanceler) -> Self {
220        Self::new_inner(WaitCancelerInner::Port(WaitCancelerPort { inner }))
221    }
222
223    /// Equivalent to `merge_unbounded`, except that it enforces that the resulting vector of
224    /// cancellers is small enough to avoid being separately allocated on the heap.
225    ///
226    /// If possible, use this function instead of `merge_unbounded`, because it gives us better
227    /// tools to keep this code path optimized.
228    pub fn merge(self, other: Self) -> Self {
229        // Increase `WAIT_CANCELER_COMMON_SIZE` if needed, or remove this assert and allow the
230        // smallvec to allocate.
231        assert!(
232            self.cancellers.len() + other.cancellers.len() <= WAIT_CANCELER_COMMON_SIZE,
233            "WaitCanceler::merge disallows more than {} cancellers, found {} + {}",
234            WAIT_CANCELER_COMMON_SIZE,
235            self.cancellers.len(),
236            other.cancellers.len()
237        );
238        WaitCanceler::merge_unbounded(self, other)
239    }
240
241    /// Creates a new `WaitCanceler` that is equivalent to canceling both its arguments.
242    pub fn merge_unbounded(
243        Self { mut cancellers }: Self,
244        Self { cancellers: mut other }: Self,
245    ) -> Self {
246        cancellers.append(&mut other);
247        WaitCanceler { cancellers }
248    }
249
250    /// Cancel the pending wait.
251    ///
252    /// Takes `self` by value since a wait can only be canceled once.
253    pub fn cancel(self) {
254        let Self { cancellers } = self;
255        for canceller in cancellers.into_iter().rev() {
256            match canceller {
257                WaitCancelerInner::Zxio(WaitCancelerZxio { zxio, inner }) => {
258                    let Some(zxio) = zxio.upgrade() else { return };
259                    let (_, signals) = zxio.wait_begin(ZxioSignals::NONE.bits());
260                    inner.cancel();
261                    zxio.wait_end(signals);
262                }
263                WaitCancelerInner::Queue(WaitCancelerQueue {
264                    wait_queue,
265                    waiter,
266                    wait_key,
267                    waiter_id: WaitEntryId { key, id },
268                }) => {
269                    let Some(wait_queue) = wait_queue.upgrade() else { return };
270                    waiter.remove_callback(&wait_key);
271                    waiter.will_remove_from_wait_queue(&wait_key);
272                    let mut wait_queue = wait_queue.lock();
273                    let waiters = &mut wait_queue.waiters;
274                    if let Some(entry) = waiters.get_mut(key) {
275                        // The map of waiters in a wait queue uses a `Slab` which
276                        // recycles keys. To make sure we are removing the right
277                        // entry, make sure the ID value matches what we expect
278                        // to remove.
279                        if entry.id == id {
280                            waiters.remove(key);
281                        }
282                    }
283                }
284                WaitCancelerInner::Port(WaitCancelerPort { inner }) => {
285                    inner.cancel();
286                }
287            }
288        }
289    }
290}
291
292/// Return values for wait_async methods that monitor the state of a handle.
293///
294/// Calling `cancel` will cancel any running wait.
295///
296/// Does not implement `Clone` or `Copy` so that only a single canceler exists
297/// per wait.
298pub struct PortWaitCanceler {
299    waiter: Weak<PortWaiter>,
300    key: WaitKey,
301}
302
303impl PortWaitCanceler {
304    /// Cancel the pending wait.
305    ///
306    /// Takes `self` by value since a wait can only be canceled once.
307    pub fn cancel(self) {
308        let Self { waiter, key } = self;
309        if let Some(waiter) = waiter.upgrade() {
310            let _ = waiter.port.cancel(key.raw);
311            waiter.remove_callback(&key);
312        }
313    }
314}
315
316#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
317struct WaitKey {
318    raw: u64,
319}
320
321/// The different type of event that can be waited on / triggered.
322#[derive(Clone, Copy, Debug)]
323enum WaitEvents {
324    /// All event: a wait on `All` will be woken up by all event, and a trigger on `All` will wake
325    /// every waiter.
326    All,
327    /// Wait on the set of FdEvents.
328    Fd(FdEvents),
329    /// Wait for the specified value.
330    Value(u64),
331    /// Wait for a signal in a specific mask to be received by the task.
332    SignalMask(SigSet),
333}
334
335impl WaitEvents {
336    /// Returns whether a wait on `self` should be woken up by `other`.
337    fn intercept(self: &WaitEvents, other: &WaitEvents) -> bool {
338        match (self, other) {
339            (Self::All, _) | (_, Self::All) => true,
340            (Self::Fd(m1), Self::Fd(m2)) => m1.bits() & m2.bits() != 0,
341            (Self::Value(v1), Self::Value(v2)) => v1 == v2,
342            // A SignalMask event can only be intercepted by another SignalMask event.
343            (Self::SignalMask(m1), Self::SignalMask(m2)) => m1.intersects(m2),
344            _ => false,
345        }
346    }
347}
348
349impl WaitCallback {
350    pub fn none() -> EventHandler {
351        EventHandler::None
352    }
353}
354
355bitflags! {
356    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
357    pub struct WaiterOptions: u8 {
358        /// The wait is not taking place at a safe point.
359        ///
360        /// For example, the caller might be holding a lock, which could cause a deadlock if the
361        /// waiter triggers delayed releasers.
362        const UNSAFE_CALLSTACK = 1 << 0;
363    }
364}
365
366/// Implementation of Waiter. We put the Waiter data in an Arc so that WaitQueue can tell when the
367/// Waiter has been destroyed by keeping a Weak reference. But this is an implementation detail and
368/// a Waiter should have a single owner. So the Arc is hidden inside Waiter.
369struct PortWaiter {
370    port: PortEvent,
371    // Keys in `callbacks` and `wait_queues` come from `next_key`, so the faster
372    // non-DoS-resistant `FxHashMap` is safe here.
373    callbacks: LockDepMutex<FxHashMap<WaitKey, WaitCallback>, PortWaiterCallbacksLock>, // the key 0 is reserved for 'no handler'
374    next_key: AtomicCounter<u64>,
375    options: WaiterOptions,
376
377    /// Collection of wait queues this Waiter is waiting on, so that when the Waiter is Dropped it
378    /// can remove itself from the queues.
379    ///
380    /// This lock is nested inside the WaitQueue.waiters lock.
381    wait_queues: LockDepMutex<
382        FxHashMap<WaitKey, Weak<LockDepMutex<WaitQueueImpl, WaitQueueImplLock>>>,
383        PortWaiterWaitQueuesLock,
384    >,
385}
386
387impl PortWaiter {
388    /// Internal constructor.
389    fn new(options: WaiterOptions) -> Arc<Self> {
390        Arc::new(PortWaiter {
391            port: PortEvent::new(),
392            callbacks: Default::default(),
393            next_key: AtomicCounter::<u64>::new(1),
394            options,
395            wait_queues: Default::default(),
396        })
397    }
398
399    /// Waits until the given deadline has passed or the waiter is woken up. See wait_until().
400    fn wait_internal(&self, deadline: zx::MonotonicInstant) -> Result<(), Errno> {
401        // This method can block arbitrarily long, possibly waiting for another process. The
402        // current thread should not own any local ref that might delay the release of a resource
403        // while doing so.
404        debug_assert_no_local_temp_ref();
405
406        match self.port.wait(deadline) {
407            PortWaitResult::Notification { kind: NotifyKind::Regular } => Ok(()),
408            PortWaitResult::Notification { kind: NotifyKind::Interrupt } => error!(EINTR),
409            PortWaitResult::Signal { key, observed } => {
410                if let Some(callback) = self.remove_callback(&WaitKey { raw: key }) {
411                    match callback {
412                        WaitCallback::SignalHandler(handler) => {
413                            if let Some(errno) = handler.handle(observed) {
414                                return Err(errno);
415                            }
416                        }
417                        WaitCallback::EventHandler(_) => {
418                            panic!("wrong type of handler called")
419                        }
420                    }
421                }
422
423                Ok(())
424            }
425            PortWaitResult::TimedOut => error!(ETIMEDOUT),
426        }
427    }
428
429    fn wait_until(
430        self: &Arc<Self>,
431        current_task: &CurrentTask,
432        run_state: RunState,
433        deadline: zx::MonotonicInstant,
434    ) -> Result<(), Errno> {
435        let is_waiting = deadline.into_nanos() > 0;
436
437        let callback = || {
438            // We are susceptible to spurious wakeups because interrupt() posts a message to the port
439            // queue. In addition to more subtle races, there could already be valid messages in the
440            // port queue that will immediately wake us up, leaving the interrupt message in the queue
441            // for subsequent waits (which by then may not have any signals pending) to read.
442            //
443            // It's impossible to non-racily guarantee that a signal is pending so there might always
444            // be an EINTR result here with no signal. But any signal we get when !is_waiting we know is
445            // leftover from before: the top of this function only sets ourself as the
446            // current_task.signals.run_state when there's a nonzero timeout, and that waiter reference
447            // is what is used to signal the interrupt().
448            loop {
449                let wait_result = self.wait_internal(deadline);
450                if let Err(errno) = &wait_result {
451                    if errno.code == EINTR && !is_waiting {
452                        continue; // Spurious wakeup.
453                    }
454                }
455                return wait_result;
456            }
457        };
458
459        // Trigger delayed releaser before blocking if we're at a safe point.
460        //
461        // For example, we cannot trigger delayed releaser if we are holding any locks.
462        if !self.options.contains(WaiterOptions::UNSAFE_CALLSTACK) {
463            current_task.trigger_delayed_releaser();
464        }
465
466        if is_waiting { current_task.run_in_state(run_state, callback) } else { callback() }
467    }
468
469    fn next_key(&self) -> WaitKey {
470        let key = self.next_key.next();
471        // TODO - find a better reaction to wraparound
472        assert!(key != 0, "bad key from u64 wraparound");
473        WaitKey { raw: key }
474    }
475
476    fn register_callback(&self, callback: WaitCallback) -> WaitKey {
477        let key = self.next_key();
478        assert!(
479            self.callbacks.lock().insert(key, callback).is_none(),
480            "unexpected callback already present for key {key:?}"
481        );
482        key
483    }
484
485    fn remove_callback(&self, key: &WaitKey) -> Option<WaitCallback> {
486        self.callbacks.lock().remove(&key)
487    }
488
489    fn wake_immediately(&self, events: FdEvents, handler: EventHandler) {
490        let callback = WaitCallback::EventHandler(handler);
491        let key = self.register_callback(callback);
492        self.queue_events(&key, WaitEvents::Fd(events));
493    }
494
495    /// Establish an asynchronous wait for the signals on the given Zircon handle (not to be
496    /// confused with POSIX signals), optionally running a FnOnce. Wait operations will return
497    /// the error code present in the provided SignalHandler.
498    ///
499    /// Returns a `PortWaitCanceler` that can be used to cancel the wait.
500    fn wake_on_zircon_signals(
501        self: &Arc<Self>,
502        handle: &dyn zx::AsHandleRef,
503        zx_signals: zx::Signals,
504        handler: SignalHandler,
505    ) -> Result<PortWaitCanceler, zx::Status> {
506        let callback = WaitCallback::SignalHandler(handler);
507        let key = self.register_callback(callback);
508        self.port.object_wait_async(
509            handle,
510            key.raw,
511            zx_signals,
512            zx::WaitAsyncOpts::EDGE_TRIGGERED,
513        )?;
514        Ok(PortWaitCanceler { waiter: Arc::downgrade(self), key })
515    }
516
517    fn queue_events(&self, key: &WaitKey, events: WaitEvents) {
518        scopeguard::defer! {
519            self.port.notify(NotifyKind::Regular)
520        }
521
522        // Handling user events immediately when they are triggered breaks any
523        // ordering expectations on Linux by batching all starnix events with
524        // the first starnix event even if other events occur on the Fuchsia
525        // platform (and are enqueued to the `zx::Port`) between them. This
526        // ordering does not seem to be load-bearing for applications running on
527        // starnix so we take the divergence in ordering in favour of improved
528        // performance (by minimizing syscalls) when operating on FDs backed by
529        // starnix.
530        //
531        // TODO(https://fxbug.dev/42084319): If we can read a batch of packets
532        // from the `zx::Port`, maybe we can keep the ordering?
533        let Some(callback) = self.remove_callback(key) else {
534            return;
535        };
536
537        match callback {
538            WaitCallback::EventHandler(handler) => {
539                let events = match events {
540                    // If the event is All, signal on all possible fd
541                    // events.
542                    WaitEvents::All => FdEvents::all(),
543                    WaitEvents::Fd(events) => events,
544                    WaitEvents::SignalMask(_) => FdEvents::POLLIN,
545                    WaitEvents::Value(_) => FdEvents::POLLIN,
546                };
547                handler.handle(events)
548            }
549            WaitCallback::SignalHandler(_) => {
550                panic!("wrong type of handler called")
551            }
552        }
553    }
554
555    fn notify(&self) {
556        self.port.notify(NotifyKind::Regular);
557    }
558
559    fn interrupt(&self) {
560        self.port.notify(NotifyKind::Interrupt);
561    }
562}
563
564impl std::fmt::Debug for PortWaiter {
565    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
566        f.debug_struct("PortWaiter").field("port", &self.port).finish_non_exhaustive()
567    }
568}
569
570/// A type that can put a thread to sleep waiting for a condition.
571#[derive(Debug, Clone)]
572pub struct Waiter {
573    // TODO(https://g-issues.fuchsia.dev/issues/303068424): Avoid `PortWaiter`
574    // when operating purely over FDs backed by starnix.
575    inner: Arc<PortWaiter>,
576}
577
578impl Waiter {
579    /// Create a new waiter.
580    pub fn new() -> Self {
581        Self { inner: PortWaiter::new(WaiterOptions::empty()) }
582    }
583
584    /// Create a new waiter with the given options.
585    pub fn with_options(options: WaiterOptions) -> Self {
586        Self { inner: PortWaiter::new(options) }
587    }
588
589    /// Create a weak reference to this waiter.
590    fn weak(&self) -> WaiterRef {
591        WaiterRef::from_port(&self.inner)
592    }
593
594    /// Freeze the task until the waiter is woken up.
595    ///
596    /// No signal, e.g. EINTR (interrupt), should be received.
597    pub fn freeze(&self, current_task: &CurrentTask) {
598        while self
599            .inner
600            .wait_until(
601                current_task,
602                RunState::Frozen(self.clone()),
603                zx::MonotonicInstant::INFINITE,
604            )
605            .is_err()
606        {
607            // Avoid attempting to freeze the task if it is exiting or has a pending SIGKILL.
608            if current_task.is_exitted() || current_task.read().has_signal_pending(SIGKILL) {
609                break;
610            }
611            // Ignore spurious wakeups from the [`PortEvent.futex`]
612        }
613    }
614
615    /// Stop the task until the waiter is woken up (e.g., by the tracer or SIGCONT).
616    ///
617    /// The wait can be aborted by SIGKILL.
618    pub fn stop(&self, current_task: &CurrentTask) {
619        // When run_state is RunState::TracingStopped and the deadline is INFINITE, wait_until only
620        // returns Err(EINTR) when CurrentTask::run_in_state has already observed
621        // state.has_signal_pending(SIGKILL)
622        let _ = self.inner.wait_until(
623            current_task,
624            RunState::TracingStopped,
625            zx::MonotonicInstant::INFINITE,
626        );
627    }
628
629    /// Wait until the waiter is woken up.
630    ///
631    /// If the wait is interrupted (see [`Waiter::interrupt`]), this function returns EINTR.
632    pub fn wait(&self, current_task: &CurrentTask) -> Result<(), Errno> {
633        self.inner.wait_until(
634            current_task,
635            RunState::Waiter(WaiterRef::from_port(&self.inner)),
636            zx::MonotonicInstant::INFINITE,
637        )
638    }
639
640    /// Wait until the given deadline has passed or the waiter is woken up.
641    ///
642    /// If the wait deadline is nonzero and is interrupted (see [`Waiter::interrupt`]), this
643    /// function returns EINTR. Callers must take special care not to lose any accumulated data or
644    /// local state when EINTR is received as this is a normal and recoverable situation.
645    ///
646    /// Using a 0 deadline (no waiting, useful for draining pending events) will not wait and is
647    /// guaranteed not to issue EINTR.
648    ///
649    /// It the timeout elapses with no events, this function returns ETIMEDOUT.
650    ///
651    /// Processes at most one event. If the caller is interested in draining the events, it should
652    /// repeatedly call this function with a 0 deadline until it reports ETIMEDOUT. (This case is
653    /// why a 0 deadline must not return EINTR, as previous calls to wait_until() may have
654    /// accumulated state that would be lost when returning EINTR to userspace.)
655    ///
656    /// It is up to the caller (the "waiter") to make sure that it synchronizes with any object
657    /// that triggers an event (the "notifier"). This `Waiter` does not provide any synchronization
658    /// itself. Note that synchronization between the "waiter" the "notifier" may be provided by
659    /// the [`EventHandler`] used to handle an event iff the waiter observes the side-effects of
660    /// the handler (e.g. reading the ready list modified by [`EventHandler::Enqueue`] or
661    /// [`EventHandler::EnqueueOnce`]).
662    pub fn wait_until(
663        &self,
664        current_task: &CurrentTask,
665        deadline: zx::MonotonicInstant,
666    ) -> Result<(), Errno> {
667        self.inner.wait_until(
668            current_task,
669            RunState::Waiter(WaiterRef::from_port(&self.inner)),
670            deadline,
671        )
672    }
673
674    fn create_wait_entry(&self, filter: WaitEvents) -> WaitEntry {
675        WaitEntry { waiter: self.weak(), filter, key: self.inner.next_key() }
676    }
677
678    fn create_wait_entry_with_handler(
679        &self,
680        filter: WaitEvents,
681        handler: EventHandler,
682    ) -> WaitEntry {
683        let key = self.inner.register_callback(WaitCallback::EventHandler(handler));
684        WaitEntry { waiter: self.weak(), filter, key }
685    }
686
687    pub fn wake_immediately(&self, events: FdEvents, handler: EventHandler) {
688        self.inner.wake_immediately(events, handler);
689    }
690
691    /// Establish an asynchronous wait for the signals on the given Zircon handle (not to be
692    /// confused with POSIX signals), optionally running a FnOnce.
693    ///
694    /// Returns a `PortWaitCanceler` that can be used to cancel the wait.
695    pub fn wake_on_zircon_signals(
696        &self,
697        handle: &dyn zx::AsHandleRef,
698        zx_signals: zx::Signals,
699        handler: SignalHandler,
700    ) -> Result<PortWaitCanceler, zx::Status> {
701        self.inner.wake_on_zircon_signals(handle, zx_signals, handler)
702    }
703
704    /// Return a WaitCanceler representing a wait that will never complete. Useful for stub
705    /// implementations that should block forever even though a real implementation would wake up
706    /// eventually.
707    pub fn fake_wait(&self) -> WaitCanceler {
708        WaitCanceler::new_noop()
709    }
710
711    // Notify the waiter to wake it up without signalling any events.
712    pub fn notify(&self) {
713        self.inner.notify();
714    }
715
716    /// Interrupt the waiter to deliver a signal. The wait operation will return EINTR, and a
717    /// typical caller should then unwind to the syscall dispatch loop to let the signal be
718    /// processed. See wait_until() for more details.
719    pub fn interrupt(&self) {
720        self.inner.interrupt();
721    }
722}
723
724impl Drop for Waiter {
725    fn drop(&mut self) {
726        // Delete ourselves from each wait queue we know we're on to prevent Weak references to
727        // ourself from sticking around forever.
728        let wait_queues = std::mem::take(&mut *self.inner.wait_queues.lock()).into_values();
729        for wait_queue in wait_queues {
730            if let Some(wait_queue) = wait_queue.upgrade() {
731                wait_queue.lock().waiters.retain(|_, entry| entry.entry.waiter != *self)
732            }
733        }
734    }
735}
736
737impl Default for Waiter {
738    fn default() -> Self {
739        Self::new()
740    }
741}
742
743impl PartialEq for Waiter {
744    fn eq(&self, other: &Self) -> bool {
745        Arc::ptr_eq(&self.inner, &other.inner)
746    }
747}
748
749pub struct SimpleWaiter {
750    event: Arc<InterruptibleEvent>,
751    wait_queues: Vec<Weak<LockDepMutex<WaitQueueImpl, WaitQueueImplLock>>>,
752}
753
754impl SimpleWaiter {
755    pub fn new(event: &Arc<InterruptibleEvent>) -> (SimpleWaiter, EventWaitGuard<'_>) {
756        (SimpleWaiter { event: event.clone(), wait_queues: Default::default() }, event.begin_wait())
757    }
758}
759
760impl Drop for SimpleWaiter {
761    fn drop(&mut self) {
762        for wait_queue in &self.wait_queues {
763            if let Some(wait_queue) = wait_queue.upgrade() {
764                wait_queue.lock().waiters.retain(|_, entry| entry.entry.waiter != self.event)
765            }
766        }
767    }
768}
769
770#[derive(Debug, Clone)]
771enum WaiterKind {
772    Port(Weak<PortWaiter>),
773    Event(Weak<InterruptibleEvent>),
774    AbortHandle(Weak<futures::stream::AbortHandle>),
775    ObjectWaiter(Weak<ObjectWaiter>),
776}
777
778impl Default for WaiterKind {
779    fn default() -> Self {
780        WaiterKind::Port(Default::default())
781    }
782}
783
784/// A weak reference to a Waiter. Intended for holding in wait queues or stashing elsewhere for
785/// calling queue_events later.
786#[derive(Debug, Default, Clone)]
787pub struct WaiterRef(WaiterKind);
788
789impl WaiterRef {
790    fn from_port(waiter: &Arc<PortWaiter>) -> WaiterRef {
791        WaiterRef(WaiterKind::Port(Arc::downgrade(waiter)))
792    }
793
794    fn from_event(event: &Arc<InterruptibleEvent>) -> WaiterRef {
795        WaiterRef(WaiterKind::Event(Arc::downgrade(event)))
796    }
797
798    pub fn from_abort_handle(handle: &Arc<futures::stream::AbortHandle>) -> WaiterRef {
799        WaiterRef(WaiterKind::AbortHandle(Arc::downgrade(handle)))
800    }
801
802    /// Returns a `WaiterRef` for the `ObjectWaiter`.
803    ///
804    /// Interrupting the returned `WaiterRef` interrupts the underlying `ObjectWaiter`, causing
805    /// `ObjectWaitGuard::wait_many` to return `ObjectWaitError::Interrupted`. A task blocking in
806    /// `wait_many` passes this `WaiterRef` to `RunState::Waiter` so that signals, task exit, and
807    /// freezing can interrupt the wait. Accepting `&ObjectWaitGuard` ensures that
808    /// `ObjectWaiter::begin_wait` was called before entering `RunState::Waiter`, preventing missed
809    /// interruptions.
810    pub fn from_object_waiter(guard: &ObjectWaitGuard<'_>) -> WaiterRef {
811        WaiterRef(WaiterKind::ObjectWaiter(Arc::downgrade(guard.waiter())))
812    }
813
814    pub fn is_valid(&self) -> bool {
815        match &self.0 {
816            WaiterKind::Port(waiter) => waiter.strong_count() != 0,
817            WaiterKind::Event(event) => event.strong_count() != 0,
818            WaiterKind::AbortHandle(handle) => handle.strong_count() != 0,
819            WaiterKind::ObjectWaiter(waiter) => waiter.strong_count() != 0,
820        }
821    }
822
823    pub fn interrupt(&self) {
824        match &self.0 {
825            WaiterKind::Port(waiter) => {
826                if let Some(waiter) = waiter.upgrade() {
827                    waiter.interrupt();
828                }
829            }
830            WaiterKind::Event(event) => {
831                if let Some(event) = event.upgrade() {
832                    event.interrupt();
833                }
834            }
835            WaiterKind::AbortHandle(handle) => {
836                if let Some(handle) = handle.upgrade() {
837                    handle.abort();
838                }
839            }
840            WaiterKind::ObjectWaiter(waiter) => {
841                if let Some(waiter) = waiter.upgrade() {
842                    waiter.interrupt();
843                }
844            }
845        }
846    }
847
848    fn remove_callback(&self, key: &WaitKey) {
849        match &self.0 {
850            WaiterKind::Port(waiter) => {
851                if let Some(waiter) = waiter.upgrade() {
852                    waiter.remove_callback(key);
853                }
854            }
855            _ => (),
856        }
857    }
858
859    /// Attempts to upgrade a waiter ref to a notifiable ref. If the waiter ref is no
860    /// longer valid, returns None.
861    fn upgrade_notifiable(&self) -> Option<NotifiableRef> {
862        match &self.0 {
863            WaiterKind::Port(waiter) => {
864                if let Some(waiter) = waiter.upgrade() {
865                    return Some(NotifiableRef::Port(waiter));
866                }
867            }
868            WaiterKind::Event(event) => {
869                if let Some(event) = event.upgrade() {
870                    return Some(NotifiableRef::Event(event));
871                }
872            }
873            WaiterKind::AbortHandle(handle) => {
874                if let Some(handle) = handle.upgrade() {
875                    return Some(NotifiableRef::AbortHandle(handle));
876                }
877            }
878            // An `ObjectWaiter` is never added to a `WaitQueue`, and only supports interruptions.
879            WaiterKind::ObjectWaiter(_) => (),
880        }
881        None
882    }
883
884    /// Called by the WaitQueue when this waiter is about to be removed from the queue.
885    ///
886    /// TODO(abarth): This function does not appear to be called when the WaitQueue is dropped,
887    /// which appears to be a leak.
888    fn will_remove_from_wait_queue(&self, key: &WaitKey) {
889        match &self.0 {
890            WaiterKind::Port(waiter) => {
891                if let Some(waiter) = waiter.upgrade() {
892                    waiter.wait_queues.lock().remove(key);
893                }
894            }
895            _ => (),
896        }
897    }
898}
899
900impl PartialEq<Waiter> for WaiterRef {
901    fn eq(&self, other: &Waiter) -> bool {
902        match &self.0 {
903            WaiterKind::Port(waiter) => waiter.as_ptr() == Arc::as_ptr(&other.inner),
904            _ => false,
905        }
906    }
907}
908
909impl PartialEq<Arc<InterruptibleEvent>> for WaiterRef {
910    fn eq(&self, other: &Arc<InterruptibleEvent>) -> bool {
911        match &self.0 {
912            WaiterKind::Event(event) => event.as_ptr() == Arc::as_ptr(other),
913            _ => false,
914        }
915    }
916}
917
918impl PartialEq for WaiterRef {
919    fn eq(&self, other: &WaiterRef) -> bool {
920        match (&self.0, &other.0) {
921            (WaiterKind::Port(lhs), WaiterKind::Port(rhs)) => Weak::ptr_eq(lhs, rhs),
922            (WaiterKind::Event(lhs), WaiterKind::Event(rhs)) => Weak::ptr_eq(lhs, rhs),
923            (WaiterKind::AbortHandle(lhs), WaiterKind::AbortHandle(rhs)) => Weak::ptr_eq(lhs, rhs),
924            (WaiterKind::ObjectWaiter(lhs), WaiterKind::ObjectWaiter(rhs)) => {
925                Weak::ptr_eq(lhs, rhs)
926            }
927            _ => false,
928        }
929    }
930}
931
932impl NotifiableRef {
933    fn notify(&self, key: &WaitKey, events: WaitEvents) {
934        match self {
935            NotifiableRef::Port(port_waiter) => port_waiter.queue_events(key, events),
936            NotifiableRef::Event(interruptible_event) => interruptible_event.notify(),
937            NotifiableRef::AbortHandle(handle) => handle.abort(),
938        }
939    }
940}
941
942/// A list of waiters waiting for some event.
943///
944/// For events that are generated inside Starnix, we walk the wait queue
945/// on the thread that triggered the event to notify the waiters that the event
946/// has occurred. The waiters will then wake up on their own thread to handle
947/// the event.
948#[derive(Default, Debug, Clone)]
949pub struct WaitQueue(Arc<LockDepMutex<WaitQueueImpl, WaitQueueImplLock>>);
950
951impl WaitQueue {
952    pub fn new() -> Self {
953        Self(Arc::new(WaitQueueImpl::default().into()))
954    }
955}
956
957#[derive(Debug)]
958struct WaitEntryWithId {
959    entry: WaitEntry,
960    /// The ID use to uniquely identify this wait entry even if it shares the
961    /// key used in the wait queue's [`Slab`] with another wait entry since a
962    /// slab's keys are recycled.
963    id: u64,
964}
965
966struct WaitEntryId {
967    key: usize,
968    id: u64,
969}
970
971#[derive(Default, Debug)]
972struct WaitQueueImpl {
973    /// Holds the next ID value to use when adding a new `WaitEntry` to the
974    /// waiters (dense) map.
975    ///
976    /// A [`Slab`]s keys are recycled so we use the ID to uniquely identify a
977    /// wait entry.
978    next_wait_entry_id: u64,
979    /// The list of waiters.
980    ///
981    /// The waiter's wait_queues lock is nested inside this lock.
982    waiters: Slab<WaitEntryWithId>,
983}
984
985/// An entry in a WaitQueue.
986#[derive(Debug)]
987struct WaitEntry {
988    /// The waiter that is waking for the FdEvent.
989    waiter: WaiterRef,
990
991    /// The events that the waiter is waiting for.
992    filter: WaitEvents,
993
994    /// key for cancelling and queueing events
995    key: WaitKey,
996}
997
998impl WaitQueue {
999    fn add_waiter(&self, entry: WaitEntry) -> WaitEntryId {
1000        let mut wait_queue = self.0.lock();
1001        let id = wait_queue
1002            .next_wait_entry_id
1003            .checked_add(1)
1004            .expect("all possible wait entry ID values exhausted");
1005        wait_queue.next_wait_entry_id = id;
1006        WaitEntryId { key: wait_queue.waiters.insert(WaitEntryWithId { entry, id }), id }
1007    }
1008
1009    /// Establish a wait for the given entry.
1010    ///
1011    /// The waiter will be notified when an event matching the entry occurs.
1012    ///
1013    /// This function does not actually block the waiter. To block the waiter,
1014    /// call the [`Waiter::wait`] function on the waiter.
1015    ///
1016    /// Returns a `WaitCanceler` that can be used to cancel the wait.
1017    fn wait_async_entry(&self, waiter: &Waiter, entry: WaitEntry) -> WaitCanceler {
1018        let wait_key = entry.key;
1019        let waiter_id = self.add_waiter(entry);
1020        let wait_queue = Arc::downgrade(&self.0);
1021        waiter.inner.wait_queues.lock().insert(wait_key, wait_queue.clone());
1022        WaitCanceler::new_inner(WaitCancelerInner::Queue(WaitCancelerQueue {
1023            wait_queue,
1024            waiter: waiter.weak(),
1025            wait_key,
1026            waiter_id,
1027        }))
1028    }
1029
1030    /// Establish a wait for the given value event.
1031    ///
1032    /// The waiter will be notified when an event with the same value occurs.
1033    ///
1034    /// This function does not actually block the waiter. To block the waiter,
1035    /// call the [`Waiter::wait`] function on the waiter.
1036    ///
1037    /// Returns a `WaitCanceler` that can be used to cancel the wait.
1038    pub fn wait_async_value(&self, waiter: &Waiter, value: u64) -> WaitCanceler {
1039        self.wait_async_entry(waiter, waiter.create_wait_entry(WaitEvents::Value(value)))
1040    }
1041
1042    /// Establish a wait for the given value event with an associated handler.
1043    ///
1044    /// The waiter will be notified when an event with the same value occurs, triggering the handler.
1045    ///
1046    /// This function does not actually block the waiter. To block the waiter,
1047    /// call the [`Waiter::wait`] function on the waiter.
1048    ///
1049    /// Returns a `WaitCanceler` that can be used to cancel the wait.
1050    pub fn wait_async_value_with_handler(
1051        &self,
1052        waiter: &Waiter,
1053        value: u64,
1054        handler: EventHandler,
1055    ) -> WaitCanceler {
1056        let entry = waiter.create_wait_entry_with_handler(WaitEvents::Value(value), handler);
1057        self.wait_async_entry(waiter, entry)
1058    }
1059
1060    /// Establish a wait for the given FdEvents.
1061    ///
1062    /// The waiter will be notified when an event matching the `events` occurs.
1063    ///
1064    /// This function does not actually block the waiter. To block the waiter,
1065    /// call the [`Waiter::wait`] function on the waiter.
1066    ///
1067    /// Returns a `WaitCanceler` that can be used to cancel the wait.
1068    pub fn wait_async_fd_events(
1069        &self,
1070        waiter: &Waiter,
1071        events: FdEvents,
1072        handler: EventHandler,
1073    ) -> WaitCanceler {
1074        let entry = waiter.create_wait_entry_with_handler(WaitEvents::Fd(events), handler);
1075        self.wait_async_entry(waiter, entry)
1076    }
1077
1078    /// Establish a wait for a particular signal mask.
1079    ///
1080    /// The waiter will be notified when a signal in the mask is received.
1081    ///
1082    /// This function does not actually block the waiter. To block the waiter,
1083    /// call the [`Waiter::wait`] function on the waiter.
1084    ///
1085    /// Returns a `WaitCanceler` that can be used to cancel the wait.
1086    pub fn wait_async_signal_mask(
1087        &self,
1088        waiter: &Waiter,
1089        mask: SigSet,
1090        handler: EventHandler,
1091    ) -> WaitCanceler {
1092        let entry = waiter.create_wait_entry_with_handler(WaitEvents::SignalMask(mask), handler);
1093        self.wait_async_entry(waiter, entry)
1094    }
1095
1096    /// Establish a wait for any event.
1097    ///
1098    /// The waiter will be notified when any event occurs.
1099    ///
1100    /// This function does not actually block the waiter. To block the waiter,
1101    /// call the [`Waiter::wait`] function on the waiter.
1102    ///
1103    /// Returns a `WaitCanceler` that can be used to cancel the wait.
1104    pub fn wait_async(&self, waiter: &Waiter) -> WaitCanceler {
1105        self.wait_async_entry(waiter, waiter.create_wait_entry(WaitEvents::All))
1106    }
1107
1108    pub fn wait_async_simple(&self, waiter: &mut SimpleWaiter) {
1109        let entry = WaitEntry {
1110            waiter: WaiterRef::from_event(&waiter.event),
1111            filter: WaitEvents::All,
1112            key: Default::default(),
1113        };
1114        waiter.wait_queues.push(Arc::downgrade(&self.0));
1115        self.add_waiter(entry);
1116    }
1117
1118    fn notify_events_count(&self, mut events: WaitEvents, mut limit: usize) -> usize {
1119        if let WaitEvents::Fd(ref mut fd_events) = events {
1120            *fd_events = fd_events.add_equivalent_fd_events();
1121        }
1122        // Store references to waiters ready to be notified locally so that we can drop our waiters
1123        // lock before notifying the waiters. The waiters will need to acquire the waiters lock once
1124        // they wake up in order to remove themselves from the queue and so they might contend
1125        // with this thread for that lock.
1126        // Usually we expect to notify at most a single waiter.
1127        let mut notifiable_refs = SmallVec::<[(NotifiableRef, WaitKey); 1]>::new();
1128        let mut woken = 0;
1129        {
1130            let mut guard = self.0.lock();
1131            guard.waiters.retain(|_, WaitEntryWithId { entry, id: _ }| {
1132                if limit > 0 && entry.filter.intercept(&events) {
1133                    if let Some(notifiable_ref) = entry.waiter.upgrade_notifiable() {
1134                        limit -= 1;
1135                        woken += 1;
1136                        notifiable_refs.push((notifiable_ref, entry.key));
1137                    }
1138
1139                    entry.waiter.will_remove_from_wait_queue(&entry.key);
1140                    false
1141                } else {
1142                    true
1143                }
1144            });
1145        }
1146        for (notifiable_ref, key) in notifiable_refs {
1147            notifiable_ref.notify(&key, events);
1148        }
1149        woken
1150    }
1151
1152    pub fn notify_fd_events(&self, events: FdEvents) {
1153        self.notify_events_count(WaitEvents::Fd(events), usize::MAX);
1154    }
1155
1156    pub fn notify_fd_events_count(&self, events: FdEvents, limit: usize) {
1157        self.notify_events_count(WaitEvents::Fd(events), limit);
1158    }
1159
1160    pub fn notify_signal(&self, signal: &Signal) {
1161        let event = WaitEvents::SignalMask(SigSet::from(*signal));
1162        self.notify_events_count(event, usize::MAX);
1163    }
1164
1165    pub fn notify_value(&self, value: u64) {
1166        self.notify_events_count(WaitEvents::Value(value), usize::MAX);
1167    }
1168
1169    pub fn notify_unordered_count(&self, limit: usize) {
1170        self.notify_events_count(WaitEvents::All, limit);
1171    }
1172
1173    pub fn notify_all(&self) {
1174        self.notify_unordered_count(usize::MAX);
1175    }
1176
1177    /// Returns whether there is no active waiters waiting on this `WaitQueue`.
1178    pub fn is_empty(&self) -> bool {
1179        self.0.lock().waiters.is_empty()
1180    }
1181}
1182
1183/// A wait queue that dispatches events based on the value of an enum.
1184pub struct TypedWaitQueue<T: Into<u64>> {
1185    wait_queue: WaitQueue,
1186    value_type: std::marker::PhantomData<T>,
1187}
1188
1189// We can't #[derive(Default)] on [TypedWaitQueue<T>] as T may not implement the Default trait.
1190impl<T: Into<u64>> Default for TypedWaitQueue<T> {
1191    fn default() -> Self {
1192        Self { wait_queue: Default::default(), value_type: Default::default() }
1193    }
1194}
1195
1196impl<T: Into<u64>> TypedWaitQueue<T> {
1197    pub fn wait_async_value(&self, waiter: &Waiter, value: T) -> WaitCanceler {
1198        self.wait_queue.wait_async_value(waiter, value.into())
1199    }
1200
1201    pub fn wait_async_value_with_handler(
1202        &self,
1203        waiter: &Waiter,
1204        value: T,
1205        handler: EventHandler,
1206    ) -> WaitCanceler {
1207        self.wait_queue.wait_async_value_with_handler(waiter, value.into(), handler)
1208    }
1209
1210    pub fn notify_value(&self, value: T) {
1211        self.wait_queue.notify_value(value.into())
1212    }
1213}
1214
1215#[cfg(test)]
1216mod tests {
1217    use super::*;
1218    use crate::fs::fuchsia::create_fuchsia_pipe;
1219    use crate::signals::SignalInfo;
1220    use crate::task::{TaskFlags, TaskStateCode};
1221    use crate::testing::{spawn_kernel_and_run, spawn_kernel_and_run_sync};
1222    use crate::vfs::buffers::{VecInputBuffer, VecOutputBuffer};
1223    use crate::vfs::eventfd::{EventFdType, new_eventfd};
1224    use assert_matches::assert_matches;
1225    use starnix_sync::ObjectWaitError;
1226    use starnix_uapi::open_flags::OpenFlags;
1227    use starnix_uapi::signals::SIGUSR1;
1228
1229    const KEY: ReadyItemKey = ReadyItemKey::Usize(1234);
1230
1231    #[::fuchsia::test]
1232    async fn test_async_wait_exec() {
1233        spawn_kernel_and_run(async |current_task| {
1234            let (local_socket, remote_socket) = zx::Socket::create_stream();
1235            let pipe = create_fuchsia_pipe(&current_task, remote_socket, OpenFlags::RDWR).unwrap();
1236
1237            const MEM_SIZE: usize = 1024;
1238            let mut output_buffer = VecOutputBuffer::new(MEM_SIZE);
1239
1240            let test_string = "hello startnix".to_string();
1241            let queue: Arc<LockDepMutex<VecDeque<ReadyItem>, EventHandlerReadyQueueLock>> =
1242                Default::default();
1243            let handler = EventHandler::Enqueue {
1244                key: KEY,
1245                queue: queue.clone(),
1246                sought_events: FdEvents::all(),
1247            };
1248            let waiter = Waiter::new();
1249            pipe.wait_async(&current_task, &waiter, FdEvents::POLLIN, handler).expect("wait_async");
1250            let test_string_clone = test_string.clone();
1251
1252            let write_count = AtomicCounter::<usize>::default();
1253            std::thread::scope(|s| {
1254                let thread = s.spawn(|| {
1255                    let test_data = test_string_clone.as_bytes();
1256                    let no_written = local_socket.write(test_data).unwrap();
1257                    assert_eq!(0, write_count.add(no_written));
1258                    assert_eq!(no_written, test_data.len());
1259                });
1260
1261                // this code would block on failure
1262
1263                assert!(queue.lock().is_empty());
1264                waiter.wait(&current_task).unwrap();
1265                thread.join().expect("join thread")
1266            });
1267            queue.lock().iter().for_each(|item| assert!(item.events.contains(FdEvents::POLLIN)));
1268
1269            let read_size = pipe.read(&current_task, &mut output_buffer).unwrap();
1270
1271            let no_written = write_count.get();
1272            assert_eq!(no_written, read_size);
1273
1274            assert_eq!(output_buffer.data(), test_string.as_bytes());
1275        })
1276        .await;
1277    }
1278
1279    #[::fuchsia::test]
1280    async fn test_async_wait_cancel() {
1281        for do_cancel in [true, false] {
1282            spawn_kernel_and_run(async move |current_task| {
1283                let event = new_eventfd(&current_task, 0, EventFdType::Counter, true);
1284                let waiter = Waiter::new();
1285                let queue: Arc<LockDepMutex<VecDeque<ReadyItem>, EventHandlerReadyQueueLock>> =
1286                    Default::default();
1287                let handler = EventHandler::Enqueue {
1288                    key: KEY,
1289                    queue: queue.clone(),
1290                    sought_events: FdEvents::all(),
1291                };
1292                let wait_canceler = event
1293                    .wait_async(&current_task, &waiter, FdEvents::POLLIN, handler)
1294                    .expect("wait_async");
1295                if do_cancel {
1296                    wait_canceler.cancel();
1297                }
1298                let add_val = 1u64;
1299                assert_eq!(
1300                    event
1301                        .write(&current_task, &mut VecInputBuffer::new(&add_val.to_ne_bytes()))
1302                        .unwrap(),
1303                    std::mem::size_of::<u64>()
1304                );
1305
1306                let wait_result = waiter.wait_until(&current_task, zx::MonotonicInstant::ZERO);
1307                let final_count = queue.lock().len();
1308                if do_cancel {
1309                    assert_eq!(wait_result, error!(ETIMEDOUT));
1310                    assert_eq!(0, final_count);
1311                } else {
1312                    assert_eq!(wait_result, Ok(()));
1313                    assert_eq!(1, final_count);
1314                }
1315            })
1316            .await;
1317        }
1318    }
1319
1320    #[::fuchsia::test]
1321    async fn single_waiter_multiple_waits_cancel_one_waiter_still_notified() {
1322        spawn_kernel_and_run(async |current_task| {
1323            let wait_queue = WaitQueue::default();
1324            let waiter = Waiter::new();
1325            let wk1 = wait_queue.wait_async(&waiter);
1326            let _wk2 = wait_queue.wait_async(&waiter);
1327            wk1.cancel();
1328            wait_queue.notify_all();
1329            assert!(waiter.wait_until(&current_task, zx::MonotonicInstant::ZERO).is_ok());
1330        })
1331        .await;
1332    }
1333
1334    #[::fuchsia::test]
1335    async fn multiple_waiters_cancel_one_other_still_notified() {
1336        spawn_kernel_and_run(async |current_task| {
1337            let wait_queue = WaitQueue::default();
1338            let waiter1 = Waiter::new();
1339            let waiter2 = Waiter::new();
1340            let wk1 = wait_queue.wait_async(&waiter1);
1341            let _wk2 = wait_queue.wait_async(&waiter2);
1342            wk1.cancel();
1343            wait_queue.notify_all();
1344            assert!(waiter1.wait_until(&current_task, zx::MonotonicInstant::ZERO).is_err());
1345            assert!(waiter2.wait_until(&current_task, zx::MonotonicInstant::ZERO).is_ok());
1346        })
1347        .await;
1348    }
1349
1350    #[::fuchsia::test]
1351    async fn test_wait_queue() {
1352        spawn_kernel_and_run(async |current_task| {
1353            let queue = WaitQueue::default();
1354
1355            let waiters = <[Waiter; 3]>::default();
1356            waiters.iter().for_each(|w| {
1357                queue.wait_async(w);
1358            });
1359
1360            let woken = || {
1361                waiters
1362                    .iter()
1363                    .filter(|w| w.wait_until(&current_task, zx::MonotonicInstant::ZERO).is_ok())
1364                    .count()
1365            };
1366
1367            const INITIAL_NOTIFY_COUNT: usize = 2;
1368            let total_waiters = waiters.len();
1369            queue.notify_unordered_count(INITIAL_NOTIFY_COUNT);
1370            assert_eq!(INITIAL_NOTIFY_COUNT, woken());
1371
1372            // Only the remaining (unnotified) waiters should be notified.
1373            queue.notify_all();
1374            assert_eq!(total_waiters - INITIAL_NOTIFY_COUNT, woken());
1375        })
1376        .await;
1377    }
1378
1379    #[::fuchsia::test]
1380    async fn waiter_kind_abort_handle() {
1381        spawn_kernel_and_run_sync(|current_task| {
1382            let mut executor = fuchsia_async::TestExecutor::new();
1383            let (abort_handle, abort_registration) = futures::stream::AbortHandle::new_pair();
1384            let abort_handle = Arc::new(abort_handle);
1385            let waiter_ref = WaiterRef::from_abort_handle(&abort_handle);
1386
1387            let mut fut = futures::stream::Abortable::new(
1388                futures::future::pending::<()>(),
1389                abort_registration,
1390            );
1391
1392            assert_matches!(executor.run_until_stalled(&mut fut), std::task::Poll::Pending);
1393
1394            waiter_ref.interrupt();
1395            let output = current_task.run_in_state(RunState::Waiter(waiter_ref), move || {
1396                match executor.run_singlethreaded(&mut fut) {
1397                    Ok(()) => unreachable!("future never terminates normally"),
1398                    Err(futures::stream::Aborted) => Ok(()),
1399                }
1400            });
1401
1402            assert_eq!(output, Ok(()));
1403        })
1404        .await;
1405    }
1406
1407    #[::fuchsia::test]
1408    async fn waiter_kind_object_waiter() {
1409        spawn_kernel_and_run_sync(|current_task| {
1410            let waiter = ObjectWaiter::new();
1411            let event = zx::Event::create();
1412            // Waits for `event` in `RunState::Waiter`, with the `WaiterRef` of `guard`.
1413            let wait = |guard: ObjectWaitGuard<'_>| {
1414                let waiter_ref = WaiterRef::from_object_waiter(&guard);
1415                current_task.run_in_state(RunState::Waiter(waiter_ref), || {
1416                    Ok(guard.wait_many(
1417                        [event.wait_item(zx::Signals::USER_0)],
1418                        zx::MonotonicInstant::INFINITE,
1419                    ))
1420                })
1421            };
1422
1423            // An interruption of the task while it is blocked in `zx_object_wait_many` ends the
1424            // wait.
1425            let task = current_task.task.clone();
1426            let thread = fuchsia_runtime::with_thread_self(|thread| {
1427                thread.duplicate_handle(zx::Rights::SAME_RIGHTS).expect("duplicate_handle")
1428            });
1429            let interrupter = std::thread::spawn(move || {
1430                while thread.info().expect("info").state
1431                    != zx::ThreadState::Blocked(zx::ThreadBlockType::WaitMany)
1432                {
1433                    std::thread::sleep(std::time::Duration::from_millis(1));
1434                }
1435                task.interrupt();
1436            });
1437            assert_eq!(wait(waiter.begin_wait()), Ok(Err(ObjectWaitError::Interrupted)));
1438            interrupter.join().expect("join");
1439
1440            // An interruption through the `WaiterRef` after `begin_wait` ends the wait, even if the
1441            // task has not blocked yet.
1442            let guard = waiter.begin_wait();
1443            let waiter_ref = WaiterRef::from_object_waiter(&guard);
1444            waiter_ref.interrupt();
1445            assert_eq!(wait(guard), Ok(Err(ObjectWaitError::Interrupted)));
1446
1447            // The next wait ignores the previous interruptions, and ends when the object is
1448            // signaled.
1449            event.signal(zx::Signals::NONE, zx::Signals::USER_0).expect("signal");
1450            assert_eq!(wait(waiter.begin_wait()), Ok(Ok([zx::Signals::USER_0])));
1451
1452            // The `WaiterRef` does not keep the waiter alive.
1453            std::mem::drop(waiter);
1454            assert!(!waiter_ref.is_valid());
1455        })
1456        .await;
1457    }
1458
1459    #[::fuchsia::test]
1460    async fn freeze_with_pending_sigusr1() {
1461        spawn_kernel_and_run(async |current_task| {
1462            {
1463                let mut task_state = current_task.task.write();
1464                let siginfo = SignalInfo::kernel(SIGUSR1);
1465                task_state.enqueue_signal(siginfo);
1466                task_state.set_flags(TaskFlags::SIGNALS_AVAILABLE, true);
1467            }
1468
1469            let event = InterruptibleEvent::default();
1470            let output =
1471                current_task.block_until(event.begin_wait(), zx::MonotonicInstant::INFINITE);
1472            assert_eq!(output, error!(EINTR));
1473
1474            let output = current_task.run_in_state(RunState::Frozen(Waiter::new()), move || Ok(()));
1475            assert_eq!(output, Ok(()));
1476        })
1477        .await;
1478    }
1479
1480    #[::fuchsia::test]
1481    async fn block_until_stack_event_interrupted_by_other_thread() {
1482        spawn_kernel_and_run(async |current_task| {
1483            let task = Arc::clone(&current_task.task);
1484            let interrupter = std::thread::spawn(move || {
1485                while !matches!(task.read().run_state(), RunState::Event(_)) {
1486                    std::thread::yield_now();
1487                }
1488                task.interrupt();
1489            });
1490
1491            let event = InterruptibleEvent::default();
1492            let output =
1493                current_task.block_until(event.begin_wait(), zx::MonotonicInstant::INFINITE);
1494            assert_eq!(output, error!(EINTR));
1495            assert_eq!(current_task.read().run_state(), RunState::Running);
1496
1497            interrupter.join().expect("join interrupter");
1498        })
1499        .await;
1500    }
1501
1502    #[::fuchsia::test]
1503    async fn freeze_with_pending_sigkill() {
1504        spawn_kernel_and_run(async |current_task| {
1505            {
1506                let mut task_state = current_task.task.write();
1507                let siginfo = SignalInfo::kernel(SIGKILL);
1508                task_state.enqueue_signal(siginfo);
1509                task_state.set_flags(TaskFlags::SIGNALS_AVAILABLE, true);
1510            }
1511
1512            let output: Result<(), _> = current_task
1513                .run_in_state(RunState::Frozen(Waiter::new()), move || {
1514                    unreachable!("callback should not be called")
1515                });
1516            assert_eq!(output, error!(EINTR));
1517        })
1518        .await;
1519    }
1520
1521    #[::fuchsia::test]
1522    async fn tracing_stopped_with_pending_sigusr1() {
1523        spawn_kernel_and_run(async |current_task| {
1524            {
1525                let mut task_state = current_task.task.write();
1526                let siginfo = SignalInfo::kernel(SIGUSR1);
1527                task_state.enqueue_signal(siginfo);
1528            }
1529
1530            let task = Arc::clone(&current_task.task);
1531            let output = current_task.run_in_state(RunState::TracingStopped, move || {
1532                assert_eq!(task.state_code(), TaskStateCode::TracingStop);
1533                Ok(())
1534            });
1535            assert_eq!(output, Ok(()));
1536            assert_eq!(current_task.task.state_code(), TaskStateCode::Running);
1537
1538            let waiter = Waiter::new();
1539            waiter.notify();
1540            waiter.stop(&current_task);
1541        })
1542        .await;
1543    }
1544
1545    #[::fuchsia::test]
1546    async fn tracing_stopped_with_pending_sigkill() {
1547        spawn_kernel_and_run(async |current_task| {
1548            {
1549                let mut task_state = current_task.task.write();
1550                let siginfo = SignalInfo::kernel(SIGKILL);
1551                task_state.enqueue_signal(siginfo);
1552            }
1553
1554            let output: Result<(), _> = current_task
1555                .run_in_state(RunState::TracingStopped, move || {
1556                    unreachable!("callback should not be called")
1557                });
1558            assert_eq!(output, error!(EINTR));
1559
1560            let waiter = Waiter::new();
1561            waiter.stop(&current_task);
1562        })
1563        .await;
1564    }
1565
1566    #[::fuchsia::test]
1567    async fn wait_while_stopping_returns_eintr() {
1568        spawn_kernel_and_run(async |current_task| {
1569            current_task.write().set_stopped(
1570                crate::ptrace::StopState::GroupStopping,
1571                None,
1572                Some(current_task),
1573                None,
1574            );
1575
1576            let event = InterruptibleEvent::default();
1577            let output =
1578                current_task.block_until(event.begin_wait(), zx::MonotonicInstant::INFINITE);
1579            assert_eq!(output, error!(EINTR));
1580        })
1581        .await;
1582    }
1583
1584    #[::fuchsia::test]
1585    async fn test_async_typed_wait_value_with_handler() {
1586        spawn_kernel_and_run(async |current_task| {
1587            let queue: Arc<LockDepMutex<VecDeque<ReadyItem>, EventHandlerReadyQueueLock>> =
1588                Default::default();
1589            let handler = EventHandler::Enqueue {
1590                key: KEY,
1591                queue: queue.clone(),
1592                sought_events: FdEvents::all(),
1593            };
1594            let waiter = Waiter::new();
1595            let wait_queue = TypedWaitQueue::<u64>::default();
1596
1597            let test_value = 100u64;
1598            let _wait_canceler =
1599                wait_queue.wait_async_value_with_handler(&waiter, test_value, handler);
1600
1601            assert!(queue.lock().is_empty());
1602
1603            // Notify wrong value
1604            wait_queue.notify_value(test_value + 1);
1605            assert!(queue.lock().is_empty());
1606
1607            // Notify right value
1608            wait_queue.notify_value(test_value);
1609
1610            waiter.wait(&current_task).expect("wait failed");
1611
1612            // Result delivered via POLLIN logic in central dispatcher
1613            let ready_items = queue.lock();
1614            assert_eq!(ready_items.len(), 1);
1615            assert!(ready_items[0].events.contains(FdEvents::POLLIN));
1616        })
1617        .await;
1618    }
1619}