Add a mutex/condvar based semaphore implementation if sem_timedwait is unavailable
Fixes #214.
This commit is contained in:
@@ -409,6 +409,8 @@ dnl check if we can cancel threads
|
|||||||
AC_CHECK_FUNCS(pthread_cancel)
|
AC_CHECK_FUNCS(pthread_cancel)
|
||||||
dnl check if native rwlocks are available
|
dnl check if native rwlocks are available
|
||||||
AC_CHECK_FUNCS(pthread_rwlock_init)
|
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
|
LIBS=$saved_LIBS
|
||||||
|
|
||||||
AC_CHECK_FUNC(
|
AC_CHECK_FUNC(
|
||||||
|
|||||||
@@ -13,10 +13,14 @@
|
|||||||
* for more details.
|
* for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <semaphore.h>
|
|
||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SEM_TIMEDWAIT
|
||||||
|
#include <semaphore.h>
|
||||||
|
#else /* !HAVE_SEM_TIMEDWAIT */
|
||||||
|
#include <threading/condvar.h>
|
||||||
|
#endif /* HAVE_SEM_TIMEDWAIT */
|
||||||
|
|
||||||
#include "semaphore.h"
|
#include "semaphore.h"
|
||||||
|
|
||||||
typedef struct private_semaphore_t private_semaphore_t;
|
typedef struct private_semaphore_t private_semaphore_t;
|
||||||
@@ -30,21 +34,50 @@ struct private_semaphore_t {
|
|||||||
*/
|
*/
|
||||||
semaphore_t public;
|
semaphore_t public;
|
||||||
|
|
||||||
|
#ifdef HAVE_SEM_TIMEDWAIT
|
||||||
/**
|
/**
|
||||||
* wrapped POSIX semaphore object
|
* wrapped POSIX semaphore object
|
||||||
*/
|
*/
|
||||||
sem_t sem;
|
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,
|
METHOD(semaphore_t, wait_, void,
|
||||||
private_semaphore_t *this)
|
private_semaphore_t *this)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_SEM_TIMEDWAIT
|
||||||
sem_wait(&this->sem);
|
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,
|
METHOD(semaphore_t, timed_wait_abs, bool,
|
||||||
private_semaphore_t *this, timeval_t tv)
|
private_semaphore_t *this, timeval_t tv)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_SEM_TIMEDWAIT
|
||||||
timespec_t ts;
|
timespec_t ts;
|
||||||
|
|
||||||
ts.tv_sec = tv.tv_sec;
|
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
|
/* there are errors other than ETIMEDOUT possible, but we consider them
|
||||||
* all as timeout */
|
* all as timeout */
|
||||||
return sem_timedwait(&this->sem, &ts) == -1;
|
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,
|
METHOD(semaphore_t, timed_wait, bool,
|
||||||
@@ -72,13 +119,25 @@ METHOD(semaphore_t, timed_wait, bool,
|
|||||||
METHOD(semaphore_t, post, void,
|
METHOD(semaphore_t, post, void,
|
||||||
private_semaphore_t *this)
|
private_semaphore_t *this)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_SEM_TIMEDWAIT
|
||||||
sem_post(&this->sem);
|
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,
|
METHOD(semaphore_t, destroy, void,
|
||||||
private_semaphore_t *this)
|
private_semaphore_t *this)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_SEM_TIMEDWAIT
|
||||||
sem_destroy(&this->sem);
|
sem_destroy(&this->sem);
|
||||||
|
#else /* !HAVE_SEM_TIMEDWAIT */
|
||||||
|
this->cond->destroy(this->cond);
|
||||||
|
this->mutex->destroy(this->mutex);
|
||||||
|
#endif /* HAVE_SEM_TIMEDWAIT */
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +158,13 @@ semaphore_t *semaphore_create(u_int value)
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#ifdef HAVE_SEM_TIMEDWAIT
|
||||||
sem_init(&this->sem, 0, value);
|
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;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user