Merge branch 'vendor/FILE'
[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);
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 *l, int timo, int wakesig)
22 {
23         int flags = wakesig ? PCATCH : 0;
24         int error;
25
26         spin_lock(&c->cv_lock);
27         tsleep_interlock(c, flags);
28         c->cv_waiters++;
29         spin_unlock(&c->cv_lock);
30         if (l != NULL)
31                 lockmgr(l, LK_RELEASE);
32         error = tsleep(c, flags, c->cv_desc, timo);
33         if (l != NULL)
34                 lockmgr(l, LK_EXCLUSIVE);
35
36         return (error);
37 }
38
39 void
40 _cv_signal(struct cv *c, int broadcast)
41 {
42         spin_lock(&c->cv_lock);
43         if (c->cv_waiters == 0)
44                 goto out;
45
46         if (broadcast) {
47                 c->cv_waiters = 0;
48                 wakeup(c);
49         } else {
50                 c->cv_waiters--;
51                 wakeup_one(c);
52         }
53
54 out:
55         spin_unlock(&c->cv_lock);
56 }
57
58 int
59 cv_has_waiters(const struct cv *c)
60 {
61         return (c->cv_waiters);
62 }