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