From a3eba19470c09f42272dac5ca1a34bd8a5cbe834 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Tue, 17 Nov 2009 10:26:25 +0100 Subject: The original version of DDEKit. --- libddekit/condvar.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 libddekit/condvar.c (limited to 'libddekit/condvar.c') diff --git a/libddekit/condvar.c b/libddekit/condvar.c new file mode 100644 index 00000000..a495cf92 --- /dev/null +++ b/libddekit/condvar.c @@ -0,0 +1,108 @@ +/** + * Unchecked (no BSD invariants) condition variable implementation for + * dde-internal use. Written from scratch. + * + * \author Thomas Friebel + */ +#include +#include +#include + +#include +#include +#include + +struct ddekit_condvar { + unsigned waiters; + unsigned signals; + l4lock_t lock; + l4semaphore_t sem; + l4semaphore_t handshake; +}; + +ddekit_condvar_t *ddekit_condvar_init() { + ddekit_condvar_t *cvp; + + cvp = ddekit_simple_malloc(sizeof(*cvp)); + + cvp->waiters = 0; + cvp->signals = 0; + cvp->lock = L4LOCK_UNLOCKED; + cvp->sem = L4SEMAPHORE_INIT(0); + cvp->handshake = L4SEMAPHORE_INIT(0); + + return cvp; +} + +void ddekit_condvar_wait(ddekit_condvar_t *cvp, ddekit_lock_t *mp) { + ddekit_condvar_wait_timed(cvp, mp, -1); +} + +int ddekit_condvar_wait_timed(ddekit_condvar_t *cvp, ddekit_lock_t *mp, int timo) { + int rval; + + l4lock_lock(&cvp->lock); + cvp->waiters++; + l4lock_unlock(&cvp->lock); + + ddekit_lock_unlock(mp); + + if (timo == -1) { + l4semaphore_down(&cvp->sem); + rval = 0; + } else { + rval = l4semaphore_down_timed(&cvp->sem, timo); + } + + l4lock_lock(&cvp->lock); + if (cvp->signals > 0) { + /* if we timed out, but there is a signal now, consume it */ + if (rval) l4semaphore_down(&cvp->sem); + + l4semaphore_up(&cvp->handshake); + cvp->signals--; + } + cvp->waiters--; + l4lock_unlock(&cvp->lock); + + ddekit_lock_lock(mp); + + return rval; +} + +void ddekit_condvar_signal(ddekit_condvar_t *cvp) +{ + l4lock_lock(&cvp->lock); + + if (cvp->waiters > cvp->signals) { + cvp->signals++; + l4semaphore_up(&cvp->sem); + l4lock_unlock(&cvp->lock); + l4semaphore_down(&cvp->handshake); + } else { + /* nobody left to wakeup */ + l4lock_unlock(&cvp->lock); + } +} + +void ddekit_condvar_broadcast(ddekit_condvar_t *cvp) { + int waiters; + + l4lock_lock(&cvp->lock); + + waiters = cvp->waiters - cvp->signals; + if (waiters > 0) { + int i; + + cvp->signals = cvp->waiters; + for (i=0; isem); + } + l4lock_unlock(&cvp->lock); + for (i=0; ihandshake); + } + } else { + l4lock_unlock(&cvp->lock); + } +} -- cgit v1.2.3