diff options
author | Torvald Riegel <triegel@redhat.com> | 2015-06-24 14:37:32 +0200 |
---|---|---|
committer | Torvald Riegel <triegel@redhat.com> | 2016-01-15 21:20:34 +0100 |
commit | b02840bacdefde318d2ad2f920e50785b9b25d69 (patch) | |
tree | dcf8ee01d1e4bdb42686d890c1d00bf3249fbcaf /nptl/pthread_barrier_init.c | |
parent | a3e5b4feeb54cb92657ec2bc6d9be1fcef9e8575 (diff) | |
download | glibc-b02840bacdefde318d2ad2f920e50785b9b25d69.tar.gz glibc-b02840bacdefde318d2ad2f920e50785b9b25d69.tar.xz glibc-b02840bacdefde318d2ad2f920e50785b9b25d69.zip |
New pthread_barrier algorithm to fulfill barrier destruction requirements.
The previous barrier implementation did not fulfill the POSIX requirements for when a barrier can be destroyed. Specifically, it was possible that threads that haven't noticed yet that their round is complete still access the barrier's memory, and that those accesses can happen after the barrier has been legally destroyed. The new algorithm does not have this issue, and it avoids using a lock internally.
Diffstat (limited to 'nptl/pthread_barrier_init.c')
-rw-r--r-- | nptl/pthread_barrier_init.c | 23 |
1 files changed, 11 insertions, 12 deletions
diff --git a/nptl/pthread_barrier_init.c b/nptl/pthread_barrier_init.c index ef14ed385a..8f89df12ca 100644 --- a/nptl/pthread_barrier_init.c +++ b/nptl/pthread_barrier_init.c @@ -18,7 +18,7 @@ #include <errno.h> #include "pthreadP.h" -#include <lowlevellock.h> +#include <futex-internal.h> #include <kernel-features.h> @@ -34,8 +34,10 @@ __pthread_barrier_init (pthread_barrier_t *barrier, { struct pthread_barrier *ibarrier; - /* XXX EINVAL is not specified by POSIX as a possible error code. */ - if (__glibc_unlikely (count == 0)) + /* XXX EINVAL is not specified by POSIX as a possible error code for COUNT + being too large. See pthread_barrier_wait for the reason for the + comparison with BARRIER_IN_THRESHOLD. */ + if (__glibc_unlikely (count == 0 || count >= BARRIER_IN_THRESHOLD)) return EINVAL; const struct pthread_barrierattr *iattr @@ -46,15 +48,12 @@ __pthread_barrier_init (pthread_barrier_t *barrier, ibarrier = (struct pthread_barrier *) barrier; /* Initialize the individual fields. */ - ibarrier->lock = LLL_LOCK_INITIALIZER; - ibarrier->left = count; - ibarrier->init_count = count; - ibarrier->curr_event = 0; - - /* XXX Don't use FUTEX_SHARED or FUTEX_PRIVATE as long as there are still - assembly implementations that expect the value determined below. */ - ibarrier->private = (iattr->pshared != PTHREAD_PROCESS_PRIVATE - ? 0 : FUTEX_PRIVATE_FLAG); + ibarrier->in = 0; + ibarrier->out = 0; + ibarrier->count = count; + ibarrier->current_round = 0; + ibarrier->shared = (iattr->pshared == PTHREAD_PROCESS_PRIVATE + ? FUTEX_PRIVATE : FUTEX_SHARED); return 0; } |