1.\" $NetBSD: condvar.9,v 1.31 2023/09/07 20:01:43 ad Exp $ 2.\" 3.\" Copyright (c) 2006, 2007, 2008, 2020, 2023 The NetBSD Foundation, Inc. 4.\" All rights reserved. 5.\" 6.\" This code is derived from software contributed to The NetBSD Foundation 7.\" by Andrew Doran. 8.\" 9.\" Redistribution and use in source and binary forms, with or without 10.\" modification, are permitted provided that the following conditions 11.\" are met: 12.\" 1. Redistributions of source code must retain the above copyright 13.\" notice, this list of conditions and the following disclaimer. 14.\" 2. Redistributions in binary form must reproduce the above copyright 15.\" notice, this list of conditions and the following disclaimer in the 16.\" documentation and/or other materials provided with the distribution. 17.\" 18.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28.\" POSSIBILITY OF SUCH DAMAGE. 29.\" 30.Dd September 7, 2023 31.Dt CONDVAR 9 32.Os 33.Sh NAME 34.Nm cv , 35.Nm condvar , 36.Nm cv_init , 37.Nm cv_destroy , 38.Nm cv_wait , 39.Nm cv_wait_sig , 40.Nm cv_timedwait , 41.Nm cv_timedwait_sig , 42.Nm cv_timedwaitbt , 43.Nm cv_timedwaitbt_sig , 44.Nm cv_signal , 45.Nm cv_broadcast , 46.Nm cv_has_waiters 47.Nd condition variables 48.Sh SYNOPSIS 49.In sys/condvar.h 50.Ft void 51.Fn cv_init "kcondvar_t *cv" "const char *wmesg" 52.Ft void 53.Fn cv_destroy "kcondvar_t *cv" 54.Ft void 55.Fn cv_wait "kcondvar_t *cv" "kmutex_t *mtx" 56.Ft int 57.Fn cv_wait_sig "kcondvar_t *cv" "kmutex_t *mtx" 58.Ft int 59.Fn cv_timedwait "kcondvar_t *cv" "kmutex_t *mtx" "int ticks" 60.Ft int 61.Fn cv_timedwait_sig "kcondvar_t *cv" "kmutex_t *mtx" "int ticks" 62.Ft int 63.Fn cv_timedwaitbt "kcondvar_t *cv" "kmutex_t *mtx" "struct bintime *bt" \ 64"const struct bintime *epsilon" 65.Ft int 66.Fn cv_timedwaitbt_sig "kcondvar_t *cv" "kmutex_t *mtx" "struct bintime *bt" \ 67"const struct bintime *epsilon" 68.Ft void 69.Fn cv_signal "kcondvar_t *cv" 70.Ft void 71.Fn cv_broadcast "kcondvar_t *cv" 72.Ft bool 73.Fn cv_has_waiters "kcondvar_t *cv" 74.Pp 75.Cd "options DIAGNOSTIC" 76.Cd "options LOCKDEBUG" 77.Sh DESCRIPTION 78Condition variables (CVs) are used in the kernel to synchronize access 79to resources that are limited (for example, memory) and to wait for 80pending I/O operations to complete. 81.Pp 82The 83.Vt kcondvar_t 84type provides storage for the CV object. 85This should be treated as an opaque object and not examined directly by 86consumers. 87.Sh OPTIONS 88.Bl -tag -width abcd 89.It Cd "options DIAGNOSTIC" 90.Pp 91Kernels compiled with the 92.Dv DIAGNOSTIC 93option perform basic sanity checks on CV operations. 94.It Cd "options LOCKDEBUG" 95.Pp 96Kernels compiled with the 97.Dv LOCKDEBUG 98option perform potentially CPU intensive sanity checks 99on CV operations. 100.El 101.Sh FUNCTIONS 102.Bl -tag -width abcd 103.It Fn cv_init "cv" "wmesg" 104.Pp 105Initialize a CV for use. 106No other operations can be performed on the CV until it has been initialized. 107.Pp 108The 109.Fa wmesg 110argument specifies a string of no more than 8 characters that describes 111the resource or condition associated with the CV. 112The kernel does not use this argument directly but makes it available for 113utilities such as 114.Xr ps 1 115to display. 116.It Fn cv_destroy "cv" 117.Pp 118Release resources used by a CV. 119If there could be waiters, they should be awoken first with 120.Fn cv_broadcast . 121The CV must not be used afterwards. 122.It Fn cv_wait "cv" "mtx" 123.Pp 124Cause the current LWP to wait non-interruptably for access to a resource, 125or for an I/O operation to complete. 126The LWP will resume execution when awoken by another thread using 127.Fn cv_signal 128or 129.Fn cv_broadcast . 130.Pp 131.Fa mtx 132specifies a kernel mutex to be used as an interlock, and must be held by the 133calling LWP on entry to 134.Fn cv_wait . 135It will be released once the LWP has prepared to sleep, and will be reacquired 136before 137.Fn cv_wait 138returns. 139.Pp 140A small window exists between testing for availability of a resource and 141waiting for the resource with 142.Fn cv_wait , 143in which the resource may become available again. 144The interlock is used to guarantee that the resource will not be signalled 145as available until the calling LWP has begun to wait for it. 146.Pp 147Non-interruptable waits have the potential to deadlock the system, and so must 148be kept short (typically, under one second). 149.Pp 150.Fn cv_wait 151is typically used within a loop or restartable code sequence, because it 152may awaken spuriously. 153The calling LWP should re-check the condition that caused the wait. 154If necessary, the calling LWP may call 155.Fn cv_wait 156again to continue waiting. 157.It Fn cv_wait_sig "cv" "mtx" 158.Pp 159As per 160.Fn cv_wait , 161but causes the current LWP to wait interruptably. 162If the LWP receives a signal, or is interrupted by another condition such 163as its containing process exiting, the wait is ended early and an error 164code returned. 165.Pp 166If 167.Fn cv_wait_sig 168returns as a result of a signal, the return value is 169.Er ERESTART 170if the signal 171has the 172.Dv SA_RESTART 173property. 174If awoken normally, the value is zero, and 175.Er EINTR 176under all other conditions. 177.It Fn cv_timedwait "cv" "mtx" "ticks" 178.Pp 179As per 180.Fn cv_wait , 181but will return early if a timeout specified by the 182.Fa ticks 183argument expires. 184.Pp 185.Fa ticks 186is an architecture and system dependent value related to the number of 187clock interrupts per second. 188See 189.Xr hz 9 190for details. 191The 192.Xr mstohz 9 193macro can be used to convert a timeout expressed in milliseconds to 194one suitable for 195.Fn cv_timedwait . 196If the 197.Fa ticks 198argument is zero, 199.Fn cv_timedwait 200behaves exactly like 201.Fn cv_wait . 202.Pp 203If the timeout expires before the LWP is awoken, the return value is 204.Er EWOULDBLOCK . 205If awoken normally, the return value is zero. 206.It Fn cv_timedwait_sig "cv" "mtx" "ticks" 207.Pp 208As per 209.Fn cv_wait_sig , 210but also accepts a timeout value and will return 211.Er EWOULDBLOCK 212if the timeout expires. 213.It Fn cv_timedwaitbt "cv" "mtx" "bt" "epsilon" 214.It Fn cv_timedwaitbt_sig "cv" "mtx" "bt" "epsilon" 215.Pp 216As per 217.Fn cv_wait 218and 219.Fn cv_wait_sig , 220but will return early if the duration 221.Fa bt 222has elapsed, immediately if 223.Fa bt 224is zero. 225On return, 226.Fn cv_timedwaitbt 227and 228.Fn cv_timedwaitbt_sig 229subtract the time elapsed from 230.Fa bt 231in place, or set it to zero if there is no time remaining. 232.Pp 233Note that 234.Fn cv_timedwaitbt 235and 236.Fn cv_timedwaitbt_sig 237may return zero indicating success, rather than 238.Er EWOULDBLOCK , 239even if they set the timeout to zero; this means that the caller must 240re-check the condition in order to avoid potentially losing a 241.Fn cv_signal , 242but the 243.Em next 244wait will time out immediately. 245.Pp 246The hint 247.Fa epsilon , 248which can be 249.Dv DEFAULT_TIMEOUT_EPSILON 250if in doubt, requests that the wakeup not be delayed more than 251.Fa bt Li "+" Fa epsilon , 252so that the system can coalesce multiple wakeups within their 253respective epsilons into a single high-resolution clock interrupt or 254choose to use cheaper low-resolution clock interrupts instead. 255.Pp 256However, the system is still limited by its best clock interrupt 257resolution and by scheduling competition, which may delay the wakeup by 258more than 259.Fa bt Li "+" Fa epsilon . 260.It Fn cv_signal "cv" 261.Pp 262Awaken one LWP waiting on the specified condition variable. 263Where there are waiters sleeping non-interruptaby, more than one 264LWP may be awoken. 265This can be used to avoid a "thundering herd" problem, where a large 266number of LWPs are awoken following an event, but only one LWP can 267process the event. 268.Pp 269The mutex passed to the wait function 270.Po Fa mtx Pc 271should be held or have been released immediately before 272.Fn cv_signal 273is called. 274.Pp 275(Note that 276.Fn cv_signal 277is erroneously named in that it does not send a signal in the traditional 278sense to LWPs waiting on a CV.) 279.It Fn cv_broadcast "cv" 280.Pp 281Awaken all LWPs waiting on the specified condition variable. 282.Pp 283As with 284.Fn cv_signal , 285the mutex passed to the wait function 286.Po Fa mtx Pc 287should be held or have been released immediately before 288.Fn cv_broadcast 289is called. 290.It Fn cv_has_waiters "cv" 291.Pp 292Return 293.Dv true 294if one or more LWPs are waiting on the specified condition variable. 295.Pp 296.Fn cv_has_waiters 297cannot test reliably for interruptable waits. 298It should only be used to test for non-interruptable waits 299made using 300.Fn cv_wait . 301.Pp 302.Fn cv_has_waiters 303should only be used when making diagnostic assertions, and must 304be called while holding the interlocking mutex passed to 305.Fn cv_wait . 306.El 307.Sh EXAMPLES 308Consuming a resource: 309.Bd -literal 310 /* 311 * Lock the resource. Its mutex will also serve as the 312 * interlock. 313 */ 314 mutex_enter(&res->mutex); 315 316 /* 317 * Wait for the resource to become available. Timeout after 318 * five seconds. If the resource is not available within the 319 * allotted time, return an error. 320 */ 321 struct bintime timeout = { .sec = 5, .frac = 0 }; 322 while (res->state == BUSY) { 323 error = cv_timedwaitbt(&res->condvar, 324 &res->mutex, &timeout, DEFAULT_TIMEOUT_EPSILON); 325 if (error) { 326 KASSERT(error == EWOULDBLOCK); 327 mutex_exit(&res->mutex); 328 return ETIMEDOUT; 329 } 330 } 331 332 /* 333 * It's now available to us. Take ownership of the 334 * resource, and consume it. 335 */ 336 res->state = BUSY; 337 mutex_exit(&res->mutex); 338 consume(res); 339.Ed 340.Pp 341Releasing a resource for the next consumer to use: 342.Bd -literal 343 mutex_enter(&res->mutex); 344 res->state = IDLE; 345 cv_signal(&res->condvar); 346 mutex_exit(&res->mutex); 347.Ed 348.Sh CODE REFERENCES 349The core of the CV implementation is in 350.Pa sys/kern/kern_condvar.c . 351.Pp 352The header file 353.Pa sys/sys/condvar.h 354describes the public interface. 355.Sh SEE ALSO 356.Xr sigaction 2 , 357.Xr membar_ops 3 , 358.Xr errno 9 , 359.Xr mstohz 9 , 360.Xr mutex 9 , 361.Xr rwlock 9 362.Pp 363.Rs 364.%A Jim Mauro 365.%A Richard McDougall 366.%T Solaris Internals: Core Kernel Architecture 367.%I Prentice Hall 368.%D 2001 369.%O ISBN 0-13-022496-0 370.Re 371.Sh HISTORY 372The CV primitives first appeared in 373.Nx 5.0 . 374The 375.Fn cv_timedwaitbt 376and 377.Fn cv_timedwaitbt_sig 378primitives first appeared in 379.Nx 9.0 . 380