diff options
Diffstat (limited to 'src/port/pthread_barrier_wait.c')
-rw-r--r-- | src/port/pthread_barrier_wait.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/port/pthread_barrier_wait.c b/src/port/pthread_barrier_wait.c new file mode 100644 index 0000000..9e59b3f --- /dev/null +++ b/src/port/pthread_barrier_wait.c @@ -0,0 +1,77 @@ +/*------------------------------------------------------------------------- + * + * pthread_barrier_wait.c + * Implementation of pthread_barrier_t support for platforms lacking it. + * + * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/port/pthread_barrier_wait.c + * + *------------------------------------------------------------------------- + */ + +#include "c.h" + +#include "port/pg_pthread.h" + +int +pthread_barrier_init(pthread_barrier_t *barrier, const void *attr, int count) +{ + int error; + + barrier->sense = false; + barrier->count = count; + barrier->arrived = 0; + if ((error = pthread_cond_init(&barrier->cond, NULL)) != 0) + return error; + if ((error = pthread_mutex_init(&barrier->mutex, NULL)) != 0) + { + pthread_cond_destroy(&barrier->cond); + return error; + } + + return 0; +} + +int +pthread_barrier_wait(pthread_barrier_t *barrier) +{ + bool initial_sense; + + pthread_mutex_lock(&barrier->mutex); + + /* We have arrived at the barrier. */ + barrier->arrived++; + Assert(barrier->arrived <= barrier->count); + + /* If we were the last to arrive, release the others and return. */ + if (barrier->arrived == barrier->count) + { + barrier->arrived = 0; + barrier->sense = !barrier->sense; + pthread_mutex_unlock(&barrier->mutex); + pthread_cond_broadcast(&barrier->cond); + + return PTHREAD_BARRIER_SERIAL_THREAD; + } + + /* Wait for someone else to flip the sense. */ + initial_sense = barrier->sense; + do + { + pthread_cond_wait(&barrier->cond, &barrier->mutex); + } while (barrier->sense == initial_sense); + + pthread_mutex_unlock(&barrier->mutex); + + return 0; +} + +int +pthread_barrier_destroy(pthread_barrier_t *barrier) +{ + pthread_cond_destroy(&barrier->cond); + pthread_mutex_destroy(&barrier->mutex); + return 0; +} |