/* * Routine: wait_queue_member_locked * Purpose: * Indicate if this set queue is a member of the queue * Conditions: * The wait queue is locked * The set queue is just that, a set queue */ static boolean_t wait_queue_member_locked( wait_queue_t wq, wait_queue_set_t wq_set) { wait_queue_element_t wq_element; queue_t q; assert(wait_queue_held(wq)); assert(wait_queue_is_set(wq_set)); q = &wq->wq_queue; wq_element = (wait_queue_element_t) queue_first(q); while (!queue_end(q, (queue_entry_t)wq_element)) { WAIT_QUEUE_ELEMENT_CHECK(wq, wq_element); if ((wq_element->wqe_type == WAIT_QUEUE_LINK) || (wq_element->wqe_type == WAIT_QUEUE_LINK_NOALLOC)) { wait_queue_link_t wql = (wait_queue_link_t)wq_element; if (wql->wql_setqueue == wq_set) return TRUE; } wq_element = (wait_queue_element_t) queue_next((queue_t) wq_element); } return FALSE; }
/* * Routine: wait_queue_wakeup64_thread_locked * Purpose: * Wakeup the particular thread that was specified if and only * it was in this wait queue (or one of it's set queues) * and waiting on the specified event. * * This is much safer than just removing the thread from * whatever wait queue it happens to be on. For instance, it * may have already been awoken from the wait you intended to * interrupt and waited on something else (like another * semaphore). * Conditions: * at splsched * wait queue already locked (may be released). * Returns: * KERN_SUCCESS - the thread was found waiting and awakened * KERN_NOT_WAITING - the thread was not waiting here */ __private_extern__ kern_return_t wait_queue_wakeup64_thread_locked( wait_queue_t wq, event64_t event, thread_t thread, wait_result_t result, boolean_t unlock) { kern_return_t res; assert(wait_queue_held(wq)); /* * See if the thread was still waiting there. If so, it got * dequeued and returned locked. */ res = _wait_queue_select64_thread(wq, event, thread); if (unlock) wait_queue_unlock(wq); if (res != KERN_SUCCESS) return KERN_NOT_WAITING; res = thread_go(thread, result); assert(res == KERN_SUCCESS); thread_unlock(thread); return res; }
/* * Routine: wait_queue_wakeup64_one_locked * Purpose: * Select a single thread that is most-eligible to run and set * set it runnings. * * Conditions: * at splsched * wait queue locked * possibly recursive * Returns: * KERN_SUCCESS: It was, and is, now removed. * KERN_NOT_WAITING - No thread was waiting <wq,event> pair */ __private_extern__ kern_return_t wait_queue_wakeup64_one_locked( wait_queue_t wq, event64_t event, wait_result_t result, boolean_t unlock) { thread_t thread; assert(wait_queue_held(wq)); thread = _wait_queue_select64_one(wq, event); if (unlock) wait_queue_unlock(wq); if (thread) { kern_return_t res; res = thread_go(thread, result); assert(res == KERN_SUCCESS); thread_unlock(thread); return res; } return KERN_NOT_WAITING; }
/* * Routine: wait_queue_wakeup64_all_locked * Purpose: * Wakeup some number of threads that are in the specified * wait queue and waiting on the specified event. * Conditions: * wait queue already locked (may be released). * Returns: * KERN_SUCCESS - Threads were woken up * KERN_NOT_WAITING - No threads were waiting <wq,event> pair */ __private_extern__ kern_return_t wait_queue_wakeup64_all_locked( wait_queue_t wq, event64_t event, wait_result_t result, boolean_t unlock) { queue_head_t wake_queue_head; queue_t q = &wake_queue_head; kern_return_t res; assert(wait_queue_held(wq)); queue_init(q); /* * Select the threads that we will wake up. The threads * are returned to us locked and cleanly removed from the * wait queue. */ _wait_queue_select64_all(wq, event, q); if (unlock) wait_queue_unlock(wq); /* * For each thread, set it running. */ res = KERN_NOT_WAITING; while (!queue_empty (q)) { thread_t thread = (thread_t) dequeue(q); res = thread_go_locked(thread, result); assert(res == KERN_SUCCESS); thread_unlock(thread); } return res; }
/* * Routine: wait_queue_unlink_nofree * Purpose: * Undo the linkage between a wait queue and a set. */ static void wait_queue_unlink_locked( wait_queue_t wq, wait_queue_set_t wq_set, wait_queue_link_t wql) { assert(wait_queue_held(wq)); assert(wait_queue_held(&wq_set->wqs_wait_queue)); wql->wql_queue = WAIT_QUEUE_NULL; queue_remove(&wq->wq_queue, wql, wait_queue_link_t, wql_links); wql->wql_setqueue = WAIT_QUEUE_SET_NULL; queue_remove(&wq_set->wqs_setlinks, wql, wait_queue_link_t, wql_setlinks); wql->wql_type = WAIT_QUEUE_UNLINKED; WAIT_QUEUE_CHECK(wq); WAIT_QUEUE_SET_CHECK(wq_set); }
/* * Routine: wait_queue_wakeup64_identity_locked * Purpose: * Select a single thread that is most-eligible to run and set * set it running. But return the thread locked. * * Conditions: * at splsched * wait queue locked * possibly recursive * Returns: * a pointer to the locked thread that was awakened */ __private_extern__ thread_t wait_queue_wakeup64_identity_locked( wait_queue_t wq, event64_t event, wait_result_t result, boolean_t unlock) { kern_return_t res; thread_t thread; assert(wait_queue_held(wq)); thread = _wait_queue_select64_one(wq, event); if (unlock) wait_queue_unlock(wq); if (thread) { res = thread_go(thread, result); assert(res == KERN_SUCCESS); } return thread; /* still locked if not NULL */ }