aboutsummaryrefslogtreecommitdiff
path: root/src/platform
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform')
-rw-r--r--src/platform/posix/posix_impl.h17
-rw-r--r--src/platform/posix/posix_thread.c171
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))