+#if !defined(i386)
+ thread_t thread = current_thread();
+
+ if (thread->top_act != holder)
+ panic("mutex_unlock_wakeup: mutex %x holder %x\n", mutex, holder);
+
+ if (thread->promotions > 0) {
+ spl_t s = splsched();
+
+ thread_lock(thread);
+ if ( --thread->promotions == 0 &&
+ (thread->sched_mode & TH_MODE_PROMOTED) ) {
+ thread->sched_mode &= ~TH_MODE_PROMOTED;
+ if (thread->sched_mode & TH_MODE_ISDEPRESSED) {
+ KERNEL_DEBUG_CONSTANT(
+ MACHDBG_CODE(DBG_MACH_SCHED,MACH_DEMOTE) | DBG_FUNC_NONE,
+ thread->sched_pri, DEPRESSPRI, 0, (int)mutex, 0);
+
+ set_sched_pri(thread, DEPRESSPRI);
+ }
+ else {
+ if (thread->priority < thread->sched_pri) {
+ KERNEL_DEBUG_CONSTANT(
+ MACHDBG_CODE(DBG_MACH_SCHED,MACH_DEMOTE) |
+ DBG_FUNC_NONE,
+ thread->sched_pri, thread->priority,
+ 0, (int)mutex, 0);
+ }
+
+ compute_priority(thread, FALSE);
+ }
+ }
+ thread_unlock(thread);
+ splx(s);
+ }
+#endif
+
+ assert(mutex->waiters > 0);
+ thread_wakeup_one(mutex);
+}
+
+boolean_t
+mutex_preblock_wait(
+ mutex_t *mutex,
+ thread_t thread,
+ thread_t holder)
+{
+ wait_result_t wresult;
+ integer_t priority;
+ wait_queue_t wq;
+
+ assert(holder == NULL || holder->thread == holder);
+
+ wq = wait_event_wait_queue((event_t)mutex);
+ if (!wait_queue_lock_try(wq))
+ return (FALSE);
+
+ if (holder != NULL && !thread_lock_try(holder)) {
+ wait_queue_unlock(wq);
+ return (FALSE);
+ }
+
+ wresult = wait_queue_assert_wait64_locked(wq, (uint32_t)mutex,
+ THREAD_UNINT, thread);
+ wait_queue_unlock(wq);
+ assert(wresult == THREAD_WAITING);
+
+ priority = thread->sched_pri;
+ if (priority < thread->priority)
+ priority = thread->priority;
+ if (priority > MINPRI_KERNEL)
+ priority = MINPRI_KERNEL;
+ else
+ if (priority < BASEPRI_DEFAULT)
+ priority = BASEPRI_DEFAULT;
+
+ if (holder != NULL) {
+ if (mutex->promoted_pri == 0)
+ holder->promotions++;
+ if (holder->priority < MINPRI_KERNEL) {
+ holder->sched_mode |= TH_MODE_PROMOTED;
+ if ( mutex->promoted_pri < priority &&
+ holder->sched_pri < priority ) {
+ KERNEL_DEBUG_CONSTANT(
+ MACHDBG_CODE(DBG_MACH_SCHED,MACH_PROMOTE) | DBG_FUNC_NONE,
+ holder->sched_pri, priority,
+ (int)holder, (int)mutex, 0);
+
+ set_sched_pri(holder, priority);
+ }
+ }
+ thread_unlock(holder);
+ }
+
+ if (mutex->promoted_pri < priority)
+ mutex->promoted_pri = priority;
+
+ if (thread->pending_promoter[thread->pending_promoter_index] == NULL) {
+ thread->pending_promoter[thread->pending_promoter_index] = mutex;
+ mutex->waiters++;
+ }
+ else
+ if (thread->pending_promoter[thread->pending_promoter_index] != mutex) {
+ thread->pending_promoter[++thread->pending_promoter_index] = mutex;
+ mutex->waiters++;
+ }
+
+ KERNEL_DEBUG_CONSTANT(
+ MACHDBG_CODE(DBG_MACH_SCHED,MACH_PREBLOCK_MUTEX) | DBG_FUNC_NONE,
+ (int)thread, thread->sched_pri, (int)mutex, 0, 0);
+
+ return (TRUE);