- movl L_ARG0,%edx /* fetch lock pointer */
-
- CHECK_SIMPLE_LOCK_TYPE()
- CHECK_THREAD(S_THREAD)
-
-#if MACH_LDEBUG
- xorl %eax,%eax
- movl %eax,S_THREAD /* disown thread */
- MP_DISABLE_PREEMPTION(%eax)
- CPU_NUMBER(%eax)
- decl CX(EXT(simple_lock_count),%eax)
- MP_ENABLE_PREEMPTION(%eax)
-#if 0
- METER_SIMPLE_LOCK_UNLOCK(%edx)
-#endif
-#if NCPUS == 1
- pushf
- pushl %edx
- cli
- call EXT(lock_stack_pop)
- popl %edx
- popfl
-#endif /* NCPUS == 1 */
-#endif /* MACH_LDEBUG */
-
- xorl %ecx,%ecx
- xchgl USL_INTERLOCK(%edx),%ecx /* unlock the HW lock */
-
- ENABLE_PREEMPTION(%eax)
-
- EMARF
- ret
-
-#endif /* 0 */
-
-
-ENTRY(mutex_init)
- FRAME
- movl L_ARG0,%edx /* fetch lock pointer */
- xorl %eax,%eax
- movl %eax,M_ILK /* clear interlock */
- movl %eax,M_LOCKED /* clear locked flag */
- movw %ax,M_WAITERS /* init waiter count */
- movw %ax,M_PROMOTED_PRI
-
-#if MACH_LDEBUG
- movl $ MUTEX_TAG,M_TYPE /* set lock type */
- movl %eax,M_PC /* init caller pc */
- movl %eax,M_THREAD /* and owning thread */
-#endif
-#if ETAP_LOCK_TRACE
- movl L_ARG1,%ecx /* fetch event type */
- pushl %ecx /* push event type */
- pushl %edx /* push mutex address */
- call EXT(etap_mutex_init) /* init ETAP data */
- addl $8,%esp
-#endif /* ETAP_LOCK_TRACE */
-
- EMARF
- ret
-
-ENTRY2(mutex_lock,_mutex_lock)
- FRAME
-
-#if ETAP_LOCK_TRACE
- subl $12,%esp /* make room for locals */
- movl $0,SWT_HI /* set wait time to zero (HI) */
- movl $0,SWT_LO /* set wait time to zero (LO) */
- movl $0,MISSED /* clear local miss marker */
-#endif /* ETAP_LOCK_TRACE */
-
- movl L_ARG0,%edx /* fetch lock pointer */
-
- CHECK_MUTEX_TYPE()
- CHECK_NO_SIMPLELOCKS()
- CHECK_PREEMPTION_LEVEL()
-
-ml_retry:
- DISABLE_PREEMPTION(%eax)
-
-ml_get_hw:
- movl $1,%ecx
- xchgl %ecx,M_ILK
- testl %ecx,%ecx /* did we succeed? */
- jne ml_get_hw /* no, try again */
-
- movl $1,%ecx
- xchgl %ecx,M_LOCKED /* try to set locked flag */
- testl %ecx,%ecx /* is the mutex locked? */
- jne ml_fail /* yes, we lose */
-
- pushl %edx
- call EXT(mutex_lock_acquire)
- addl $4,%esp
- movl L_ARG0,%edx
-
-#if MACH_LDEBUG
- movl L_PC,%ecx
- movl %ecx,M_PC
- movl $ CPD_ACTIVE_THREAD,%eax
- movl %gs:(%eax),%ecx
- movl %ecx,M_THREAD
- testl %ecx,%ecx
- je 3f
- incl TH_MUTEX_COUNT(%ecx)
-3:
-#endif
-
- xorl %ecx,%ecx
- xchgl %ecx,M_ILK
-
- ENABLE_PREEMPTION(%eax)
-
-#if ETAP_LOCK_TRACE
- movl L_PC,%eax /* fetch pc */
- pushl SWT_LO /* push wait time (low) */
- pushl SWT_HI /* push wait time (high) */
- pushl %eax /* push pc */
- pushl %edx /* push mutex address */
- call EXT(etap_mutex_hold) /* collect hold timestamp */
- addl $16+12,%esp /* clean up stack, adjusting for locals */
-#endif /* ETAP_LOCK_TRACE */
-
- EMARF
- ret
-
-ml_fail:
-#if ETAP_LOCK_TRACE
- cmp $0,MISSED /* did we already take a wait timestamp? */
- jne ml_block /* yup. carry-on */
- pushl %edx /* push mutex address */
- call EXT(etap_mutex_miss) /* get wait timestamp */
- movl %eax,SWT_HI /* set wait time (high word) */
- movl %edx,SWT_LO /* set wait time (low word) */
- popl %edx /* clean up stack */
- movl $1,MISSED /* mark wait timestamp as taken */
-#endif /* ETAP_LOCK_TRACE */
-
-ml_block:
- CHECK_MYLOCK(M_THREAD)
- xorl %eax,%eax
- pushl %eax /* no promotion here yet */
- pushl %edx /* push mutex address */
- call EXT(mutex_lock_wait) /* wait for the lock */
- addl $8,%esp
- movl L_ARG0,%edx /* refetch lock pointer */
- jmp ml_retry /* and try again */
-
-ENTRY2(mutex_try,_mutex_try)
- FRAME
-
-#if ETAP_LOCK_TRACE
- subl $8,%esp /* make room for locals */
- movl $0,SWT_HI /* set wait time to zero (HI) */
- movl $0,SWT_LO /* set wait time to zero (LO) */
-#endif /* ETAP_LOCK_TRACE */
-
- movl L_ARG0,%edx /* fetch lock pointer */
-
- CHECK_MUTEX_TYPE()
- CHECK_NO_SIMPLELOCKS()
-
- DISABLE_PREEMPTION(%eax)
-
-mt_get_hw:
- movl $1,%ecx
- xchgl %ecx,M_ILK
- testl %ecx,%ecx
- jne mt_get_hw
-
- movl $1,%ecx
- xchgl %ecx,M_LOCKED
- testl %ecx,%ecx
- jne mt_fail
-
- pushl %edx
- call EXT(mutex_lock_acquire)
- addl $4,%esp
- movl L_ARG0,%edx
-
-#if MACH_LDEBUG
- movl L_PC,%ecx
- movl %ecx,M_PC
- movl $ CPD_ACTIVE_THREAD,%ecx
- movl %gs:(%ecx),%ecx
- movl %ecx,M_THREAD
- testl %ecx,%ecx
- je 1f
- incl TH_MUTEX_COUNT(%ecx)
-1:
-#endif
-
- xorl %ecx,%ecx
- xchgl %ecx,M_ILK
-
- ENABLE_PREEMPTION(%eax)
-
-#if ETAP_LOCK_TRACE
- movl L_PC,%eax /* fetch pc */
- pushl SWT_LO /* push wait time (low) */
- pushl SWT_HI /* push wait time (high) */
- pushl %eax /* push pc */
- pushl %edx /* push mutex address */
- call EXT(etap_mutex_hold) /* get start hold timestamp */
- addl $16,%esp /* clean up stack, adjusting for locals */
-#endif /* ETAP_LOCK_TRACE */
-
- movl $1,%eax
-
-#if MACH_LDEBUG || ETAP_LOCK_TRACE
-#if ETAP_LOCK_TRACE
- addl $8,%esp /* pop stack claimed on entry */
-#endif
-#endif
-
- EMARF
- ret
-
-mt_fail:
- xorl %ecx,%ecx
- xchgl %ecx,M_ILK
-
- ENABLE_PREEMPTION(%eax)
-
-#if ETAP_LOCK_TRACE
- movl L_PC,%eax /* fetch pc */
- pushl SWT_LO /* push wait time (low) */
- pushl SWT_HI /* push wait time (high) */
- pushl %eax /* push pc */
- pushl %edx /* push mutex address */
- call EXT(etap_mutex_hold) /* get start hold timestamp */
- addl $16,%esp /* clean up stack, adjusting for locals */
-#endif /* ETAP_LOCK_TRACE */
-
- xorl %eax,%eax
-
-#if MACH_LDEBUG || ETAP_LOCK_TRACE
-#if ETAP_LOCK_TRACE
- addl $8,%esp /* pop stack claimed on entry */
-#endif
-#endif
-
- EMARF
- ret
-
-ENTRY(mutex_unlock)
- FRAME
- movl L_ARG0,%edx /* fetch lock pointer */
-
-#if ETAP_LOCK_TRACE
- pushl %edx /* push mutex address */
- call EXT(etap_mutex_unlock) /* collect ETAP data */
- popl %edx /* restore mutex address */
-#endif /* ETAP_LOCK_TRACE */
-
- CHECK_MUTEX_TYPE()
- CHECK_THREAD(M_THREAD)
-
- DISABLE_PREEMPTION(%eax)
-
-mu_get_hw:
- movl $1,%ecx
- xchgl %ecx,M_ILK
- testl %ecx,%ecx /* did we succeed? */
- jne mu_get_hw /* no, try again */
-
- cmpw $0,M_WAITERS /* are there any waiters? */
- jne mu_wakeup /* yes, more work to do */
-
-mu_doit:
-#if MACH_LDEBUG
- xorl %eax,%eax
- movl %eax,M_THREAD /* disown thread */
- movl $ CPD_ACTIVE_THREAD,%eax
- movl %gs:(%eax),%ecx
- testl %ecx,%ecx
- je 0f
- decl TH_MUTEX_COUNT(%ecx)
-0:
-#endif
-
- xorl %ecx,%ecx
- xchgl %ecx,M_LOCKED /* unlock the mutex */
-
- xorl %ecx,%ecx
- xchgl %ecx,M_ILK
-
- ENABLE_PREEMPTION(%eax)
-
- EMARF
- ret
-
-mu_wakeup:
- xorl %eax,%eax
- pushl %eax /* no promotion here yet */
- pushl %edx /* push mutex address */
- call EXT(mutex_unlock_wakeup)/* yes, wake a thread */
- addl $8,%esp
- movl L_ARG0,%edx /* refetch lock pointer */
- jmp mu_doit
-
-ENTRY(interlock_unlock)
- FRAME
- movl L_ARG0,%edx
-
- xorl %ecx,%ecx
- xchgl %ecx,M_ILK
-
- ENABLE_PREEMPTION(%eax)
-
- EMARF
- ret
-
-
-ENTRY(_disable_preemption)
-#if MACH_RT
- _DISABLE_PREEMPTION(%eax)
-#endif /* MACH_RT */
- ret
-
-ENTRY(_enable_preemption)
-#if MACH_RT
-#if MACH_ASSERT
- movl $ CPD_PREEMPTION_LEVEL,%eax
- cmpl $0,%gs:(%eax)
- jg 1f
- pushl %gs:(%eax)
- pushl $2f
- call EXT(panic)