FreeBSD/sys/kern/kern_umtx.c
/*
 * Check if the mutex has waiters and tries to fix contention bit.
 */
Check if the mutex has waiters and tries to fix contention bit.
Check if the mutex has waiters and tries to fix contention bit .
static int
do_wake2_umutex(struct thread *td, struct umutex *m, uint32_t flags)
{
	struct umtx_key key;
	uint32_t owner, old;
	int type;
	int error;
	int count;
	switch (flags & (UMUTEX_PRIO_INHERIT | UMUTEX_PRIO_PROTECT |
	    UMUTEX_ROBUST)) {
	case 0:
	case UMUTEX_ROBUST:
		type = TYPE_NORMAL_UMUTEX;
		break;
	case UMUTEX_PRIO_INHERIT:
		type = TYPE_PI_UMUTEX;
		break;
	case (UMUTEX_PRIO_INHERIT | UMUTEX_ROBUST):
		type = TYPE_PI_ROBUST_UMUTEX;
		break;
	case UMUTEX_PRIO_PROTECT:
		type = TYPE_PP_UMUTEX;
		break;
	case (UMUTEX_PRIO_PROTECT | UMUTEX_ROBUST):
		type = TYPE_PP_ROBUST_UMUTEX;
		break;
	default:
		return (EINVAL);
	}
	if ((error = umtx_key_get(m, type, GET_SHARE(flags), &key)) != 0)
		return (error);
	owner = 0;
	umtxq_lock(&key);
	umtxq_busy(&key);
	count = umtxq_count(&key);
	umtxq_unlock(&key);
	if (count > 1) {
		error = fueword32(&m->m_owner, &owner);
		if (error == -1)
			error = EFAULT;
		while (error == 0 && (owner & UMUTEX_CONTESTED) == 0) {
			error = casueword32(&m->m_owner, owner, &old,
			    owner | UMUTEX_CONTESTED);
			if (error == -1) {
				error = EFAULT;
				break;
			}
			if (old == owner)
				break;
			owner = old;
			error = umtxq_check_susp(td);
			if (error != 0)
				break;
		}
	} else if (count == 1) {
		error = fueword32(&m->m_owner, &owner);
		if (error == -1)
			error = EFAULT;
		while (error == 0 && (owner & ~UMUTEX_CONTESTED) != 0 &&
		    (owner & UMUTEX_CONTESTED) == 0) {
			error = casueword32(&m->m_owner, owner, &old,
			    owner | UMUTEX_CONTESTED);
			if (error == -1) {
				error = EFAULT;
				break;
			}
			if (old == owner)
				break;
			owner = old;
			error = umtxq_check_susp(td);
			if (error != 0)
				break;
		}
	}
	umtxq_lock(&key);
	if (error == EFAULT) {
		umtxq_signal(&key, INT_MAX);
	} else if (count != 0 && ((owner & ~UMUTEX_CONTESTED) == 0 ||
	    owner == UMUTEX_RB_OWNERDEAD || owner == UMUTEX_RB_NOTRECOV))
		umtxq_signal(&key, 1);
	umtxq_unbusy(&key);
	umtxq_unlock(&key);
	umtx_key_release(&key);
	return (error);
}
static int do_wake2_umutex ( struct thread * td , struct umutex * m , uint32_t flags ) { struct umtx_key key ; uint32_t owner , old ; int type ; int error ; int count ; switch ( flags & ( UMUTEX_PRIO_INHERIT | UMUTEX_PRIO_PROTECT | UMUTEX_ROBUST ) ) { case 0 : case UMUTEX_ROBUST : type = TYPE_NORMAL_UMUTEX ; break ; case UMUTEX_PRIO_INHERIT : type = TYPE_PI_UMUTEX ; break ; case ( UMUTEX_PRIO_INHERIT | UMUTEX_ROBUST ) : type = TYPE_PI_ROBUST_UMUTEX ; break ; case UMUTEX_PRIO_PROTECT : type = TYPE_PP_UMUTEX ; break ; case ( UMUTEX_PRIO_PROTECT | UMUTEX_ROBUST ) : type = TYPE_PP_ROBUST_UMUTEX ; break ; default : return ( EINVAL ) ; } if ( ( error = umtx_key_get ( m , type , GET_SHARE ( flags ) , & key ) ) != 0 ) return ( error ) ; owner = 0 ; umtxq_lock ( & key ) ; umtxq_busy ( & key ) ; count = umtxq_count ( & key ) ; umtxq_unlock ( & key ) ; if ( count > 1 ) { error = fueword32 ( & m -> m_owner , & owner ) ; if ( error == -1 ) error = EFAULT ; while ( error == 0 && ( owner & UMUTEX_CONTESTED ) == 0 ) { error = casueword32 ( & m -> m_owner , owner , & old , owner | UMUTEX_CONTESTED ) ; if ( error == -1 ) { error = EFAULT ; break ; } if ( old == owner ) break ; owner = old ; error = umtxq_check_susp ( td ) ; if ( error != 0 ) break ; } } else if ( count == 1 ) { error = fueword32 ( & m -> m_owner , & owner ) ; if ( error == -1 ) error = EFAULT ; while ( error == 0 && ( owner & ~ UMUTEX_CONTESTED ) != 0 && ( owner & UMUTEX_CONTESTED ) == 0 ) { error = casueword32 ( & m -> m_owner , owner , & old , owner | UMUTEX_CONTESTED ) ; if ( error == -1 ) { error = EFAULT ; break ; } if ( old == owner ) break ; owner = old ; error = umtxq_check_susp ( td ) ; if ( error != 0 ) break ; } } umtxq_lock ( & key ) ; if ( error == EFAULT ) { umtxq_signal ( & key , INT_MAX ) ; } else if ( count != 0 && ( ( owner & ~ UMUTEX_CONTESTED ) == 0 || owner == UMUTEX_RB_OWNERDEAD || owner == UMUTEX_RB_NOTRECOV ) ) umtxq_signal ( & key , 1 ) ; umtxq_unbusy ( & key ) ; umtxq_unlock ( & key ) ; umtx_key_release ( & key ) ; return ( error ) ; }
Check if the mutex has waiters and tries to fix contention bit.
Check if the mutex has waiters and tries to fix contention bit .
/*
	 * Only repair contention bit if there is a waiter, this means the mutex
	 * is still being referenced by userland code, otherwise don't update
	 * any memory.
	 */