1condvar(9F) Kernel Functions for Drivers condvar(9F)
2
3
4
6 condvar, cv_init, cv_destroy, cv_wait, cv_signal, cv_broadcast,
7 cv_wait_sig, cv_timedwait, cv_timedwait_sig - condition variable rou‐
8 tines
9
11 #include <sys/ksynch.h>
12
13
14
15 void cv_init(kcondvar_t *cvp, char *name, kcv_type_t type, void *arg);
16
17
18 void cv_destroy(kcondvar_t *cvp);
19
20
21 void cv_wait(kcondvar_t *cvp, kmutex_t *mp);
22
23
24 void cv_signal(kcondvar_t *cvp);
25
26
27 void cv_broadcast(kcondvar_t *cvp);
28
29
30 int cv_wait_sig(kcondvar_t *cvp, kmutex_t *mp);
31
32
33 clock_t cv_timedwait(kcondvar_t *cvp, kmutex_t *mp, clock_t timeout);
34
35
36 clock_t cv_timedwait_sig(kcondvar_t *cvp, kmutex_t *mp, clock_t timeout);
37
38
40 Solaris DDI specific (Solaris DDI).
41
43 cvp A pointer to an abstract data type kcondvar_t.
44
45
46 mp A pointer to a mutual exclusion lock (kmutex_t), initialized
47 by mutex_init(9F) and held by the caller.
48
49
50 name Descriptive string. This is obsolete and should be NULL.
51 (Non-NULL strings are legal, but they're a waste of kernel
52 memory.)
53
54
55 type The constant CV_DRIVER.
56
57
58 arg A type-specific argument, drivers should pass arg as NULL.
59
60
61 timeout A time, in absolute ticks since boot, when cv_timedwait() or
62 cv_timedwait_sig() should return.
63
64
66 Condition variables are a standard form of thread synchronization. They
67 are designed to be used with mutual exclusion locks (mutexes). The
68 associated mutex is used to ensure that a condition can be checked
69 atomically and that the thread can block on the associated condition
70 variable without missing either a change to the condition or a signal
71 that the condition has changed. Condition variables must be initialized
72 by calling cv_init(), and must be deallocated by calling cv_destroy().
73
74
75 The usual use of condition variables is to check a condition (for exam‐
76 ple, device state, data structure reference count, etc.) while holding
77 a mutex which keeps other threads from changing the condition. If the
78 condition is such that the thread should block, cv_wait() is called
79 with a related condition variable and the mutex. At some later point in
80 time, another thread would acquire the mutex, set the condition such
81 that the previous thread can be unblocked, unblock the previous thread
82 with cv_signal() or cv_broadcast(), and then release the mutex.
83
84
85 cv_wait() suspends the calling thread and exits the mutex atomically so
86 that another thread which holds the mutex cannot signal on the condi‐
87 tion variable until the blocking thread is blocked. Before returning,
88 the mutex is reacquired.
89
90
91 cv_signal() signals the condition and wakes one blocked thread. All
92 blocked threads can be unblocked by calling cv_broadcast(). cv_signal()
93 and cv_broadcast() can be called by a thread even if it does not hold
94 the mutex passed into cv_wait(), though holding the mutex is necessary
95 to ensure predictable scheduling.
96
97
98 The function cv_wait_sig() is similar to cv_wait() but returns 0 if a
99 signal (for example, by kill(2)) is sent to the thread. In any case,
100 the mutex is reacquired before returning.
101
102
103 The function cv_timedwait() is similar to cv_wait(), except that it
104 returns −1 without the condition being signaled after the timeout time
105 has been reached.
106
107
108 The function cv_timedwait_sig() is similar to cv_timedwait() and
109 cv_wait_sig(), except that it returns −1 without the condition being
110 signaled after the timeout time has been reached, or 0 if a signal (for
111 example, by kill(2)) is sent to the thread.
112
113
114 For both cv_timedwait() and cv_timedwait_sig(), time is in absolute
115 clock ticks since the last system reboot. The current time may be found
116 by calling ddi_get_lbolt(9F).
117
119 0 For cv_wait_sig() and cv_timedwait_sig() indicates that the
120 condition was not necessarily signaled and the function
121 returned because a signal (as in kill(2)) was pending.
122
123
124 −1 For cv_timedwait() and cv_timedwait_sig() indicates that the
125 condition was not necessarily signaled and the function
126 returned because the timeout time was reached.
127
128
129 >0 For cv_wait_sig(), cv_timedwait() or cv_timedwait_sig() indi‐
130 cates that the condition was met and the function returned due
131 to a call to cv_signal() or cv_broadcast(), or due to a prema‐
132 ture wakeup (see NOTES).
133
134
136 These functions can be called from user, kernel or interrupt context.
137 In most cases, however, cv_wait(), cv_timedwait(), cv_wait_sig(), and
138 cv_timedwait_sig() should not be called from interrupt context, and
139 cannot be called from a high-level interrupt context.
140
141
142 If cv_wait(), cv_timedwait(), cv_wait_sig(), or cv_timedwait_sig() are
143 used from interrupt context, lower-priority interrupts will not be ser‐
144 viced during the wait. This means that if the thread that will eventu‐
145 ally perform the wakeup becomes blocked on anything that requires the
146 lower-priority interrupt, the system will hang.
147
148
149 For example, the thread that will perform the wakeup may need to first
150 allocate memory. This memory allocation may require waiting for paging
151 I/O to complete, which may require a lower-priority disk or network
152 interrupt to be serviced. In general, situations like this are hard to
153 predict, so it is advisable to avoid waiting on condition variables or
154 semaphores in an interrupt context.
155
157 Example 1 Waiting for a Flag Value in a Driver's Unit
158
159
160 Here the condition being waited for is a flag value in a driver's unit
161 structure. The condition variable is also in the unit structure, and
162 the flag word is protected by a mutex in the unit structure.
163
164
165 mutex_enter(&un->un_lock);
166 while (un->un_flag & UNIT_BUSY)
167 cv_wait(&un->un_cv, &un->un_lock);
168 un->un_flag |= UNIT_BUSY;
169 mutex_exit(&un->un_lock);
170
171
172 Example 2 Unblocking Threads Blocked by the Code in Example 1
173
174
175 At some later point in time, another thread would execute the following
176 to unblock any threads blocked by the above code.
177
178
179
180 mutex_enter(&un->un_lock);
181 un->un_flag &= ~UNIT_BUSY;
182 cv_broadcast(&un->un_cv);
183 mutex_exit(&un->un_lock);
184
185
187 It is possible for cv_wait(), cv_wait_sig(), cv_timedwait(), and
188 cv_timedwait_sig() to return prematurely, that is, not due to a call to
189 cv_signal() or cv_broadcast(). This occurs most commonly in the case of
190 cv_wait_sig() and cv_timedwait_sig() when the thread is stopped and
191 restarted by job control signals or by a debugger, but can happen in
192 other cases as well, even for cv_wait(). Code that calls these func‐
193 tions must always recheck the reason for blocking and call again if the
194 reason for blocking is still true.
195
196
197 If your driver needs to wait on behalf of processes that have real-time
198 constraints, use cv_timedwait() rather than delay(9F). The delay()
199 function calls timeout(9F), which can be subject to priority inver‐
200 sions.
201
202
203 Not all threads can receive signals from user level processes. In cases
204 where such reception is impossible (such as during execution of
205 close(9E) due to exit(2)), cv_wait_sig() behaves as cv_wait(), and
206 cv_timedwait_sig() behaves as cv_timedwait(). To avoid unkillable pro‐
207 cesses, users of these functions may need to protect against waiting
208 indefinitely for events that might not occur. The
209 ddi_can_receive_sig(9F) function is provided to detect when signal
210 reception is possible.
211
213 kill(2), ddi_can_receive_sig(9F), ddi_get_lbolt(9F), mutex(9F),
214 mutex_init(9F)
215
216
217 Writing Device Drivers
218
219
220
221SunOS 5.11 15 Dec 2003 condvar(9F)