CONDVAR(9)
π CONDVAR(9) β kernel condition variable π
ok so like. bestie. this is condvar, from the Kernel Developer's Manual. it's the whole condition-variable situation for the kernel, and honestly? it's giving "elegant synchronization primitive" and i'm obsessed. π
the crew you're meeting today: cv_init, cv_destroy, cv_wait, cv_wait_sig, cv_wait_unlock, cv_timedwait, cv_timedwait_sbt, cv_timedwait_sig, cv_timedwait_sig_sbt, cv_signal, cv_broadcast, cv_broadcastpri, and cv_wmesg. that's the whole squad. periodt.
β¨ SYNOPSIS β¨
first things first, you gotta invite them in:
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/condvar.h>
and here's the whole friend group, signature by signature, no cap:
void
cv_init(struct cv *cvp, const char *desc);
void
cv_destroy(struct cv *cvp);
void
cv_wait(struct cv *cvp, lock);
int
cv_wait_sig(struct cv *cvp, lock);
void
cv_wait_unlock(struct cv *cvp, lock);
int
cv_timedwait(struct cv *cvp, lock, int timo);
int
cv_timedwait_sbt(struct cv *cvp, lock, sbintime_t sbt, sbintime_t pr,
int flags);
int
cv_timedwait_sig(struct cv *cvp, lock, int timo);
int
cv_timedwait_sig_sbt(struct cv *cvp, lock, sbintime_t sbt,
sbintime_t pr, int flags);
void
cv_signal(struct cv *cvp);
void
cv_broadcast(struct cv *cvp);
void
cv_broadcastpri(struct cv *cvp, int pri);
const char *
cv_wmesg(struct cv *cvp);
πΈ DESCRIPTION πΈ
okay so here's the tea. condition variables team up with mutexes to wait for conditions to actually happen. iconic duo behavior. π
you make one with cv_init(), where cvp is a pointer to space for a struct cv, and desc is a pointer to a null-terminated character string describing the condition variable. like a lil name tag for your cv. so cute. π
you tear it down with cv_destroy(). rip bestie, you served well. π
threads wait on condition variables by calling cv_wait(), cv_wait_sig(), cv_wait_unlock(), cv_timedwait(), or cv_timedwait_sig().
threads unblock waiters by calling cv_signal() to unblock one waiter, or cv_broadcast() or cv_broadcastpri() to unblock all the waiters. the whole group chat, awake. π
and on top of waking everyone up, cv_broadcastpri() also makes sure all the waiters have a priority of at least pri, by raising the priority of any threads that don't. it's giving "everyone gets a glow-up whether they asked or not." β¨
cv_wmesg() returns the description string of cvp, exactly as set by that initial call to cv_init().
π the lock argument, a whole moment π
the lock argument is a pointer to either a mutex(9), rwlock(9), or sx(9) lock.
amutex(9)argument must be initialized withMTX_DEFand notMTX_SPIN. no exceptions, bestie, that's the law.
a thread must hold lock before calling cv_wait(), cv_wait_sig(), cv_wait_unlock(), cv_timedwait(), or cv_timedwait_sig().
when a thread waits on a condition, lock is atomically released before the thread is blocked, then reacquired before the function call returns. plus β and this is the part people forget β the thread will fully drop the Giant mutex (even if recursed) while it's suspended, and will reacquire the Giant mutex before the function returns.
the cv_wait_unlock() function does not reacquire the lock before returning. it said "i'm leaving and i'm not coming back." π¦
note that the Giant mutex may be specified as lock. However β and this is a big however β Giant may not be used as lock for the cv_wait_unlock() function. π
all waiters must pass the same lock in conjunction with cvp. consistency is key, queen. π
β° waking up & timing out β°
when cv_wait(), cv_wait_sig(), cv_wait_unlock(), cv_timedwait(), and cv_timedwait_sig() unblock, their calling threads are made runnable.
cv_timedwait() and cv_timedwait_sig() wait for at most timo / HZ seconds before being unblocked and returning EWOULDBLOCK; otherwise, they return 0.
cv_wait_sig() and cv_timedwait_sig() return prematurely with a value of EINTR or ERESTART if a signal is caught, or 0 if signaled via cv_signal() or cv_broadcast(). dramatic exits only. π
π§ the _sbt girlies π§
cv_timedwait_sbt() and cv_timedwait_sig_sbt() take the sbt argument instead of timo. it lets you specify a relative or absolute unblock time with higher resolution in the form of sbintime_t. highkey fancy. β¨
the parameter pr lets you specify the wanted absolute event precision.
the parameter flags lets you pass additional callout_reset_sbt() flags.
π«Ά RETURN VALUES π«Ά
if successful, cv_wait_sig(), cv_timedwait(), and cv_timedwait_sig() return 0. otherwise, a non-zero error code is returned.
cv_wmesg() returns the description string that was passed to cv_init().
π ERRORS π
cv_wait_sig() and cv_timedwait_sig() will fail if:
[EINTR]β a signal was caught and the system call should be interrupted.[ERESTART]β a signal was caught and the system call should be restarted.
cv_timedwait() and cv_timedwait_sig() will fail if:
[EWOULDBLOCK]β timeout expired. you waited, bestie, and it did not come through. π
π SEE ALSO π
locking(9), mtx_pool(9), mutex(9), rwlock(9), sema(9), sleep(9), sx(9), timeout(9)
go read those too, iykyk. π
and that's the whole page, bestie! this little love letter to kernel synchronization comes to you from Debian, dated February 19, 2013. slay, stay synchronized, and always release your locks. π β¨π
π¦ where this page comes from
- debian bookworm: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- debian trixie: freebsd-manpages 12.2-2 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu jammy: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu noble: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu questing: freebsd-manpages 12.2-2
- ubuntu resolute: freebsd-manpages 12.2-2build1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu stonking: freebsd-manpages 12.2-2build1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- Copyright (C) 2000 Jason Evans <jasone@FreeBSD.org>. All rights reserved
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms