aboutsummaryrefslogtreecommitdiffstats
path: root/barrier.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2024-08-28 16:42:05 +0200
committerMattias Andrée <maandree@kth.se>2024-08-28 16:42:05 +0200
commita24071ae913b223487df78859c8d830f9e69f580 (patch)
treee2ec712cc29461c82cfdd477e8b1ba961b50018d /barrier.c
parentFirst commit (diff)
downloadanysum-a24071ae913b223487df78859c8d830f9e69f580.tar.gz
anysum-a24071ae913b223487df78859c8d830f9e69f580.tar.bz2
anysum-a24071ae913b223487df78859c8d830f9e69f580.tar.xz
Second commit
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'barrier.c')
-rw-r--r--barrier.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/barrier.c b/barrier.c
new file mode 100644
index 0000000..cd7bae8
--- /dev/null
+++ b/barrier.c
@@ -0,0 +1,113 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+void
+barrierwait(pthread_barrier_t *barrier)
+{
+#ifndef SINGLE_THREADED
+ int r = pthread_barrier_wait(barrier);
+ if (r && r != PTHREAD_BARRIER_SERIAL_THREAD) {
+ errno = r;
+ eprintf("pthread_barrier_wait:");
+ }
+#else
+ (void) barrier;
+#endif
+}
+
+
+void
+barriersend(struct barrier_group *group, struct global_data *global, void (*action)(struct algorithm *, struct global_data *))
+{
+ size_t index;
+ global->action = action;
+ if (group->nthreads)
+ barrierwait(&group->barrier);
+ for (index = 0; index < global->nalgorithms; index += group->nthreads + 1U)
+ (*action)(&global->algorithms[index], global);
+ if (group->nthreads)
+ barrierwait(&group->barrier);
+}
+
+
+#ifndef SINGLE_THREADED
+static void *
+slaveloop(void *thread_param)
+{
+ struct thread_data *data = thread_param;
+ void (*action)(struct algorithm *, struct global_data *);
+ size_t index;
+
+ for (;;) {
+ barrierwait(&data->group->barrier);
+ action = data->global->action;
+ if (!action)
+ break;
+ for (index = data->index; index < data->global->nalgorithms; index += data->group->nthreads + 1U)
+ (*action)(&data->global->algorithms[index], data->global);
+ barrierwait(&data->group->barrier);
+ }
+
+ return NULL;
+}
+#endif
+
+
+void
+createbarriergroup(struct barrier_group *group_out, size_t count, struct global_data *global)
+{
+#ifndef SINGLE_THREADED
+ size_t i;
+
+ group_out->nthreads = count - 1U;
+ group_out->threads = NULL;
+ if (!group_out->nthreads)
+ return;
+ group_out->threads = ecalloc(group_out->nthreads, sizeof(*group_out->threads));
+
+ if ((errno = pthread_barrier_init(&group_out->barrier, NULL, (unsigned)count)))
+ eprintf("pthread_barrier_init NULL %u:", (unsigned)count);
+
+ for (i = 0; i < group_out->nthreads; i++) {
+ group_out->threads[i].group = group_out;
+ group_out->threads[i].global = global;
+ group_out->threads[i].index = i + 1U;
+ errno = pthread_create(&group_out->threads[i].thread, NULL, &slaveloop, &group_out->threads[i]);
+ if (errno)
+ eprintf("pthread_create NULL:");
+ }
+#else
+ group_out->nthreads = 0U;
+ group_out->threads = NULL;
+ (void) global;
+ (void) count;
+#endif
+}
+
+
+void
+killbarriergroup(struct barrier_group *group, struct global_data *global)
+{
+#ifndef SINGLE_THREADED
+ size_t i;
+
+ if (!group->nthreads)
+ return;
+
+ global->action = NULL;
+ for (i = 0; i < group->nthreads; i++)
+ group->threads[i].global = global;
+ barrierwait(&group->barrier);
+
+ for (i = 0; i < group->nthreads; i++)
+ if ((errno = pthread_join(group->threads[i].thread, NULL)))
+ weprintf("pthread_join:");
+ pthread_barrier_destroy(&group->barrier);
+
+ free(group->threads);
+#else
+ (void) group;
+ (void) global;
+#endif
+}