sys/vfs/msdosfs: Sync with FreeBSD (non functional diffs)
[dragonfly.git] / sys / kern / kern_condvar.c
1 #include <sys/condvar.h>
2 #include <sys/spinlock2.h>
3 #include <sys/systm.h>
4 #include <sys/lock.h>
5
6 void
7 cv_init(struct cv *c, const char *desc)
8 {
9         c->cv_desc = desc;
10         c->cv_waiters = 0;
11         spin_init(&c->cv_lock, "cvinit");
12 }
13
14 void
15 cv_destroy(struct cv *c)
16 {
17         spin_uninit(&c->cv_lock);
18 }
19
20 int
21 _cv_timedwait(struct cv *c, struct lock *lk, int timo, int wakesig)
22 {
23         int flags = wakesig ? PCATCH : 0;
24         int error;
25
26         /*
27          * Can interlock without critical section/spinlock as long
28          * as we don't block before calling *sleep().  PINTERLOCKED
29          * must be passed to the *sleep() to use the manual interlock
30          * (else a new one is created which opens a timing race).
31          */
32         tsleep_interlock(c, flags);
33
34         spin_lock(&c->cv_lock);
35         c->cv_waiters++;
36         spin_unlock(&c->cv_lock);
37
38         if (lk)
39                 error = lksleep(c, lk, flags | PINTERLOCKED, c->cv_desc, timo);
40         else
41                 error = tsleep(c, flags | PINTERLOCKED, c->cv_desc, timo);
42
43         return (error);
44 }
45
46 /*
47  * _cv_timedwait() implementation using mtx.
48  */
49 int
50 _cv_mtx_timedwait(struct cv *c, struct mtx *mtx, int timo, int wakesig)
51 {
52         int flags = wakesig ? PCATCH : 0;
53         int error;
54
55         /*
56          * Can interlock without critical section/spinlock as long
57          * as we don't block before calling *sleep().  PINTERLOCKED
58          * must be passed to the *sleep() to use the manual interlock
59          * (else a new one is created which opens a timing race).
60          */
61         tsleep_interlock(c, flags);
62
63         spin_lock(&c->cv_lock);
64         c->cv_waiters++;
65         spin_unlock(&c->cv_lock);
66
67         if (mtx)
68                 error = mtxsleep(c, mtx, flags | PINTERLOCKED, c->cv_desc, timo);
69         else
70                 error = tsleep(c, flags | PINTERLOCKED, c->cv_desc, timo);
71
72         return (error);
73 }
74
75 void
76 _cv_signal(struct cv *c, int broadcast)
77 {
78         spin_lock(&c->cv_lock);
79         if (c->cv_waiters == 0) {
80                 spin_unlock(&c->cv_lock);
81         } else if (broadcast) {
82                 c->cv_waiters = 0;
83                 spin_unlock(&c->cv_lock);       /* must unlock first */
84                 wakeup(c);
85         } else {
86                 c->cv_waiters--;
87                 spin_unlock(&c->cv_lock);       /* must unlock first */
88                 wakeup_one(c);
89         }
90 }
91
92 int
93 cv_has_waiters(const struct cv *c)
94 {
95         return (c->cv_waiters);
96 }