xref: /netbsd-src/share/man/man9/condvar.9 (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
1.\"	$NetBSD: condvar.9,v 1.30 2020/08/27 14:14:00 fcambus Exp $
2.\"
3.\" Copyright (c) 2006, 2007, 2008, 2020 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 May 2, 2020
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.
268The mutex passed to the wait function
269.Po Fa mtx Pc
270must also be held when calling
271.Fn cv_signal .
272.Pp
273(Note that
274.Fn cv_signal
275is erroneously named in that it does not send a signal in the traditional
276sense to LWPs waiting on a CV.)
277.It Fn cv_broadcast "cv"
278.Pp
279Awaken all LWPs waiting on the specified condition variable.
280The mutex passed to the wait function
281.Po Fa mtx Pc
282must also be held when calling
283.Fn cv_broadcast .
284.It Fn cv_has_waiters "cv"
285.Pp
286Return
287.Dv true
288if one or more LWPs are waiting on the specified condition variable.
289.Pp
290.Fn cv_has_waiters
291cannot test reliably for interruptable waits.
292It should only be used to test for non-interruptable waits
293made using
294.Fn cv_wait .
295.Pp
296.Fn cv_has_waiters
297should only be used when making diagnostic assertions, and must
298be called while holding the interlocking mutex passed to
299.Fn cv_wait .
300.El
301.Sh EXAMPLES
302Consuming a resource:
303.Bd -literal
304	/*
305	 * Lock the resource.  Its mutex will also serve as the
306	 * interlock.
307	 */
308	mutex_enter(&res->mutex);
309
310	/*
311	 * Wait for the resource to become available.  Timeout after
312	 * five seconds.  If the resource is not available within the
313	 * allotted time, return an error.
314	 */
315	struct bintime timeout = { .sec = 5, .frac = 0 };
316	while (res->state == BUSY) {
317		error = cv_timedwaitbt(&res->condvar,
318		    &res->mutex, &timeout, DEFAULT_TIMEOUT_EPSILON);
319		if (error) {
320			KASSERT(error == EWOULDBLOCK);
321			mutex_exit(&res->mutex);
322			return ETIMEDOUT;
323		}
324	}
325
326	/*
327	 * It's now available to us.  Take ownership of the
328	 * resource, and consume it.
329	 */
330	res->state = BUSY;
331	mutex_exit(&res->mutex);
332	consume(res);
333.Ed
334.Pp
335Releasing a resource for the next consumer to use:
336.Bd -literal
337	mutex_enter(&res->mutex);
338	res->state = IDLE;
339	cv_signal(&res->condvar);
340	mutex_exit(&res->mutex);
341.Ed
342.Sh CODE REFERENCES
343The core of the CV implementation is in
344.Pa sys/kern/kern_condvar.c .
345.Pp
346The header file
347.Pa sys/sys/condvar.h
348describes the public interface.
349.Sh SEE ALSO
350.Xr sigaction 2 ,
351.Xr membar_ops 3 ,
352.Xr errno 9 ,
353.Xr mstohz 9 ,
354.Xr mutex 9 ,
355.Xr rwlock 9
356.Pp
357.Rs
358.%A Jim Mauro
359.%A Richard McDougall
360.%T Solaris Internals: Core Kernel Architecture
361.%I Prentice Hall
362.%D 2001
363.%O ISBN 0-13-022496-0
364.Re
365.Sh HISTORY
366The CV primitives first appeared in
367.Nx 5.0 .
368The
369.Fn cv_timedwaitbt
370and
371.Fn cv_timedwaitbt_sig
372primitives first appeared in
373.Nx 9.0 .
374