From 6830d0fc0de36e92552f8aee97d44750f49c6a62 Mon Sep 17 00:00:00 2001 From: Simon Schubert Date: Fri, 11 Dec 2009 23:25:09 +0100 Subject: [PATCH] condvar: add implementation Add a small implementation of condition variables. API design adopted from FreeBSD. --- sys/conf/files | 1 + sys/kern/kern_condvar.c | 56 +++++++++++++++++++++++++++++++++++++++++ sys/sys/condvar.h | 36 ++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 sys/kern/kern_condvar.c create mode 100644 sys/sys/condvar.h diff --git a/sys/conf/files b/sys/conf/files index 39793d0d1f..a5bc7b8ed8 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -649,6 +649,7 @@ kern/link_elf.c standard kern/kern_acct.c standard kern/kern_acl.c standard kern/kern_clock.c standard +kern/kern_condvar.c standard kern/kern_conf.c standard kern/kern_debug.c standard kern/kern_device.c standard diff --git a/sys/kern/kern_condvar.c b/sys/kern/kern_condvar.c new file mode 100644 index 0000000000..06ec868c45 --- /dev/null +++ b/sys/kern/kern_condvar.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include + +void +cv_init(struct cv *c, const char *desc) +{ + c->cv_desc = desc; + c->cv_waiters = 0; + spin_init(&c->cv_lock); +} + +void +cv_destroy(struct cv *c) +{ + spin_uninit(&c->cv_lock); +} + +int +_cv_timedwait(struct cv *c, struct lock *l, int timo, int wakesig) +{ + int flags = wakesig ? PCATCH : 0; + int error; + + spin_lock_wr(&c->cv_lock); + tsleep_interlock(c, flags); + c->cv_waiters++; + spin_unlock_wr(&c->cv_lock); + if (l != NULL) + lockmgr(l, LK_RELEASE); + error = tsleep(c, flags, c->cv_desc, timo); + if (l != NULL) + lockmgr(l, LK_EXCLUSIVE); + + return (error); +} + +void +_cv_signal(struct cv *c, int broadcast) +{ + spin_lock_wr(&c->cv_lock); + if (c->cv_waiters == 0) + goto out; + + if (broadcast) { + c->cv_waiters = 0; + wakeup(c); + } else { + c->cv_waiters--; + wakeup_one(c); + } + +out: + spin_unlock_wr(&c->cv_lock); +} diff --git a/sys/sys/condvar.h b/sys/sys/condvar.h new file mode 100644 index 0000000000..3acd3144a7 --- /dev/null +++ b/sys/sys/condvar.h @@ -0,0 +1,36 @@ +#ifndef _SYS_CONDVAR_H_ +#define _SYS_CONDVAR_H_ + +#include + +struct lock; + +struct cv { + struct spinlock cv_lock; + int cv_waiters; + const char *cv_desc; +}; + +void cv_init(struct cv *, const char *desc); +void cv_destroy(struct cv *); + +int _cv_timedwait(struct cv *, struct lock *, int timo, int wakesig); +void _cv_signal(struct cv *, int broadcast); + +#define cv_wait(cv, lock) \ + _cv_timedwait((cv), (lock), 0, 0) +#define cv_wait_sig(cv, lock) \ + _cv_timedwait((cv), (lock), 0, 1) +#define cv_timedwait(cv, lock, timeo) \ + _cv_timedwait((cv), (lock), (timeo), 0) +#define cv_timedwait_sig(cv, lock, timeo) \ + _cv_timedwait((cv), (lock), (timeo), 1) + +#define cv_signal(cv) \ + _cv_signal((cv), 0) +#define cv_broadcast(cv) \ + _cv_signal((cv), 1) +#define cv_broadcastpri(cv) \ + cv_broadcast((cv)) + +#endif /* _SYS_CONDVAR_H_ */ -- 2.41.0