00001 /** 00002 * Unchecked (no BSD invariants) condition variable implementation for 00003 * dde-internal use. Written from scratch. 00004 * 00005 * \author Thomas Friebel <tf13@os.inf.tu-dresden.de> 00006 */ 00007 #include <l4/dde/ddekit/condvar.h> 00008 #include <l4/dde/ddekit/lock.h> 00009 #include <l4/dde/ddekit/memory.h> 00010 00011 #include <l4/log/l4log.h> 00012 #include <l4/semaphore/semaphore.h> 00013 #include <l4/lock/lock.h> 00014 00015 struct ddekit_condvar { 00016 unsigned waiters; 00017 unsigned signals; 00018 l4lock_t lock; 00019 l4semaphore_t sem; 00020 l4semaphore_t handshake; 00021 }; 00022 00023 ddekit_condvar_t *ddekit_condvar_init() { 00024 ddekit_condvar_t *cvp; 00025 00026 cvp = ddekit_simple_malloc(sizeof(*cvp)); 00027 00028 cvp->waiters = 0; 00029 cvp->signals = 0; 00030 cvp->lock = L4LOCK_UNLOCKED; 00031 cvp->sem = L4SEMAPHORE_INIT(0); 00032 cvp->handshake = L4SEMAPHORE_INIT(0); 00033 00034 return cvp; 00035 } 00036 00037 void ddekit_condvar_wait(ddekit_condvar_t *cvp, ddekit_lock_t *mp) { 00038 ddekit_condvar_wait_timed(cvp, mp, -1); 00039 } 00040 00041 int ddekit_condvar_wait_timed(ddekit_condvar_t *cvp, ddekit_lock_t *mp, int timo) { 00042 int rval; 00043 00044 l4lock_lock(&cvp->lock); 00045 cvp->waiters++; 00046 l4lock_unlock(&cvp->lock); 00047 00048 ddekit_lock_unlock(mp); 00049 00050 if (timo == -1) { 00051 l4semaphore_down(&cvp->sem); 00052 rval = 0; 00053 } else { 00054 rval = l4semaphore_down_timed(&cvp->sem, timo); 00055 } 00056 00057 l4lock_lock(&cvp->lock); 00058 if (cvp->signals > 0) { 00059 /* if we timed out, but there is a signal now, consume it */ 00060 if (rval) l4semaphore_down(&cvp->sem); 00061 00062 l4semaphore_up(&cvp->handshake); 00063 cvp->signals--; 00064 } 00065 cvp->waiters--; 00066 l4lock_unlock(&cvp->lock); 00067 00068 ddekit_lock_lock(mp); 00069 00070 return rval; 00071 } 00072 00073 void ddekit_condvar_signal(ddekit_condvar_t *cvp) 00074 { 00075 l4lock_lock(&cvp->lock); 00076 00077 if (cvp->waiters > cvp->signals) { 00078 cvp->signals++; 00079 l4semaphore_up(&cvp->sem); 00080 l4lock_unlock(&cvp->lock); 00081 l4semaphore_down(&cvp->handshake); 00082 } else { 00083 /* nobody left to wakeup */ 00084 l4lock_unlock(&cvp->lock); 00085 } 00086 } 00087 00088 void ddekit_condvar_broadcast(ddekit_condvar_t *cvp) { 00089 int waiters; 00090 00091 l4lock_lock(&cvp->lock); 00092 00093 waiters = cvp->waiters - cvp->signals; 00094 if (waiters > 0) { 00095 int i; 00096 00097 cvp->signals = cvp->waiters; 00098 for (i=0; i<waiters; i++) { 00099 l4semaphore_up(&cvp->sem); 00100 } 00101 l4lock_unlock(&cvp->lock); 00102 for (i=0; i<waiters; i++) { 00103 l4semaphore_down(&cvp->handshake); 00104 } 00105 } else { 00106 l4lock_unlock(&cvp->lock); 00107 } 00108 }
1.5.6