Skip to content

Commit

Permalink
Revised posix semaphore implementation to binary semaphore
Browse files Browse the repository at this point in the history
Fabricates a binary semaphore using a mutex and condition variable.

Unlike the previous condition variable implementation, the use of this
flag state avoids race problems with signaling before conditional waits.
  • Loading branch information
geky committed Aug 15, 2016
1 parent 3470d88 commit cb97f5f
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 17 deletions.
54 changes: 39 additions & 15 deletions equeue_posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,31 +43,55 @@ void equeue_mutex_unlock(equeue_mutex_t *m) {

// Semaphore operations
int equeue_sema_create(equeue_sema_t *s) {
return sem_init(s, 0, 0);
int err = pthread_mutex_init(&s->mutex, 0);
if (err) {
return err;
}

err = pthread_cond_init(&s->cond, 0);
if (err) {
return err;
}

s->signal = false;
return 0;
}

void equeue_sema_destroy(equeue_sema_t *s) {
sem_destroy(s);
pthread_cond_destroy(&s->cond);
pthread_mutex_destroy(&s->mutex);
}

void equeue_sema_signal(equeue_sema_t *s) {
sem_post(s);
pthread_mutex_lock(&s->mutex);
s->signal = true;
pthread_cond_signal(&s->cond);
pthread_mutex_unlock(&s->mutex);
}

bool equeue_sema_wait(equeue_sema_t *s, int ms) {
if (ms < 0) {
return !sem_wait(s);
} else {
struct timeval tv;
gettimeofday(&tv, 0);

struct timespec ts = {
.tv_sec = ms/1000 + tv.tv_sec,
.tv_nsec = ms*1000000 + tv.tv_usec*1000,
};

return !sem_timedwait(s, &ts);
pthread_mutex_lock(&s->mutex);
if (!s->signal) {
if (ms < 0) {
pthread_cond_wait(&s->cond, &s->mutex);
} else {
struct timeval tv;
gettimeofday(&tv, 0);

struct timespec ts = {
.tv_sec = ms/1000 + tv.tv_sec,
.tv_nsec = ms*1000000 + tv.tv_usec*1000,
};

pthread_cond_timedwait(&s->cond, &s->mutex, &ts);
}
}

bool signal = s->signal;
s->signal = false;
pthread_mutex_unlock(&s->mutex);

return signal;
}

#endif
8 changes: 6 additions & 2 deletions equeue_sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@ extern "C" {
// dispatch loop to run unnecessarily. For that matter, equeue_signal_wait
// may even be implemented as a single return statement.
#if defined(__unix__)
#include <semaphore.h>
typedef sem_t equeue_sema_t;
#include <pthread.h>
typedef struct equeue_sema {
pthread_mutex_t mutex;
pthread_cond_t cond;
bool signal;
} equeue_sema_t;
#elif defined(__MBED__) && defined(MBED_CONF_RTOS_PRESENT)
typedef unsigned equeue_sema_t[8];
#elif defined(__MBED__)
Expand Down

0 comments on commit cb97f5f

Please sign in to comment.