FreeBSD/sys/kern/kern_umtx.c
/*
 * Fetch and compare value, sleep on the address if value is not changed.
 */
Fetch and compare value, sleep on the address if value is not changed.
Fetch and compare value sleep on the address if value is not changed .
static int
do_wait(struct thread *td, void *addr, u_long id,
    struct _umtx_time *timeout, int compat32, int is_private)
{
	struct abs_timeout timo;
	struct umtx_q *uq;
	u_long tmp;
	uint32_t tmp32;
	int error = 0;
	uq = td->td_umtxq;
	if ((error = umtx_key_get(addr, TYPE_SIMPLE_WAIT,
		is_private ? THREAD_SHARE : AUTO_SHARE, &uq->uq_key)) != 0)
		return (error);
	if (timeout != NULL)
		abs_timeout_init2(&timo, timeout);
	umtxq_lock(&uq->uq_key);
	umtxq_insert(uq);
	umtxq_unlock(&uq->uq_key);
	if (compat32 == 0) {
		error = fueword(addr, &tmp);
		if (error != 0)
			error = EFAULT;
	} else {
		error = fueword32(addr, &tmp32);
		if (error == 0)
			tmp = tmp32;
		else
			error = EFAULT;
	}
	umtxq_lock(&uq->uq_key);
	if (error == 0) {
		if (tmp == id)
			error = umtxq_sleep(uq, "uwait", timeout == NULL ?
			    NULL : &timo);
		if ((uq->uq_flags & UQF_UMTXQ) == 0)
			error = 0;
		else
			umtxq_remove(uq);
	} else if ((uq->uq_flags & UQF_UMTXQ) != 0) {
		umtxq_remove(uq);
	}
	umtxq_unlock(&uq->uq_key);
	umtx_key_release(&uq->uq_key);
	if (error == ERESTART)
		error = EINTR;
	return (error);
}
static int do_wait ( struct thread * td , void * addr , u_long id , struct _umtx_time * timeout , int compat32 , int is_private ) { struct abs_timeout timo ; struct umtx_q * uq ; u_long tmp ; uint32_t tmp32 ; int error = 0 ; uq = td -> td_umtxq ; if ( ( error = umtx_key_get ( addr , TYPE_SIMPLE_WAIT , is_private ? THREAD_SHARE : AUTO_SHARE , & uq -> uq_key ) ) != 0 ) return ( error ) ; if ( timeout != NULL ) abs_timeout_init2 ( & timo , timeout ) ; umtxq_lock ( & uq -> uq_key ) ; umtxq_insert ( uq ) ; umtxq_unlock ( & uq -> uq_key ) ; if ( compat32 == 0 ) { error = fueword ( addr , & tmp ) ; if ( error != 0 ) error = EFAULT ; } else { error = fueword32 ( addr , & tmp32 ) ; if ( error == 0 ) tmp = tmp32 ; else error = EFAULT ; } umtxq_lock ( & uq -> uq_key ) ; if ( error == 0 ) { if ( tmp == id ) error = umtxq_sleep ( uq , " " , timeout == NULL ? NULL : & timo ) ; if ( ( uq -> uq_flags & UQF_UMTXQ ) == 0 ) error = 0 ; else umtxq_remove ( uq ) ; } else if ( ( uq -> uq_flags & UQF_UMTXQ ) != 0 ) { umtxq_remove ( uq ) ; } umtxq_unlock ( & uq -> uq_key ) ; umtx_key_release ( & uq -> uq_key ) ; if ( error == ERESTART ) error = EINTR ; return ( error ) ; }
Fetch and compare value, sleep on the address if value is not changed.
Fetch and compare value sleep on the address if value is not changed .