xref: /dragonfly/sys/kern/kern_condvar.c (revision 3426d2c2)
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