CONDVAR(9)
π CONDVAR(9) π
okay so this is condvar(9) from the Kernel Developer's Manual β section 9, kernel-land only, bestie. it's the whole condition-variable family and honestly it's giving "the backbone of every blocking wait in the kernel." let's get into it π«Ά
β¨ NAME β¨
condvar, 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, cv_wmesg β literally the kernel condition variable and all its little friends π
πΈ SYNOPSIS πΈ
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/condvar.h>
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 the whole vibe: condition variables are used in conjunction with mutexes to wait for conditions to occur. that's the entire point. you got a lock, you got a condition, you wait on it. iconic teamwork fr fr π
Making one: you create condition variables 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 that describes the condition variable. give her a name, she deserves it π
Destroying one: you destroy condition variables with cv_destroy(). bye bestie π
Waiting: threads wait on condition variables by calling cv_wait(), cv_wait_sig(), cv_wait_unlock(), cv_timedwait(), or cv_timedwait_sig(). pick your fighter.
Waking: threads unblock waiters by calling cv_signal() to unblock one waiter, or cv_broadcast() or cv_broadcastpri() to unblock all waiters. and cv_broadcastpri() is the overachiever β in addition to waking waiters, it ensures that all of the waiters have a priority of at least pri by raising the priority of any threads that do not. main character energy honestly π
Interrogating one: cv_wmesg() returns the description string of cvp, as set by the initial call to cv_init().
π the lock argument, lowkey the most important part π
the lock argument is a pointer to either a mutex(9), rwlock(9), or sx(9) lock. a mutex(9) argument must be initialized with MTX_DEF and not MTX_SPIN. no cap, that's non-negotiable.
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. it's giving magic trick β¨
in addition, the thread will fully drop the Giant mutex (even if recursed) while it is suspended and will reacquire the Giant mutex before the function returns.
β οΈ the cv_wait_unlock() function does not reacquire the lock before returning. she leaves it unlocked. that's the whole bit. do not forget.
π note that theGiantmutex may be specified aslock. However,Giantmay not be used aslockfor thecv_wait_unlock()function. rules are rules.
all waiters must pass the same lock in conjunction with cvp. consistency is cute, chaos is not π
β° timing + return behaviour β°
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().
cv_timedwait_sbt() and cv_timedwait_sig_sbt() functions take sbt argument instead of timo. it allows to specify relative or absolute unblock time with higher resolution in form of sbintime_t. the parameter pr allows to specify wanted absolute event precision. the parameter flags allows to pass additional callout_reset_sbt() flags. fancy high-res timing, we stan π§
β 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. she waited, she gave up, she moved on π
π SEE ALSO π
callout(9), locking(9), mtx_pool(9), mutex(9), rwlock(9), sema(9), sleep(9), sx(9)
go read locking(9) next, it's the prerequisite lore iykyk π
and that's the whole page bestie πβ¨ππ¦πΈπ π«Ά β brought to you by Debian, dated February 19, 2013. yes that's old. yes she still slays. periodt π
π¦ where this page comes from
- freebsd 14.5: base 14.5
- freebsd 15.1: base 15.1
- Copyright (C) 2000 Jason Evans <jasone@FreeBSD.org>. All rights reserved
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms