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 *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 void 47 _cv_signal(struct cv *c, int broadcast) 48 { 49 spin_lock(&c->cv_lock); 50 if (c->cv_waiters == 0) { 51 spin_unlock(&c->cv_lock); 52 } else if (broadcast) { 53 c->cv_waiters = 0; 54 spin_unlock(&c->cv_lock); /* must unlock first */ 55 wakeup(c); 56 } else { 57 c->cv_waiters--; 58 spin_unlock(&c->cv_lock); /* must unlock first */ 59 wakeup_one(c); 60 } 61 } 62 63 int 64 cv_has_waiters(const struct cv *c) 65 { 66 return (c->cv_waiters); 67 } 68