#include <sys/condvar.h>
#include <sys/spinlock2.h>
#include <sys/systm.h>
#include <sys/lock.h>
void
cv_init(struct cv *c, const char *desc)
{
c->cv_desc = desc;
c->cv_waiters = 0;
spin_init(&c->cv_lock, "cvinit");
}
void
cv_destroy(struct cv *c)
{
spin_uninit(&c->cv_lock);
}
int
_cv_timedwait(struct cv *c, struct lock *lk, int timo, int wakesig)
{
int flags = wakesig ? PCATCH : 0;
int error;
tsleep_interlock(c, flags);
spin_lock(&c->cv_lock);
c->cv_waiters++;
spin_unlock(&c->cv_lock);
if (lk)
error = lksleep(c, lk, flags | PINTERLOCKED, c->cv_desc, timo);
else
error = tsleep(c, flags | PINTERLOCKED, c->cv_desc, timo);
return (error);
}
int
_cv_mtx_timedwait(struct cv *c, struct mtx *mtx, int timo, int wakesig)
{
int flags = wakesig ? PCATCH : 0;
int error;
tsleep_interlock(c, flags);
spin_lock(&c->cv_lock);
c->cv_waiters++;
spin_unlock(&c->cv_lock);
if (mtx)
error = mtxsleep(c, mtx, flags | PINTERLOCKED, c->cv_desc, timo);
else
error = tsleep(c, flags | PINTERLOCKED, c->cv_desc, timo);
return (error);
}
void
_cv_signal(struct cv *c, int broadcast)
{
spin_lock(&c->cv_lock);
if (c->cv_waiters == 0) {
spin_unlock(&c->cv_lock);
} else if (broadcast) {
c->cv_waiters = 0;
spin_unlock(&c->cv_lock);
wakeup(c);
} else {
c->cv_waiters--;
spin_unlock(&c->cv_lock);
wakeup_one(c);
}
}
int
cv_has_waiters(const struct cv *c)
{
return (c->cv_waiters);
}