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