1 /*-
2 * Copyright (c) 2000 Jake Burkholder <jake@freebsd.org>.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD: releng/5.2/sys/kern/kern_condvar.c 122352 2003-11-09 09:17:26Z tanimura $");
29
30 #include "opt_ktrace.h"
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/lock.h>
35 #include <sys/mutex.h>
36 #include <sys/proc.h>
37 #include <sys/kernel.h>
38 #include <sys/ktr.h>
39 #include <sys/condvar.h>
40 #include <sys/sched.h>
41 #include <sys/signalvar.h>
42 #include <sys/resourcevar.h>
43 #ifdef KTRACE
44 #include <sys/uio.h>
45 #include <sys/ktrace.h>
46 #endif
47
48 /*
49 * Common sanity checks for cv_wait* functions.
50 */
51 #define CV_ASSERT(cvp, mp, td) do { \
52 KASSERT((td) != NULL, ("%s: curthread NULL", __func__)); \
53 KASSERT(TD_IS_RUNNING(td), ("%s: not TDS_RUNNING", __func__)); \
54 KASSERT((cvp) != NULL, ("%s: cvp NULL", __func__)); \
55 KASSERT((mp) != NULL, ("%s: mp NULL", __func__)); \
56 mtx_assert((mp), MA_OWNED | MA_NOTRECURSED); \
57 } while (0)
58
59 #ifdef INVARIANTS
60 #define CV_WAIT_VALIDATE(cvp, mp) do { \
61 if (TAILQ_EMPTY(&(cvp)->cv_waitq)) { \
62 /* Only waiter. */ \
63 (cvp)->cv_mtx = (mp); \
64 } else { \
65 /* \
66 * Other waiter; assert that we're using the \
67 * same mutex. \
68 */ \
69 KASSERT((cvp)->cv_mtx == (mp), \
70 ("%s: Multiple mutexes", __func__)); \
71 } \
72 } while (0)
73
74 #define CV_SIGNAL_VALIDATE(cvp) do { \
75 if (!TAILQ_EMPTY(&(cvp)->cv_waitq)) { \
76 KASSERT(mtx_owned((cvp)->cv_mtx), \
77 ("%s: Mutex not owned", __func__)); \
78 } \
79 } while (0)
80
81 #else
82 #define CV_WAIT_VALIDATE(cvp, mp)
83 #define CV_SIGNAL_VALIDATE(cvp)
84 #endif
85
86 static void cv_timedwait_end(void *arg);
87
88 /*
89 * Initialize a condition variable. Must be called before use.
90 */
91 void
92 cv_init(struct cv *cvp, const char *desc)
93 {
94
95 TAILQ_INIT(&cvp->cv_waitq);
96 cvp->cv_mtx = NULL;
97 cvp->cv_description = desc;
98 }
99
100 /*
101 * Destroy a condition variable. The condition variable must be re-initialized
102 * in order to be re-used.
103 */
104 void
105 cv_destroy(struct cv *cvp)
106 {
107
108 KASSERT(cv_waitq_empty(cvp), ("%s: cv_waitq non-empty", __func__));
109 }
110
111 /*
112 * Common code for cv_wait* functions. All require sched_lock.
113 */
114
115 /*
116 * Switch context.
117 */
118 static __inline void
119 cv_switch(struct thread *td)
120 {
121 TD_SET_SLEEPING(td);
122 td->td_proc->p_stats->p_ru.ru_nvcsw++;
123 mi_switch();
124 CTR3(KTR_PROC, "cv_switch: resume thread %p (pid %d, %s)", td,
125 td->td_proc->p_pid, td->td_proc->p_comm);
126 }
127
128 /*
129 * Switch context, catching signals.
130 */
131 static __inline int
132 cv_switch_catch(struct thread *td)
133 {
134 struct proc *p;
135 int sig;
136
137 /*
138 * We put ourselves on the sleep queue and start our timeout before
139 * calling cursig, as we could stop there, and a wakeup or a SIGCONT (or
140 * both) could occur while we were stopped. A SIGCONT would cause us to
141 * be marked as TDS_SLP without resuming us, thus we must be ready for
142 * sleep when cursig is called. If the wakeup happens while we're
143 * stopped, td->td_wchan will be 0 upon return from cursig,
144 * and TD_ON_SLEEPQ() will return false.
145 */
146 td->td_flags |= TDF_SINTR;
147 mtx_unlock_spin(&sched_lock);
148 p = td->td_proc;
149 PROC_LOCK(p);
150 mtx_lock(&p->p_sigacts->ps_mtx);
151 sig = cursig(td);
152 mtx_unlock(&p->p_sigacts->ps_mtx);
153 if (thread_suspend_check(1))
154 sig = SIGSTOP;
155 mtx_lock_spin(&sched_lock);
156 PROC_UNLOCK(p);
157 if (sig != 0) {
158 if (TD_ON_SLEEPQ(td))
159 cv_waitq_remove(td);
160 TD_SET_RUNNING(td);
161 } else if (TD_ON_SLEEPQ(td)) {
162 cv_switch(td);
163 }
164 td->td_flags &= ~TDF_SINTR;
165
166 return sig;
167 }
168
169 /*
170 * Add a thread to the wait queue of a condition variable.
171 */
172 static __inline void
173 cv_waitq_add(struct cv *cvp, struct thread *td)
174 {
175
176 td->td_flags |= TDF_CVWAITQ;
177 TD_SET_ON_SLEEPQ(td);
178 td->td_wchan = cvp;
179 td->td_wmesg = cvp->cv_description;
180 CTR3(KTR_PROC, "cv_waitq_add: thread %p (pid %d, %s)", td,
181 td->td_proc->p_pid, td->td_proc->p_comm);
182 TAILQ_INSERT_TAIL(&cvp->cv_waitq, td, td_slpq);
183 sched_sleep(td, td->td_priority);
184 }
185
186 /*
187 * Wait on a condition variable. The current thread is placed on the condition
188 * variable's wait queue and suspended. A cv_signal or cv_broadcast on the same
189 * condition variable will resume the thread. The mutex is released before
190 * sleeping and will be held on return. It is recommended that the mutex be
191 * held when cv_signal or cv_broadcast are called.
192 */
193 void
194 cv_wait(struct cv *cvp, struct mtx *mp)
195 {
196 struct thread *td;
197 WITNESS_SAVE_DECL(mp);
198
199 td = curthread;
200 #ifdef KTRACE
201 if (KTRPOINT(td, KTR_CSW))
202 ktrcsw(1, 0);
203 #endif
204 CV_ASSERT(cvp, mp, td);
205 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, &mp->mtx_object,
206 "Waiting on \"%s\"", cvp->cv_description);
207 WITNESS_SAVE(&mp->mtx_object, mp);
208
209 if (cold ) {
210 /*
211 * During autoconfiguration, just give interrupts
212 * a chance, then just return. Don't run any other
213 * thread or panic below, in case this is the idle
214 * process and already asleep.
215 */
216 return;
217 }
218
219 mtx_lock_spin(&sched_lock);
220
221 CV_WAIT_VALIDATE(cvp, mp);
222
223 DROP_GIANT();
224 mtx_unlock(mp);
225
226 cv_waitq_add(cvp, td);
227 cv_switch(td);
228
229 mtx_unlock_spin(&sched_lock);
230 #ifdef KTRACE
231 if (KTRPOINT(td, KTR_CSW))
232 ktrcsw(0, 0);
233 #endif
234 PICKUP_GIANT();
235 mtx_lock(mp);
236 WITNESS_RESTORE(&mp->mtx_object, mp);
237 }
238
239 /*
240 * Wait on a condition variable, allowing interruption by signals. Return 0 if
241 * the thread was resumed with cv_signal or cv_broadcast, EINTR or ERESTART if
242 * a signal was caught. If ERESTART is returned the system call should be
243 * restarted if possible.
244 */
245 int
246 cv_wait_sig(struct cv *cvp, struct mtx *mp)
247 {
248 struct thread *td;
249 struct proc *p;
250 int rval;
251 int sig;
252 WITNESS_SAVE_DECL(mp);
253
254 td = curthread;
255 p = td->td_proc;
256 rval = 0;
257 #ifdef KTRACE
258 if (KTRPOINT(td, KTR_CSW))
259 ktrcsw(1, 0);
260 #endif
261 CV_ASSERT(cvp, mp, td);
262 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, &mp->mtx_object,
263 "Waiting on \"%s\"", cvp->cv_description);
264 WITNESS_SAVE(&mp->mtx_object, mp);
265
266 if (cold || panicstr) {
267 /*
268 * After a panic, or during autoconfiguration, just give
269 * interrupts a chance, then just return; don't run any other
270 * procs or panic below, in case this is the idle process and
271 * already asleep.
272 */
273 return 0;
274 }
275
276 mtx_lock_spin(&sched_lock);
277
278 CV_WAIT_VALIDATE(cvp, mp);
279
280 DROP_GIANT();
281 mtx_unlock(mp);
282
283 cv_waitq_add(cvp, td);
284 sig = cv_switch_catch(td);
285
286 mtx_unlock_spin(&sched_lock);
287
288 PROC_LOCK(p);
289 mtx_lock(&p->p_sigacts->ps_mtx);
290 if (sig == 0) {
291 sig = cursig(td); /* XXXKSE */
292 if (sig == 0 && td->td_flags & TDF_INTERRUPT)
293 rval = td->td_intrval;
294 }
295 if (sig != 0) {
296 if (SIGISMEMBER(p->p_sigacts->ps_sigintr, sig))
297 rval = EINTR;
298 else
299 rval = ERESTART;
300 }
301 mtx_unlock(&p->p_sigacts->ps_mtx);
302 if (p->p_flag & P_WEXIT)
303 rval = EINTR;
304 PROC_UNLOCK(p);
305
306 #ifdef KTRACE
307 if (KTRPOINT(td, KTR_CSW))
308 ktrcsw(0, 0);
309 #endif
310 PICKUP_GIANT();
311 mtx_lock(mp);
312 WITNESS_RESTORE(&mp->mtx_object, mp);
313
314 return (rval);
315 }
316
317 /*
318 * Wait on a condition variable for at most timo/hz seconds. Returns 0 if the
319 * process was resumed by cv_signal or cv_broadcast, EWOULDBLOCK if the timeout
320 * expires.
321 */
322 int
323 cv_timedwait(struct cv *cvp, struct mtx *mp, int timo)
324 {
325 struct thread *td;
326 int rval;
327 WITNESS_SAVE_DECL(mp);
328
329 td = curthread;
330 rval = 0;
331 #ifdef KTRACE
332 if (KTRPOINT(td, KTR_CSW))
333 ktrcsw(1, 0);
334 #endif
335 CV_ASSERT(cvp, mp, td);
336 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, &mp->mtx_object,
337 "Waiting on \"%s\"", cvp->cv_description);
338 WITNESS_SAVE(&mp->mtx_object, mp);
339
340 if (cold || panicstr) {
341 /*
342 * After a panic, or during autoconfiguration, just give
343 * interrupts a chance, then just return; don't run any other
344 * thread or panic below, in case this is the idle process and
345 * already asleep.
346 */
347 return 0;
348 }
349
350 mtx_lock_spin(&sched_lock);
351
352 CV_WAIT_VALIDATE(cvp, mp);
353
354 DROP_GIANT();
355 mtx_unlock(mp);
356
357 cv_waitq_add(cvp, td);
358 callout_reset(&td->td_slpcallout, timo, cv_timedwait_end, td);
359 cv_switch(td);
360
361 if (td->td_flags & TDF_TIMEOUT) {
362 td->td_flags &= ~TDF_TIMEOUT;
363 rval = EWOULDBLOCK;
364 } else if (td->td_flags & TDF_TIMOFAIL)
365 td->td_flags &= ~TDF_TIMOFAIL;
366 else if (callout_stop(&td->td_slpcallout) == 0) {
367 /*
368 * Work around race with cv_timedwait_end similar to that
369 * between msleep and endtsleep.
370 * Go back to sleep.
371 */
372 TD_SET_SLEEPING(td);
373 td->td_proc->p_stats->p_ru.ru_nivcsw++;
374 mi_switch();
375 td->td_flags &= ~TDF_TIMOFAIL;
376 }
377
378 mtx_unlock_spin(&sched_lock);
379 #ifdef KTRACE
380 if (KTRPOINT(td, KTR_CSW))
381 ktrcsw(0, 0);
382 #endif
383 PICKUP_GIANT();
384 mtx_lock(mp);
385 WITNESS_RESTORE(&mp->mtx_object, mp);
386
387 return (rval);
388 }
389
390 /*
391 * Wait on a condition variable for at most timo/hz seconds, allowing
392 * interruption by signals. Returns 0 if the thread was resumed by cv_signal
393 * or cv_broadcast, EWOULDBLOCK if the timeout expires, and EINTR or ERESTART if
394 * a signal was caught.
395 */
396 int
397 cv_timedwait_sig(struct cv *cvp, struct mtx *mp, int timo)
398 {
399 struct thread *td;
400 struct proc *p;
401 int rval;
402 int sig;
403 WITNESS_SAVE_DECL(mp);
404
405 td = curthread;
406 p = td->td_proc;
407 rval = 0;
408 #ifdef KTRACE
409 if (KTRPOINT(td, KTR_CSW))
410 ktrcsw(1, 0);
411 #endif
412 CV_ASSERT(cvp, mp, td);
413 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, &mp->mtx_object,
414 "Waiting on \"%s\"", cvp->cv_description);
415 WITNESS_SAVE(&mp->mtx_object, mp);
416
417 if (cold || panicstr) {
418 /*
419 * After a panic, or during autoconfiguration, just give
420 * interrupts a chance, then just return; don't run any other
421 * thread or panic below, in case this is the idle process and
422 * already asleep.
423 */
424 return 0;
425 }
426
427 mtx_lock_spin(&sched_lock);
428
429 CV_WAIT_VALIDATE(cvp, mp);
430
431 DROP_GIANT();
432 mtx_unlock(mp);
433
434 cv_waitq_add(cvp, td);
435 callout_reset(&td->td_slpcallout, timo, cv_timedwait_end, td);
436 sig = cv_switch_catch(td);
437
438 if (td->td_flags & TDF_TIMEOUT) {
439 td->td_flags &= ~TDF_TIMEOUT;
440 rval = EWOULDBLOCK;
441 } else if (td->td_flags & TDF_TIMOFAIL)
442 td->td_flags &= ~TDF_TIMOFAIL;
443 else if (callout_stop(&td->td_slpcallout) == 0) {
444 /*
445 * Work around race with cv_timedwait_end similar to that
446 * between msleep and endtsleep.
447 * Go back to sleep.
448 */
449 TD_SET_SLEEPING(td);
450 td->td_proc->p_stats->p_ru.ru_nivcsw++;
451 mi_switch();
452 td->td_flags &= ~TDF_TIMOFAIL;
453 }
454 mtx_unlock_spin(&sched_lock);
455
456 PROC_LOCK(p);
457 mtx_lock(&p->p_sigacts->ps_mtx);
458 if (sig == 0) {
459 sig = cursig(td);
460 if (sig == 0 && td->td_flags & TDF_INTERRUPT)
461 rval = td->td_intrval;
462 }
463 if (sig != 0) {
464 if (SIGISMEMBER(p->p_sigacts->ps_sigintr, sig))
465 rval = EINTR;
466 else
467 rval = ERESTART;
468 }
469 mtx_unlock(&p->p_sigacts->ps_mtx);
470 if (p->p_flag & P_WEXIT)
471 rval = EINTR;
472 PROC_UNLOCK(p);
473
474 #ifdef KTRACE
475 if (KTRPOINT(td, KTR_CSW))
476 ktrcsw(0, 0);
477 #endif
478 PICKUP_GIANT();
479 mtx_lock(mp);
480 WITNESS_RESTORE(&mp->mtx_object, mp);
481
482 return (rval);
483 }
484
485 /*
486 * Common code for signal and broadcast. Assumes waitq is not empty. Must be
487 * called with sched_lock held.
488 */
489 static __inline void
490 cv_wakeup(struct cv *cvp)
491 {
492 struct thread *td;
493
494 mtx_assert(&sched_lock, MA_OWNED);
495 td = TAILQ_FIRST(&cvp->cv_waitq);
496 KASSERT(td->td_wchan == cvp, ("%s: bogus wchan", __func__));
497 KASSERT(td->td_flags & TDF_CVWAITQ, ("%s: not on waitq", __func__));
498 cv_waitq_remove(td);
499 TD_CLR_SLEEPING(td);
500 setrunnable(td);
501 }
502
503 /*
504 * Signal a condition variable, wakes up one waiting thread. Will also wakeup
505 * the swapper if the process is not in memory, so that it can bring the
506 * sleeping process in. Note that this may also result in additional threads
507 * being made runnable. Should be called with the same mutex as was passed to
508 * cv_wait held.
509 */
510 void
511 cv_signal(struct cv *cvp)
512 {
513
514 KASSERT(cvp != NULL, ("%s: cvp NULL", __func__));
515 mtx_lock_spin(&sched_lock);
516 if (!TAILQ_EMPTY(&cvp->cv_waitq)) {
517 CV_SIGNAL_VALIDATE(cvp);
518 cv_wakeup(cvp);
519 }
520 mtx_unlock_spin(&sched_lock);
521 }
522
523 /*
524 * Broadcast a signal to a condition variable. Wakes up all waiting threads.
525 * Should be called with the same mutex as was passed to cv_wait held.
526 */
527 void
528 cv_broadcastpri(struct cv *cvp, int pri)
529 {
530 struct thread *td;
531
532 KASSERT(cvp != NULL, ("%s: cvp NULL", __func__));
533 mtx_lock_spin(&sched_lock);
534 CV_SIGNAL_VALIDATE(cvp);
535 while (!TAILQ_EMPTY(&cvp->cv_waitq)) {
536 if (pri >= PRI_MIN && pri <= PRI_MAX) {
537 td = TAILQ_FIRST(&cvp->cv_waitq);
538 if (td->td_priority > pri)
539 td->td_priority = pri;
540 }
541 cv_wakeup(cvp);
542 }
543 mtx_unlock_spin(&sched_lock);
544 }
545
546 /*
547 * Remove a thread from the wait queue of its condition variable. This may be
548 * called externally.
549 */
550 void
551 cv_waitq_remove(struct thread *td)
552 {
553 struct cv *cvp;
554
555 mtx_assert(&sched_lock, MA_OWNED);
556 if ((cvp = td->td_wchan) != NULL && td->td_flags & TDF_CVWAITQ) {
557 TAILQ_REMOVE(&cvp->cv_waitq, td, td_slpq);
558 td->td_flags &= ~TDF_CVWAITQ;
559 td->td_wmesg = NULL;
560 TD_CLR_ON_SLEEPQ(td);
561 }
562 }
563
564 /*
565 * Timeout function for cv_timedwait. Put the thread on the runqueue and set
566 * its timeout flag.
567 */
568 static void
569 cv_timedwait_end(void *arg)
570 {
571 struct thread *td;
572
573 td = arg;
574 CTR3(KTR_PROC, "cv_timedwait_end: thread %p (pid %d, %s)",
575 td, td->td_proc->p_pid, td->td_proc->p_comm);
576 mtx_lock_spin(&sched_lock);
577 if (TD_ON_SLEEPQ(td)) {
578 cv_waitq_remove(td);
579 td->td_flags |= TDF_TIMEOUT;
580 } else {
581 td->td_flags |= TDF_TIMOFAIL;
582 }
583 TD_CLR_SLEEPING(td);
584 setrunnable(td);
585 mtx_unlock_spin(&sched_lock);
586 }
587
588 /*
589 * For now only abort interruptable waits.
590 * The others will have to either complete on their own or have a timeout.
591 */
592 void
593 cv_abort(struct thread *td)
594 {
595
596 CTR3(KTR_PROC, "cv_abort: thread %p (pid %d, %s)", td,
597 td->td_proc->p_pid, td->td_proc->p_comm);
598 mtx_lock_spin(&sched_lock);
599 if ((td->td_flags & (TDF_SINTR|TDF_TIMEOUT)) == TDF_SINTR) {
600 if (TD_ON_SLEEPQ(td)) {
601 cv_waitq_remove(td);
602 }
603 TD_CLR_SLEEPING(td);
604 setrunnable(td);
605 }
606 mtx_unlock_spin(&sched_lock);
607 }
608
Cache object: c248f52fb58bb9b5c7121846ad3c336b
|