summaryrefslogtreecommitdiffstats
path: root/test/thread_id.c
diff options
context:
space:
mode:
authorDavid Young <dyoung@hdfgroup.org>2020-02-27 02:38:57 (GMT)
committerDavid Young <dyoung@hdfgroup.org>2020-02-27 02:38:57 (GMT)
commitb87d9cb50e68da06210a49eedfd01356e127b011 (patch)
tree25576e5231b2b0f3ef0a11402e29f2e7a6f29bad /test/thread_id.c
parent1775d6c9bc86862f120bd39865840ed152c47b0a (diff)
downloadhdf5-b87d9cb50e68da06210a49eedfd01356e127b011.zip
hdf5-b87d9cb50e68da06210a49eedfd01356e127b011.tar.gz
hdf5-b87d9cb50e68da06210a49eedfd01356e127b011.tar.bz2
Implement pthread_barrier(3) for Darwin using a counter, condition variable,
and mutex. Untested.
Diffstat (limited to 'test/thread_id.c')
-rw-r--r--test/thread_id.c123
1 files changed, 123 insertions, 0 deletions
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