blob: cd7bae8f5d63d8aa12da9e8ce449916ba2975d1e (
plain) (
tree)
|
|
/* 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
}
|