FreeBSD/sys/compat/cloudabi/cloudabi_futex.c
/*
 * Blocking calls: acquiring locks, waiting on condition variables.
 */
Blocking calls: acquiring locks, waiting on condition variables.
Blocking calls : acquiring locks waiting on condition variables .
int
cloudabi_futex_condvar_wait(struct thread *td, cloudabi_condvar_t *condvar,
    cloudabi_scope_t condvar_scope, cloudabi_lock_t *lock,
    cloudabi_scope_t lock_scope, cloudabi_clockid_t clock_id,
    cloudabi_timestamp_t timeout, cloudabi_timestamp_t precision)
{
	struct futex_condvar *fc;
	struct futex_lock *fl;
	struct futex_waiter fw;
	int error, error2;
	error = futex_condvar_lookup_or_create(td, condvar, condvar_scope, lock,
	    lock_scope, &fc);
	if (error != 0)
		return (error);
	fl = fc->fc_lock;
	error = futex_user_store(condvar, ~CLOUDABI_CONDVAR_HAS_NO_WAITERS);
	if (error != 0) {
		futex_condvar_release(fc);
		return (error);
	}
	error = futex_lock_unlock(fl, td, lock);
	if (error != 0) {
		futex_condvar_unmanage(fc, condvar);
		futex_condvar_release(fc);
		return (error);
	}
	++fc->fc_waitcount;
	error = futex_queue_sleep(&fc->fc_waiters, fc->fc_lock, &fw, td,
	    clock_id, timeout, precision);
	if (fw.fw_locked) {
		KASSERT(futex_queue_count(&fw.fw_donated) == 0,
		    ("Received threads while being locked"));
	} else if (error == 0 || error == ETIMEDOUT) {
		if (error != 0)
			futex_condvar_unmanage(fc, condvar);
		error2 = futex_lock_wrlock(fl, td, lock,
		    CLOUDABI_CLOCK_MONOTONIC, UINT64_MAX, 0, &fw.fw_donated);
		if (error2 != 0)
			error = error2;
	} else {
		KASSERT(futex_queue_count(&fw.fw_donated) == 0,
		    ("Received threads on error"));
		futex_condvar_unmanage(fc, condvar);
		futex_lock_unmanage(fl, lock);
	}
	--fc->fc_waitcount;
	futex_condvar_release(fc);
	return (error);
}
int cloudabi_futex_condvar_wait ( struct thread * td , cloudabi_condvar_t * condvar , cloudabi_scope_t condvar_scope , cloudabi_lock_t * lock , cloudabi_scope_t lock_scope , cloudabi_clockid_t clock_id , cloudabi_timestamp_t timeout , cloudabi_timestamp_t precision ) { struct futex_condvar * fc ; struct futex_lock * fl ; struct futex_waiter fw ; int error , error2 ; error = futex_condvar_lookup_or_create ( td , condvar , condvar_scope , lock , lock_scope , & fc ) ; if ( error != 0 ) return ( error ) ; fl = fc -> fc_lock ; error = futex_user_store ( condvar , ~ CLOUDABI_CONDVAR_HAS_NO_WAITERS ) ; if ( error != 0 ) { futex_condvar_release ( fc ) ; return ( error ) ; } error = futex_lock_unlock ( fl , td , lock ) ; if ( error != 0 ) { futex_condvar_unmanage ( fc , condvar ) ; futex_condvar_release ( fc ) ; return ( error ) ; } ++ fc -> fc_waitcount ; error = futex_queue_sleep ( & fc -> fc_waiters , fc -> fc_lock , & fw , td , clock_id , timeout , precision ) ; if ( fw . fw_locked ) { KASSERT ( futex_queue_count ( & fw . fw_donated ) == 0 , ( " " ) ) ; } else if ( error == 0 || error == ETIMEDOUT ) { if ( error != 0 ) futex_condvar_unmanage ( fc , condvar ) ; error2 = futex_lock_wrlock ( fl , td , lock , CLOUDABI_CLOCK_MONOTONIC , UINT64_MAX , 0 , & fw . fw_donated ) ; if ( error2 != 0 ) error = error2 ; } else { KASSERT ( futex_queue_count ( & fw . fw_donated ) == 0 , ( " " ) ) ; futex_condvar_unmanage ( fc , condvar ) ; futex_lock_unmanage ( fl , lock ) ; } -- fc -> fc_waitcount ; futex_condvar_release ( fc ) ; return ( error ) ; }
Blocking calls: acquiring locks, waiting on condition variables.
Blocking calls : acquiring locks waiting on condition variables .
/* Lookup condition variable object. */ /*
	 * Set the condition variable to something other than
	 * CLOUDABI_CONDVAR_HAS_NO_WAITERS to make userspace threads
	 * call into the kernel to perform wakeups.
	 */ /* Drop the lock. */ /* Go to sleep. */ /* Waited and got the lock assigned to us. */ /*
		 * Got woken up without having the lock assigned to us.
		 * This can happen in two cases:
		 *
		 * 1. We observed a timeout on a condition variable.
		 * 2. We got signalled on a condition variable while the
		 *    associated lock is unlocked. We are the first
		 *    thread that gets woken up. This thread is
		 *    responsible for reacquiring the userspace lock.
		 */