From 6d8cabe8f4f1abc304c60dd832e05f18f069451b Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Sat, 10 Dec 2016 22:48:57 -0800 Subject: Condition variable implementation. --- src/platform/platform.h | 12 ++++---- src/platform/posix/posix_synch.h | 61 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 7 deletions(-) (limited to 'src/platform') diff --git a/src/platform/platform.h b/src/platform/platform.h index 05f55be9..36ec207c 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -26,6 +26,7 @@ #include #include #include +#include /* * These are the APIs that a platform must implement to support nng. @@ -95,22 +96,19 @@ void nni_cond_destroy(nni_cond_t); * nni_cond_broadcast wakes all waiters on the condition. This should be * called with the lock held. */ -int nni_cond_broadcast(nni_cond_t); +void nni_cond_broadcast(nni_cond_t); /* * nni_cond_signal wakes a signal waiter. */ -int nni_cond_signal(nni_cond_t); +void nni_cond_signal(nni_cond_t); /* * nni_condwait waits for a wake up on the condition variable. The * associated lock is atomically released and reacquired upon wake up. - * Callers can be spuriously woken. The return value is 0 on success, - * or an error code. (Most implementations should never return an error.) - * Most callers will ignore the return value. The associated lock must - * be held. + * Callers can be spuriously woken. The associated lock must be held. */ -int nni_cond_wait(nni_cond_t); +void nni_cond_wait(nni_cond_t); /* * nni_cond_timedwait waits for a wakeup on the condition variable, just diff --git a/src/platform/posix/posix_synch.h b/src/platform/posix/posix_synch.h index 4a3a152d..0eae133e 100644 --- a/src/platform/posix/posix_synch.h +++ b/src/platform/posix/posix_synch.h @@ -32,6 +32,7 @@ */ #include +#include struct nni_mutex { pthread_mutex_t mx; @@ -141,3 +142,63 @@ nni_cond_destroy(nni_cond_t c) } nni_free(c, sizeof (*c)); } + +void +nni_cond_signal(nni_cond_t c) +{ + if (pthread_cond_signal(&c->cv) != 0) { + nni_panic("pthread_cond_signal failed"); + } +} + +void +nni_cond_broadcast(nni_cond_t c) +{ + if (pthread_cond_broadcast(&c->cv) != 0) { + nni_panic("pthread_cond_broadcast failed"); + } +} + +void +nni_cond_wait(nni_cond_t c) +{ + if (pthread_cond_wait(&c->cv, c->mx) != 0) { + nni_panic("pthread_cond_wait failed"); + } +} + +int +nni_cond_timedwait(nni_cond_t c, int msec) +{ + struct timespec ts; + int rv; + /* POSIX says clock_gettime exists since SUSv2 at least. */ + + rv = clock_gettime(CLOCK_REALTIME, &ts); + if (rv != 0) { + /* + * If the clock_gettime() is not working, its a problem with + * the platform. Arguably we could use gettimeofday instead, + * but for now we just panic(). We can fix this when someone + * finds a platform that returns ENOSYS here. + */ + nni_panic("clock_gettime failed: %s", strerror(errno)); + } + + ts.tv_nsec += (msec * 1000000); + + /* Normalize -- its not clear if this is strictly necessary. */ + while (ts.tv_nsec > 1000000000) { + ts.tv_nsec -= 1000000000; + ts.tv_sec++; + } + + if ((rv = pthread_cond_timedwait(&c->cv, c->mx, &ts)) != 0) { + if (rv == ETIMEDOUT) { + return (NNG_ETIMEDOUT); + } else { + nni_panic("pthread_cond_timedwait returned %d", rv); + } + } + return (0); +} -- cgit v1.2.3-70-g09d2