diff options
Diffstat (limited to 'src/platform/posix')
| -rw-r--r-- | src/platform/posix/posix_impl.h | 17 | ||||
| -rw-r--r-- | src/platform/posix/posix_thread.c | 171 |
2 files changed, 186 insertions, 2 deletions
diff --git a/src/platform/posix/posix_impl.h b/src/platform/posix/posix_impl.h index 2df96c71..5ca7812f 100644 --- a/src/platform/posix/posix_impl.h +++ b/src/platform/posix/posix_impl.h @@ -41,6 +41,23 @@ struct nni_cond { pthread_cond_t cv; pthread_mutex_t * mx; }; + +// These types are provided for here, to permit them to be directly inlined +// elsewhere. + +struct nni_plat_mtx { + pthread_mutex_t mtx; +}; + +struct nni_plat_thr { + pthread_t tid; +}; + +struct nni_plat_cv { + pthread_cond_t cv; + pthread_mutex_t *mtx; +}; + #endif #endif // PLATFORM_POSIX_IMPL_H diff --git a/src/platform/posix/posix_thread.c b/src/platform/posix/posix_thread.c index f5cad7a9..0c928d84 100644 --- a/src/platform/posix/posix_thread.c +++ b/src/platform/posix/posix_thread.c @@ -31,6 +31,9 @@ static int nni_plat_inited = 0; static int nni_plat_forked = 0; static int nni_plat_next = 0; +pthread_condattr_t nni_cvattr; +pthread_mutexattr_t nni_mxattr; + uint32_t nni_plat_nextid(void) { @@ -86,6 +89,172 @@ nni_thread_reap(nni_thread *thr) } +int +nni_plat_mtx_init(nni_plat_mtx *mtx) +{ + int rv; + + if ((rv = pthread_mutex_init(&mtx->mtx, &nni_mxattr)) != 0) { + switch (rv) { + case EAGAIN: + case ENOMEM: + return (NNG_ENOMEM); + + default: + nni_panic("pthread_mutex_init: %s", strerror(rv)); + } + } + return (0); +} + + +void +nni_plat_mtx_fini(nni_plat_mtx *mtx) +{ + int rv; + + if ((rv = pthread_mutex_destroy(&mtx->mtx)) != 0) { + nni_panic("pthread_mutex_fini: %s", strerror(rv)); + } +} + + +void +nni_plat_mtx_lock(nni_plat_mtx *mtx) +{ + int rv; + + if ((rv = pthread_mutex_lock(&mtx->mtx)) != 0) { + nni_panic("pthread_mutex_lock: %s", strerror(rv)); + } +} + + +void +nni_plat_mtx_unlock(nni_plat_mtx *mtx) +{ + int rv; + + if ((rv = pthread_mutex_unlock(&mtx->mtx)) != 0) { + nni_panic("pthread_mutex_unlock: %s", strerror(rv)); + } +} + + +int +nni_plat_mtx_trylock(nni_plat_mtx *mtx) +{ + int rv; + + if ((rv = pthread_mutex_trylock(&mtx->mtx)) == EBUSY) { + return (NNG_EBUSY); + } + if (rv != 0) { + nni_panic("pthread_mutex_trylock: %s", strerror(rv)); + } + return (0); +} + + +int +nni_plat_cv_init(nni_plat_cv *cv, nni_plat_mtx *mtx) +{ + int rv; + + if ((rv = pthread_cond_init(&cv->cv, &nni_cvattr)) != 0) { + switch (rv) { + case ENOMEM: + case EAGAIN: + return (NNG_ENOMEM); + + default: + nni_panic("pthread_cond_init: %s", strerror(rv)); + } + } + cv->mtx = &mtx->mtx; + return (0); +} + +void +nni_plat_cv_wake(nni_plat_cv *cv) +{ + int rv; + + if ((rv = pthread_cond_broadcast(&cv->cv)) != 0) { + nni_panic("pthread_cond_broadcast: %s", strerror(rv)); + } +} + +void +nni_plat_cv_wait(nni_plat_cv *cv) +{ + int rv; + + if ((rv = pthread_cond_wait(&cv->cv, cv->mtx)) != 0) { + nni_panic("pthread_cond_wait: %s", strerror(rv)); + } +} + +int +nni_plat_cv_until(nni_plat_cv *cv, nni_time until) +{ + struct timespec ts; + int rv; + + // Our caller has already guaranteed a sane value for until. + ts.tv_sec = until / 1000000; + ts.tv_nsec = (until % 1000000) * 1000; + + rv = pthread_cond_timedwait(&cv->cv, cv->mtx, &ts); + if (rv == ETIMEDOUT) { + if (nni_clock() < until) { + // Buggy pthreads implementation!! Seen with + // CLOCK_MONOTONIC on macOS Sierra. + nni_panic("nni_plat_cv_until: Premature wake up!"); + } + return (NNG_ETIMEDOUT); + } else if (rv != 0) { + nni_panic("pthread_cond_timedwait: %d", rv); + } + return (0); + +} + +void +nni_plat_cv_fini(nni_plat_cv *cv) +{ + int rv; + + if ((rv = pthread_cond_destroy(&cv->cv)) != 0) { + nni_panic("pthread_cond_destroy: %s", strerror(rv)); + } +} + +int +nni_plat_thr_init(nni_plat_thr *thr, void (*fn)(void *), void *arg) +{ + int rv; + + // POSIX wants functions to return a void *, but we don't care. + if ((rv = pthread_create(&thr->tid, NULL, (void *) fn, arg)) != 0) { + //nni_printf("pthread_create: %s", strerror(rv)); + return (NNG_ENOMEM); + } + return (0); +} + + +void +nni_plat_thr_fini(nni_plat_thr *thr) +{ + int rv; + + if ((rv = pthread_join(thr->tid, NULL))) { + nni_panic("pthread_join: %s", strerror(rv)); + } +} + + void nni_atfork_child(void) { @@ -93,8 +262,6 @@ nni_atfork_child(void) } -pthread_condattr_t nni_cvattr; -pthread_mutexattr_t nni_mxattr; int nni_plat_init(int (*helper)(void)) |
