/* * Routine: wait_queue_wakeup_all * Purpose: * Wakeup some number of threads that are in the specified * wait queue and waiting on the specified event. * Conditions: * Nothing locked * Returns: * KERN_SUCCESS - Threads were woken up * KERN_NOT_WAITING - No threads were waiting <wq,event> pair */ kern_return_t wait_queue_wakeup_all( wait_queue_t wq, event_t event, wait_result_t result) { kern_return_t ret; spl_t s; if (!wait_queue_is_valid(wq)) { return KERN_INVALID_ARGUMENT; } s = splsched(); wait_queue_lock(wq); // if(!wq->wq_interlock.lock_data) { /* (BRINGUP */ // panic("wait_queue_wakeup_all: we did not get the lock on %p\n", wq); /* (BRINGUP) */ // } ret = wait_queue_wakeup64_all_locked( wq, CAST_DOWN(event64_t,event), result, TRUE); /* lock released */ splx(s); return ret; }
/* * Routine: semaphore_destroy * * Destroys a semaphore. This call will only succeed if the * specified task is the SAME task name specified at the semaphore's * creation. * * All threads currently blocked on the semaphore are awoken. These * threads will return with the KERN_TERMINATED error. */ kern_return_t semaphore_destroy( task_t task, semaphore_t semaphore) { int old_count; spl_t spl_level; if (task == TASK_NULL || semaphore == SEMAPHORE_NULL) return KERN_INVALID_ARGUMENT; /* * Disown semaphore */ task_lock(task); if (semaphore->owner != task) { task_unlock(task); return KERN_INVALID_ARGUMENT; } remqueue(&task->semaphore_list, (queue_entry_t) semaphore); semaphore->owner = TASK_NULL; task->semaphores_owned--; task_unlock(task); spl_level = splsched(); semaphore_lock(semaphore); /* * Deactivate semaphore */ assert(semaphore->active); semaphore->active = FALSE; /* * Wakeup blocked threads */ old_count = semaphore->count; semaphore->count = 0; if (old_count < 0) { wait_queue_wakeup64_all_locked(&semaphore->wait_queue, SEMAPHORE_EVENT, THREAD_RESTART, TRUE); /* unlock? */ } else { semaphore_unlock(semaphore); } splx(spl_level); /* * Deallocate * * Drop the semaphore reference, which in turn deallocates the * semaphore structure if the reference count goes to zero. */ ipc_port_dealloc_kernel(semaphore->port); semaphore_dereference(semaphore); return KERN_SUCCESS; }
void ipc_mqueue_changed( ipc_mqueue_t mqueue) { wait_queue_wakeup64_all_locked( &mqueue->imq_wait_queue, IPC_MQUEUE_RECEIVE, THREAD_RESTART, FALSE); /* unlock waitq? */ }
/* * Routine: wait_queue_wakeup64_all * Purpose: * Wakeup some number of threads that are in the specified * wait queue and waiting on the specified event. * Conditions: * Nothing locked * Returns: * KERN_SUCCESS - Threads were woken up * KERN_NOT_WAITING - No threads were waiting <wq,event> pair */ kern_return_t wait_queue_wakeup64_all( wait_queue_t wq, event64_t event, wait_result_t result) { kern_return_t ret; spl_t s; if (!wait_queue_is_valid(wq)) { return KERN_INVALID_ARGUMENT; } s = splsched(); wait_queue_lock(wq); ret = wait_queue_wakeup64_all_locked(wq, event, result, TRUE); /* lock released */ splx(s); return ret; }
/* * Routine: semaphore_signal_internal * * Signals the semaphore as direct. * Assumptions: * Semaphore is locked. */ kern_return_t semaphore_signal_internal( semaphore_t semaphore, thread_t thread, int options) { kern_return_t kr; spl_t spl_level; spl_level = splsched(); semaphore_lock(semaphore); if (!semaphore->active) { semaphore_unlock(semaphore); splx(spl_level); return KERN_TERMINATED; } if (thread != THREAD_NULL) { if (semaphore->count < 0) { kr = wait_queue_wakeup64_thread_locked( &semaphore->wait_queue, SEMAPHORE_EVENT, thread, THREAD_AWAKENED, TRUE); /* unlock? */ } else { semaphore_unlock(semaphore); kr = KERN_NOT_WAITING; } splx(spl_level); return kr; } if (options & SEMAPHORE_SIGNAL_ALL) { int old_count = semaphore->count; if (old_count < 0) { semaphore->count = 0; /* always reset */ kr = wait_queue_wakeup64_all_locked( &semaphore->wait_queue, SEMAPHORE_EVENT, THREAD_AWAKENED, TRUE); /* unlock? */ } else { if (options & SEMAPHORE_SIGNAL_PREPOST) semaphore->count++; semaphore_unlock(semaphore); kr = KERN_SUCCESS; } splx(spl_level); return kr; } if (semaphore->count < 0) { if (wait_queue_wakeup64_one_locked( &semaphore->wait_queue, SEMAPHORE_EVENT, THREAD_AWAKENED, FALSE) == KERN_SUCCESS) { semaphore_unlock(semaphore); splx(spl_level); return KERN_SUCCESS; } else semaphore->count = 0; /* all waiters gone */ } if (options & SEMAPHORE_SIGNAL_PREPOST) { semaphore->count++; } semaphore_unlock(semaphore); splx(spl_level); return KERN_NOT_WAITING; }