xref: /netbsd-src/share/man/man9/condvar.9 (revision 587ba4d7aa303951551a36daf637a431a25e8b8f)
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