From: Martin Willi Date: Mon, 20 Aug 2012 14:58:15 +0000 (+0200) Subject: Add a mutex/condvar based semaphore implementation if sem_timedwait is unavailable X-Git-Tag: 5.0.1~172 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=907d3d0f1d4bde9738c7ba3a4b369de310efc830;p=thirdparty%2Fstrongswan.git Add a mutex/condvar based semaphore implementation if sem_timedwait is unavailable Fixes #214. --- diff --git a/configure.in b/configure.in index b685db9007..2ab96e078b 100644 --- a/configure.in +++ b/configure.in @@ -409,6 +409,8 @@ dnl check if we can cancel threads AC_CHECK_FUNCS(pthread_cancel) dnl check if native rwlocks are available AC_CHECK_FUNCS(pthread_rwlock_init) +dnl check if we have POSIX semaphore functions, including timed-wait +AC_CHECK_FUNCS(sem_timedwait) LIBS=$saved_LIBS AC_CHECK_FUNC( diff --git a/src/libstrongswan/threading/semaphore.c b/src/libstrongswan/threading/semaphore.c index b7ab9ce7ae..c35cf1ea50 100644 --- a/src/libstrongswan/threading/semaphore.c +++ b/src/libstrongswan/threading/semaphore.c @@ -13,10 +13,14 @@ * for more details. */ -#include - #include +#ifdef HAVE_SEM_TIMEDWAIT +#include +#else /* !HAVE_SEM_TIMEDWAIT */ +#include +#endif /* HAVE_SEM_TIMEDWAIT */ + #include "semaphore.h" typedef struct private_semaphore_t private_semaphore_t; @@ -30,21 +34,50 @@ struct private_semaphore_t { */ semaphore_t public; +#ifdef HAVE_SEM_TIMEDWAIT /** * wrapped POSIX semaphore object */ sem_t sem; +#else /* !HAVE_SEM_TIMEDWAIT */ + + /** + * Mutex to lock count variable + */ + mutex_t *mutex; + + /** + * Condvar to signal count increase + */ + condvar_t *cond; + + /** + * Semaphore count value + */ + u_int count; +#endif /* HAVE_SEM_TIMEDWAIT */ }; METHOD(semaphore_t, wait_, void, private_semaphore_t *this) { +#ifdef HAVE_SEM_TIMEDWAIT sem_wait(&this->sem); +#else /* !HAVE_SEM_TIMEDWAIT */ + this->mutex->lock(this->mutex); + while (this->count == 0) + { + this->cond->wait(this->cond, this->mutex); + } + this->count--; + this->mutex->unlock(this->mutex); +#endif /* HAVE_SEM_TIMEDWAIT */ } METHOD(semaphore_t, timed_wait_abs, bool, private_semaphore_t *this, timeval_t tv) { +#ifdef HAVE_SEM_TIMEDWAIT timespec_t ts; ts.tv_sec = tv.tv_sec; @@ -53,6 +86,20 @@ METHOD(semaphore_t, timed_wait_abs, bool, /* there are errors other than ETIMEDOUT possible, but we consider them * all as timeout */ return sem_timedwait(&this->sem, &ts) == -1; +#else /* !HAVE_SEM_TIMEDWAIT */ + this->mutex->lock(this->mutex); + while (this->count == 0) + { + if (this->cond->timed_wait_abs(this->cond, this->mutex, tv)) + { + this->mutex->unlock(this->mutex); + return TRUE; + } + } + this->count--; + this->mutex->unlock(this->mutex); + return FALSE; +#endif /* HAVE_SEM_TIMEDWAIT */ } METHOD(semaphore_t, timed_wait, bool, @@ -72,13 +119,25 @@ METHOD(semaphore_t, timed_wait, bool, METHOD(semaphore_t, post, void, private_semaphore_t *this) { +#ifdef HAVE_SEM_TIMEDWAIT sem_post(&this->sem); +#else /* !HAVE_SEM_TIMEDWAIT */ + this->mutex->lock(this->mutex); + this->count++; + this->mutex->unlock(this->mutex); + this->cond->signal(this->cond); +#endif /* HAVE_SEM_TIMEDWAIT */ } METHOD(semaphore_t, destroy, void, private_semaphore_t *this) { +#ifdef HAVE_SEM_TIMEDWAIT sem_destroy(&this->sem); +#else /* !HAVE_SEM_TIMEDWAIT */ + this->cond->destroy(this->cond); + this->mutex->destroy(this->mutex); +#endif /* HAVE_SEM_TIMEDWAIT */ free(this); } @@ -99,7 +158,13 @@ semaphore_t *semaphore_create(u_int value) }, ); +#ifdef HAVE_SEM_TIMEDWAIT sem_init(&this->sem, 0, value); +#else /* !HAVE_SEM_TIMEDWAIT */ + this->mutex = mutex_create(MUTEX_TYPE_DEFAULT); + this->cond = condvar_create(CONDVAR_TYPE_DEFAULT); + this->count = value; +#endif /* HAVE_SEM_TIMEDWAIT */ return &this->public; }