-Llml_ext_fail:
-#ifdef LOG_FIRST_MISS_ALONE
- testl $1, %edi
- jnz 1f
-#endif /* LOG_FIRST_MISS_ALONE */
- /* Record that a lock acquire attempt missed (per-group statistic) */
- LOCK_IF_ATOMIC_STAT_UPDATES
- incl GRP_MTX_STAT_MISS(%esi)
-#ifdef LOG_FIRST_MISS_ALONE
- orl $1, %edi
-#endif /* LOG_FIRST_MISS_ALONE */
-1:
- /*
- * Check if the owner is on another processor and therefore
- * we should try to spin before blocking.
- */
- testl $(OnProc),ACT_SPF(%ecx)
- jnz 2f
- /*
- * Record the "direct wait" statistic, which indicates if a
- * miss proceeded to block directly without spinning--occurs
- * if the owner of the mutex isn't running on another processor
- * at the time of the check.
- */
- LOCK_IF_ATOMIC_STAT_UPDATES
- incl GRP_MTX_STAT_DIRECT_WAIT(%esi)
- jmp Llml_ext_block
-2:
- /*
- * Here if owner is on another processor:
- * - release the interlock
- * - spin on the holder until release or timeout
- * - in either case re-acquire the interlock
- * - if released, acquire it
- * - otherwise drop thru to block.
- */
- xorl %eax,%eax
- movl %eax,M_ILK /* zero interlock */
-
- pushl 8(%esp) /* Make another copy of EFLAGS image */
- popf /* Restore interrupt state */
- pushl %edx /* save mutex address */
- pushl %edx
- call EXT(lck_mtx_lock_spinwait)
- addl $4,%esp
- popl %edx /* restore mutex address */
-
- /* Re-acquire interlock */
- movl M_ILK,%eax /* read interlock */
- testl %eax,%eax /* unlocked? */
- jne Llml_ext_ilk_refail /* no, go to spin loop */
-Llml_ext_reget_retry:
- cli /* disable interrupts */
- movl %gs:CPU_ACTIVE_THREAD,%ecx
-
- /* eax == 0 at this point */
- lock; cmpxchgl %ecx,M_ILK /* atomic compare and exchange */
- jne Llml_ext_ilk_refail /* branch on failure to spin loop */
-
- movl M_LOCKED,%ecx /* get lock owner */
- testl %ecx,%ecx /* is the mutex free? */
- je Llml_ext_acquire /* yes, acquire */
-
-Llml_ext_block:
- /* If we wanted to count waits just once per lock acquire, we'd
- * skip over the stat update here
- */
- LOCK_IF_ATOMIC_STAT_UPDATES
- /* Record that a lock miss proceeded to block */
- incl GRP_MTX_STAT_WAIT(%esi)
-1:
- CHECK_MYLOCK(M_THREAD)
- pushl %edx /* save mutex address */
- pushl M_LOCKED
- pushl %edx /* push mutex address */
- /*
- * N.B.: lck_mtx_lock_wait is called here with interrupts disabled
- * Consider reworking.
- */
- call EXT(lck_mtx_lock_wait) /* wait for the lock */
- addl $8,%esp
- popl %edx /* restore mutex address */
- jmp Llml_ext_restart /* and start over */
-
-Llml_ext_ilk_refail:
- movl 8(%esp),%ecx
- pushl %ecx
- popf /* restore interrupt state */
-
-Llml_ext_ilk_reloop: