FreeBSD/sys/compat/cloudabi/cloudabi_futex.c
/*
 * Non-blocking calls: releasing locks, signalling condition variables.
 */
Non-blocking calls: releasing locks, signalling condition variables.
Non - blocking calls : releasing locks signalling condition variables .
int
cloudabi_sys_condvar_signal(struct thread *td,
    struct cloudabi_sys_condvar_signal_args *uap)
{
	struct futex_condvar *fc;
	struct futex_lock *fl;
	cloudabi_nthreads_t nwaiters;
	int error;
	nwaiters = uap->nwaiters;
	if (nwaiters == 0) {
		return (0);
	}
	error = futex_condvar_lookup(td, uap->condvar, uap->scope, &fc);
	if (error != 0) {
		return (error == ENOENT ? 0 : error);
	}
	fl = fc->fc_lock;
	if (fl->fl_owner == LOCK_UNMANAGED) {
		futex_queue_wake_up_donate(&fc->fc_waiters, nwaiters - 1);
	} else {
		futex_queue_requeue(&fc->fc_waiters, &fl->fl_writers, nwaiters);
	}
	error = futex_condvar_unmanage(fc, uap->condvar);
	futex_condvar_release(fc);
	return (error);
}
int cloudabi_sys_condvar_signal ( struct thread * td , struct cloudabi_sys_condvar_signal_args * uap ) { struct futex_condvar * fc ; struct futex_lock * fl ; cloudabi_nthreads_t nwaiters ; int error ; nwaiters = uap -> nwaiters ; if ( nwaiters == 0 ) { return ( 0 ) ; } error = futex_condvar_lookup ( td , uap -> condvar , uap -> scope , & fc ) ; if ( error != 0 ) { return ( error == ENOENT ? 0 : error ) ; } fl = fc -> fc_lock ; if ( fl -> fl_owner == LOCK_UNMANAGED ) { futex_queue_wake_up_donate ( & fc -> fc_waiters , nwaiters - 1 ) ; } else { futex_queue_requeue ( & fc -> fc_waiters , & fl -> fl_writers , nwaiters ) ; } error = futex_condvar_unmanage ( fc , uap -> condvar ) ; futex_condvar_release ( fc ) ; return ( error ) ; }
Non-blocking calls: releasing locks, signalling condition variables.
Non - blocking calls : releasing locks signalling condition variables .
/* No threads to wake up. */ /* Look up futex object. */ /* Race condition: condition variable with no waiters. */ /*
		 * The lock is currently not managed by the kernel,
		 * meaning we must attempt to acquire the userspace lock
		 * first. We cannot requeue threads to an unmanaged lock,
		 * as these threads will then never be scheduled.
		 *
		 * Unfortunately, the memory address of the lock is
		 * unknown from this context, meaning that we cannot
		 * acquire the lock on behalf of the first thread to be
		 * scheduled. The lock may even not be mapped within the
		 * address space of the current thread.
		 *
		 * To solve this, wake up a single waiter that will
		 * attempt to acquire the lock. Donate all of the other
		 * waiters that need to be woken up to this waiter, so
		 * it can requeue them after acquiring the lock.
		 */ /*
		 * Lock is already managed by the kernel. This makes it
		 * easy, as we can requeue the threads from the
		 * condition variable directly to the associated lock.
		 */ /* Clear userspace condition variable if all waiters are gone. */