- ulock_t ulock;
- int i;
-
- if (task == TASK_NULL || lock_set == LOCK_SET_NULL)
- return KERN_INVALID_ARGUMENT;
-
- if (lock_set->owner != task)
- return KERN_INVALID_RIGHT;
-
- lock_set_lock(lock_set);
- if (!lock_set->active) {
- lock_set_unlock(lock_set);
- return KERN_LOCK_SET_DESTROYED;
- }
-
- /*
- * Deactivate lock set
- */
- lock_set->active = FALSE;
-
- /*
- * If a ulock is currently held in the target lock set:
- *
- * 1) Wakeup all threads blocked on the ulock (if any). Threads
- * may be blocked waiting normally, or waiting for a handoff.
- * Blocked threads will return with KERN_LOCK_SET_DESTROYED.
- *
- * 2) ulock ownership is cleared.
- * The thread currently holding the ulock is revoked of its
- * ownership.
- */
- for (i = 0; i < lock_set->n_ulocks; i++) {
- ulock = &lock_set->ulock_list[i];
-
- ulock_lock(ulock);
-
- if (ulock->accept_wait) {
- ulock->accept_wait = FALSE;
- wait_queue_wakeup64_one(&ulock->wait_queue,
- LOCK_SET_HANDOFF,
- THREAD_RESTART);
- }
-
- if (ulock->holder) {
- if (ulock->blocked) {
- ulock->blocked = FALSE;
- wait_queue_wakeup64_all(&ulock->wait_queue,
- LOCK_SET_EVENT,
- THREAD_RESTART);
- }
- if (ulock->ho_wait) {
- ulock->ho_wait = FALSE;
- wait_queue_wakeup64_one(&ulock->wait_queue,
- LOCK_SET_HANDOFF,
- THREAD_RESTART);
- }
- ulock_ownership_clear(ulock);
- }
-
- ulock_unlock(ulock);
- }
-
- lock_set_unlock(lock_set);
- lock_set_ownership_clear(lock_set, task);
-
- /*
- * Deallocate
- *
- * Drop the lock set reference, which inturn destroys the
- * lock set structure if the reference count goes to zero.
- */
-
- ipc_port_dealloc_kernel(lock_set->port);
- lock_set_dereference(lock_set);
-
- return KERN_SUCCESS;
-}
-
-kern_return_t
-lock_acquire (lock_set_t lock_set, int lock_id)
-{
- ulock_t ulock;
-
- if (lock_set == LOCK_SET_NULL)
- return KERN_INVALID_ARGUMENT;
-
- if (lock_id < 0 || lock_id >= lock_set->n_ulocks)
- return KERN_INVALID_ARGUMENT;
-
- retry:
- lock_set_lock(lock_set);
- if (!lock_set->active) {
- lock_set_unlock(lock_set);
- return KERN_LOCK_SET_DESTROYED;
- }
-
- ulock = (ulock_t) &lock_set->ulock_list[lock_id];
- ulock_lock(ulock);
- lock_set_unlock(lock_set);
-
- /*
- * Block the current thread if the lock is already held.
- */
-
- if (ulock->holder != THREAD_NULL) {
- int wait_result;
-
- if (ulock->holder == current_thread()) {
- ulock_unlock(ulock);
- return KERN_LOCK_OWNED_SELF;
- }
-
- ulock->blocked = TRUE;
- wait_result = wait_queue_assert_wait64(&ulock->wait_queue,
- LOCK_SET_EVENT,
- THREAD_ABORTSAFE, 0);
- ulock_unlock(ulock);
-
- /*
- * Block - Wait for lock to become available.
- */
- if (wait_result == THREAD_WAITING)
- wait_result = thread_block(THREAD_CONTINUE_NULL);
-
- /*
- * Check the result status:
- *
- * Check to see why thread was woken up. In all cases, we
- * already have been removed from the queue.
- */
- switch (wait_result) {
- case THREAD_AWAKENED:
- /* lock transitioned from old locker to us */
- /* he already made us owner */
- return (ulock->unstable) ? KERN_LOCK_UNSTABLE :
- KERN_SUCCESS;
-
- case THREAD_INTERRUPTED:
- return KERN_ABORTED;
-
- case THREAD_RESTART:
- goto retry; /* probably a dead lock_set */
-
- default:
- panic("lock_acquire\n");
- }
- }
-
- /*
- * Assign lock ownership
- */
- ulock_ownership_set(ulock, current_thread());
- ulock_unlock(ulock);
-
- return (ulock->unstable) ? KERN_LOCK_UNSTABLE : KERN_SUCCESS;