16830d0fcSSimon Schubert #include <sys/condvar.h>
26830d0fcSSimon Schubert #include <sys/spinlock2.h>
36830d0fcSSimon Schubert #include <sys/systm.h>
46830d0fcSSimon Schubert #include <sys/lock.h>
56830d0fcSSimon Schubert
66830d0fcSSimon Schubert void
cv_init(struct cv * c,const char * desc)76830d0fcSSimon Schubert cv_init(struct cv *c, const char *desc)
86830d0fcSSimon Schubert {
96830d0fcSSimon Schubert c->cv_desc = desc;
106830d0fcSSimon Schubert c->cv_waiters = 0;
11ba87a4abSSascha Wildner spin_init(&c->cv_lock, "cvinit");
126830d0fcSSimon Schubert }
136830d0fcSSimon Schubert
146830d0fcSSimon Schubert void
cv_destroy(struct cv * c)156830d0fcSSimon Schubert cv_destroy(struct cv *c)
166830d0fcSSimon Schubert {
176830d0fcSSimon Schubert spin_uninit(&c->cv_lock);
186830d0fcSSimon Schubert }
196830d0fcSSimon Schubert
206830d0fcSSimon Schubert int
_cv_timedwait(struct cv * c,struct lock * lk,int timo,int wakesig)21a5fcdfa4SMatthew Dillon _cv_timedwait(struct cv *c, struct lock *lk, int timo, int wakesig)
226830d0fcSSimon Schubert {
236830d0fcSSimon Schubert int flags = wakesig ? PCATCH : 0;
246830d0fcSSimon Schubert int error;
256830d0fcSSimon Schubert
26a5fcdfa4SMatthew Dillon /*
27a5fcdfa4SMatthew Dillon * Can interlock without critical section/spinlock as long
28a5fcdfa4SMatthew Dillon * as we don't block before calling *sleep(). PINTERLOCKED
29a5fcdfa4SMatthew Dillon * must be passed to the *sleep() to use the manual interlock
30a5fcdfa4SMatthew Dillon * (else a new one is created which opens a timing race).
31a5fcdfa4SMatthew Dillon */
326830d0fcSSimon Schubert tsleep_interlock(c, flags);
33a5fcdfa4SMatthew Dillon
34a5fcdfa4SMatthew Dillon spin_lock(&c->cv_lock);
356830d0fcSSimon Schubert c->cv_waiters++;
36287a8577SAlex Hornung spin_unlock(&c->cv_lock);
37a5fcdfa4SMatthew Dillon
38a5fcdfa4SMatthew Dillon if (lk)
39a5fcdfa4SMatthew Dillon error = lksleep(c, lk, flags | PINTERLOCKED, c->cv_desc, timo);
40a5fcdfa4SMatthew Dillon else
41a5fcdfa4SMatthew Dillon error = tsleep(c, flags | PINTERLOCKED, c->cv_desc, timo);
426830d0fcSSimon Schubert
436830d0fcSSimon Schubert return (error);
446830d0fcSSimon Schubert }
456830d0fcSSimon Schubert
46*3426d2c2STomohiro Kusumi /*
47*3426d2c2STomohiro Kusumi * _cv_timedwait() implementation using mtx.
48*3426d2c2STomohiro Kusumi */
49*3426d2c2STomohiro Kusumi int
_cv_mtx_timedwait(struct cv * c,struct mtx * mtx,int timo,int wakesig)50*3426d2c2STomohiro Kusumi _cv_mtx_timedwait(struct cv *c, struct mtx *mtx, int timo, int wakesig)
51*3426d2c2STomohiro Kusumi {
52*3426d2c2STomohiro Kusumi int flags = wakesig ? PCATCH : 0;
53*3426d2c2STomohiro Kusumi int error;
54*3426d2c2STomohiro Kusumi
55*3426d2c2STomohiro Kusumi /*
56*3426d2c2STomohiro Kusumi * Can interlock without critical section/spinlock as long
57*3426d2c2STomohiro Kusumi * as we don't block before calling *sleep(). PINTERLOCKED
58*3426d2c2STomohiro Kusumi * must be passed to the *sleep() to use the manual interlock
59*3426d2c2STomohiro Kusumi * (else a new one is created which opens a timing race).
60*3426d2c2STomohiro Kusumi */
61*3426d2c2STomohiro Kusumi tsleep_interlock(c, flags);
62*3426d2c2STomohiro Kusumi
63*3426d2c2STomohiro Kusumi spin_lock(&c->cv_lock);
64*3426d2c2STomohiro Kusumi c->cv_waiters++;
65*3426d2c2STomohiro Kusumi spin_unlock(&c->cv_lock);
66*3426d2c2STomohiro Kusumi
67*3426d2c2STomohiro Kusumi if (mtx)
68*3426d2c2STomohiro Kusumi error = mtxsleep(c, mtx, flags | PINTERLOCKED, c->cv_desc, timo);
69*3426d2c2STomohiro Kusumi else
70*3426d2c2STomohiro Kusumi error = tsleep(c, flags | PINTERLOCKED, c->cv_desc, timo);
71*3426d2c2STomohiro Kusumi
72*3426d2c2STomohiro Kusumi return (error);
73*3426d2c2STomohiro Kusumi }
74*3426d2c2STomohiro Kusumi
756830d0fcSSimon Schubert void
_cv_signal(struct cv * c,int broadcast)766830d0fcSSimon Schubert _cv_signal(struct cv *c, int broadcast)
776830d0fcSSimon Schubert {
78287a8577SAlex Hornung spin_lock(&c->cv_lock);
79a5fcdfa4SMatthew Dillon if (c->cv_waiters == 0) {
80a5fcdfa4SMatthew Dillon spin_unlock(&c->cv_lock);
81a5fcdfa4SMatthew Dillon } else if (broadcast) {
826830d0fcSSimon Schubert c->cv_waiters = 0;
83a5fcdfa4SMatthew Dillon spin_unlock(&c->cv_lock); /* must unlock first */
846830d0fcSSimon Schubert wakeup(c);
856830d0fcSSimon Schubert } else {
866830d0fcSSimon Schubert c->cv_waiters--;
87a5fcdfa4SMatthew Dillon spin_unlock(&c->cv_lock); /* must unlock first */
886830d0fcSSimon Schubert wakeup_one(c);
896830d0fcSSimon Schubert }
906830d0fcSSimon Schubert }
9170f34aabSAlex Hornung
9270f34aabSAlex Hornung int
cv_has_waiters(const struct cv * c)93c67284abSStathis Kamperis cv_has_waiters(const struct cv *c)
9470f34aabSAlex Hornung {
9570f34aabSAlex Hornung return (c->cv_waiters);
9670f34aabSAlex Hornung }
97