1 // © 2021 Qualcomm Innovation Center, Inc. All rights reserved.
2 //
3 // SPDX-License-Identifier: BSD-3-Clause
4 
5 // A simple wait_queue for blocking threads while waiting on events.
6 // TODO: add support for interruption - e.g. destroying threads
7 
8 // Ordering in the wait_queue API:
9 //
10 // An acquire operation is implied by any wait_queue_wait() call that sleeps;
11 // and a release operation on the wait queue is implied by any
12 // wait_queue_wakeup() call that wakes up at least one thread.
13 
14 // Initialise the wait_queue.
15 void
16 wait_queue_init(wait_queue_t *wait_queue);
17 
18 // Enqueue calling thread on the wait_queue.
19 //
20 // Must be called before calling wait_queue_get(), and finally the caller
21 // should call wait_queue_finish() when done.
22 void
23 wait_queue_prepare(wait_queue_t *wait_queue)
24 	ACQUIRE_PREEMPT_DISABLED ACQUIRE_LOCK(wait_queue);
25 
26 // The calling thread enters a critical section where it is safe to perform the
27 // condition check without races. If the condition passes, then call
28 // wait_queue_put(), else call wait_queue_wait().
29 //
30 // wait_queue_prepare() must have been called prior to this.
31 void
32 wait_queue_get(void)
33 	REQUIRE_PREEMPT_DISABLED ACQUIRE_LOCK(wait_queue_condition);
34 
35 // Exit the wait_queue critical section.
36 //
37 // Must be called after wait_queue_get() and the subsequent condition check
38 // succeeded. Must not be called after wait_queue_wait().
39 void
40 wait_queue_put(void)
41 	REQUIRE_PREEMPT_DISABLED RELEASE_LOCK(wait_queue_condition);
42 
43 // Atomically exit the wait_queue critical section and block until a wakeup
44 // event.
45 //
46 // May be called after wait_queue_get() and the subsequent condition check
47 // fails and we want to yield. Must not be called after wait_queue_put().
48 void
49 wait_queue_wait(void)
50 	REQUIRE_PREEMPT_DISABLED RELEASE_LOCK(wait_queue_condition);
51 
52 // Dequeue the thread from the wait_queue. Call this when woken up and the wait
53 // condition now passes, after wait_queue_put() or wait_queue_wait().
54 void
55 wait_queue_finish(wait_queue_t *wait_queue)
56 	RELEASE_PREEMPT_DISABLED RELEASE_LOCK(wait_queue)
57 		EXCLUDE_LOCK(wait_queue_condition);
58 
59 // Perform a wakeup event on the wait_queue
60 void
61 wait_queue_wakeup(wait_queue_t *wait_queue);
62