From b87d9cb50e68da06210a49eedfd01356e127b011 Mon Sep 17 00:00:00 2001 From: David Young Date: Wed, 26 Feb 2020 20:38:57 -0600 Subject: Implement pthread_barrier(3) for Darwin using a counter, condition variable, and mutex. Untested. --- test/thread_id.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/test/thread_id.c b/test/thread_id.c index af36625..4637d9c 100644 --- a/test/thread_id.c +++ b/test/thread_id.c @@ -42,6 +42,129 @@ my_errx(int code, const char *fmt, ...) #if defined(H5_HAVE_THREADSAFE) && !defined(H5_HAVE_WIN_THREADS) +#if defined(H5_HAVE_DARWIN) + +typedef struct _pthread_barrierattr { + uint8_t unused; +} pthread_barrierattr_t; + +typedef struct _pthread_barrier { + uint32_t magic; + unsigned int count; + uint64_t nentered; + pthread_cond_t cv; + pthread_mutex_t mtx; +} pthread_barrier_t; + +int pthread_barrier_init(pthread_barrier_t *, const pthread_barrierattr_t *, + unsigned int); +int pthread_barrier_wait(pthread_barrier_t *); +int pthread_barrier_destroy(pthread_barrier_t *); + +static const uint32_t barrier_magic = 0xf00dd00f; + +int +pthread_barrier_init(pthread_barrier_t *barrier, + const pthread_barrierattr_t *attr, unsigned int count) +{ + int rc; + + if (count == 0) + return EINVAL; + + if (attr != NULL) + return EINVAL; + + memset(barrier, 0, sizeof(*barrier)); + + barrier->count = count; + + if ((rc = pthread_cond_init(&barrier->cv, NULL)) != 0) + return rc; + + if ((rc = pthread_mutex_init(&barrier->mtx, NULL)) != 0) { + (void)pthread_cond_destroy(&barrier->cv); + return rc; + } + + barrier->magic = barrier_magic; + + return 0; +} + +static void +barrier_lock(pthread_barrier_t *barrier) +{ + int rc; + + if ((rc = pthread_mutex_lock(&barrier->mtx)) != 0) { + my_errx(exit_failure, "%s: pthread_mutex_lock: %s", __func__, + strerror(rc)); + } +} + +static void +barrier_unlock(pthread_barrier_t *barrier) +{ + int rc; + + if ((rc = pthread_mutex_unlock(&barrier->mtx)) != 0) { + my_errx(exit_failure, "%s: pthread_mutex_unlock: %s", __func__, + strerror(rc)); + } +} + +int +pthread_barrier_destroy(pthread_barrier_t *barrier) +{ + int rc; + + barrier_lock(barrier); + if (barrier->magic != barrier_magic) + rc = EINVAL; + else if (barrier->count != 0) + rc = EBUSY; + else { + rc = 0; + barrier->magic = ~barrier->magic; + } + barrier_unlock(barrier); + + if (rc != 0) + return rc; + + (void)pthread_cond_destroy(&barrier->cv); + (void)pthread_mutex_destroy(&barrier->mtx); + + return 0; +} + +int +pthread_barrier_wait(pthread_barrier_t *barrier) +{ + int rc; + + if (barrier == NULL) + return EINVAL; + + barrier_lock(barrier); + if (barrier->magic != barrier_magic) { + rc = EINVAL; + goto out; + } + barrier->nentered++; + while (barrier->nentered % barrier->count != 0) { + if ((rc = pthread_cond_wait(&barrier->cv, &barrier->mtx)) != 0) + goto out; + } + rc = pthread_cond_broadcast(&barrier->cv); +out: + barrier_unlock(barrier); + return rc; +} + +#endif /* H5_HAVE_DARWIN */ + static void my_err(int, const char *, ...) H5_ATTR_FORMAT(printf, 2, 3); static void -- cgit v0.12