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 /sysdeps/sparc | |
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 'sysdeps/sparc')
-rw-r--r-- | sysdeps/sparc/nptl/pthread_barrier_destroy.c | 44 | ||||
-rw-r--r-- | sysdeps/sparc/nptl/pthread_barrier_init.c | 54 | ||||
-rw-r--r-- | sysdeps/sparc/nptl/pthread_barrier_wait.c | 80 | ||||
-rw-r--r-- | sysdeps/sparc/sparc32/pthread_barrier_wait.c | 97 | ||||
-rw-r--r-- | sysdeps/sparc/sparc32/sparcv9/pthread_barrier_wait.c | 2 |
5 files changed, 2 insertions, 275 deletions
diff --git a/sysdeps/sparc/nptl/pthread_barrier_destroy.c b/sysdeps/sparc/nptl/pthread_barrier_destroy.c deleted file mode 100644 index 1a61b357ed..0000000000 --- a/sysdeps/sparc/nptl/pthread_barrier_destroy.c +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright (C) 2002-2016 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <errno.h> -#include "pthreadP.h" -#include <lowlevellock.h> -#include <sparc-nptl.h> - -int -pthread_barrier_destroy (pthread_barrier_t *barrier) -{ - union sparc_pthread_barrier *ibarrier; - int result = EBUSY; - - ibarrier = (union sparc_pthread_barrier *) barrier; - - int private = ibarrier->s.pshared ? LLL_SHARED : LLL_PRIVATE; - - lll_lock (ibarrier->b.lock, private); - - if (__glibc_likely (ibarrier->b.left == ibarrier->b.init_count)) - /* The barrier is not used anymore. */ - result = 0; - else - /* Still used, return with an error. */ - lll_unlock (ibarrier->b.lock, private); - - return result; -} diff --git a/sysdeps/sparc/nptl/pthread_barrier_init.c b/sysdeps/sparc/nptl/pthread_barrier_init.c deleted file mode 100644 index 1bbeb1eaef..0000000000 --- a/sysdeps/sparc/nptl/pthread_barrier_init.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (C) 2002-2016 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <errno.h> -#include "pthreadP.h" -#include <lowlevellock.h> -#include <futex-internal.h> -#include <sparc-nptl.h> - -int -__pthread_barrier_init (pthread_barrier_t *barrier, - const pthread_barrierattr_t *attr, unsigned int count) -{ - union sparc_pthread_barrier *ibarrier; - - if (__glibc_unlikely (count == 0)) - return EINVAL; - - struct pthread_barrierattr *iattr = (struct pthread_barrierattr *) attr; - if (iattr != NULL) - { - int err = futex_supports_pshared (iattr->pshared); - if (err != 0) - return err; - } - - ibarrier = (union sparc_pthread_barrier *) barrier; - - /* Initialize the individual fields. */ - ibarrier->b.lock = LLL_LOCK_INITIALIZER; - ibarrier->b.left = count; - ibarrier->b.init_count = count; - ibarrier->b.curr_event = 0; - ibarrier->s.left_lock = 0; - ibarrier->s.pshared = (iattr && iattr->pshared == PTHREAD_PROCESS_SHARED); - - return 0; -} -weak_alias (__pthread_barrier_init, pthread_barrier_init) diff --git a/sysdeps/sparc/nptl/pthread_barrier_wait.c b/sysdeps/sparc/nptl/pthread_barrier_wait.c deleted file mode 100644 index 55cb1e76b2..0000000000 --- a/sysdeps/sparc/nptl/pthread_barrier_wait.c +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright (C) 2003-2016 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <errno.h> -#include <sysdep.h> -#include <lowlevellock.h> -#include <pthreadP.h> -#include <sparc-nptl.h> -#include <futex-internal.h> - -/* Wait on barrier. */ -int -__pthread_barrier_wait (pthread_barrier_t *barrier) -{ - union sparc_pthread_barrier *ibarrier - = (union sparc_pthread_barrier *) barrier; - int result = 0; - int private = ibarrier->s.pshared ? LLL_SHARED : LLL_PRIVATE; - int futex_private = ibarrier->s.pshared ? FUTEX_SHARED : FUTEX_PRIVATE; - - /* Make sure we are alone. */ - lll_lock (ibarrier->b.lock, private); - - /* One more arrival. */ - --ibarrier->b.left; - - /* Are these all? */ - if (ibarrier->b.left == 0) - { - /* Yes. Increment the event counter to avoid invalid wake-ups and - tell the current waiters that it is their turn. */ - ++ibarrier->b.curr_event; - - /* Wake up everybody. */ - futex_wake (&ibarrier->b.curr_event, INT_MAX, futex_private); - - /* This is the thread which finished the serialization. */ - result = PTHREAD_BARRIER_SERIAL_THREAD; - } - else - { - /* The number of the event we are waiting for. The barrier's event - number must be bumped before we continue. */ - unsigned int event = ibarrier->b.curr_event; - - /* Before suspending, make the barrier available to others. */ - lll_unlock (ibarrier->b.lock, private); - - /* Wait for the event counter of the barrier to change. */ - do - futex_wait_simple (&ibarrier->b.curr_event, event, futex_private); - while (event == ibarrier->b.curr_event); - } - - /* Make sure the init_count is stored locally or in a register. */ - unsigned int init_count = ibarrier->b.init_count; - - /* If this was the last woken thread, unlock. */ - if (atomic_increment_val (&ibarrier->b.left) == init_count) - /* We are done. */ - lll_unlock (ibarrier->b.lock, private); - - return result; -} -weak_alias (__pthread_barrier_wait, pthread_barrier_wait) diff --git a/sysdeps/sparc/sparc32/pthread_barrier_wait.c b/sysdeps/sparc/sparc32/pthread_barrier_wait.c index c61de5f4bd..e5ef911f62 100644 --- a/sysdeps/sparc/sparc32/pthread_barrier_wait.c +++ b/sysdeps/sparc/sparc32/pthread_barrier_wait.c @@ -1,96 +1 @@ -/* Copyright (C) 2003-2016 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <errno.h> -#include <sysdep.h> -#include <lowlevellock.h> -#include <pthreadP.h> -#include <sparc-nptl.h> -#include <futex-internal.h> - -/* Wait on barrier. */ -int -__pthread_barrier_wait (pthread_barrier_t *barrier) -{ - union sparc_pthread_barrier *ibarrier - = (union sparc_pthread_barrier *) barrier; - int result = 0; - int private = ibarrier->s.pshared ? LLL_SHARED : LLL_PRIVATE; - int futex_private = ibarrier->s.pshared ? FUTEX_SHARED : FUTEX_PRIVATE; - - /* Make sure we are alone. */ - lll_lock (ibarrier->b.lock, private); - - /* One more arrival. */ - --ibarrier->b.left; - - /* Are these all? */ - if (ibarrier->b.left == 0) - { - /* Yes. Increment the event counter to avoid invalid wake-ups and - tell the current waiters that it is their turn. */ - ++ibarrier->b.curr_event; - - /* Wake up everybody. */ - futex_wake (&ibarrier->b.curr_event, INT_MAX, futex_private); - - /* This is the thread which finished the serialization. */ - result = PTHREAD_BARRIER_SERIAL_THREAD; - } - else - { - /* The number of the event we are waiting for. The barrier's event - number must be bumped before we continue. */ - unsigned int event = ibarrier->b.curr_event; - - /* Before suspending, make the barrier available to others. */ - lll_unlock (ibarrier->b.lock, private); - - /* Wait for the event counter of the barrier to change. */ - do - futex_wait_simple (&ibarrier->b.curr_event, event, futex_private); - while (event == ibarrier->b.curr_event); - } - - /* Make sure the init_count is stored locally or in a register. */ - unsigned int init_count = ibarrier->b.init_count; - - /* If this was the last woken thread, unlock. */ - if (__atomic_is_v9 || ibarrier->s.pshared == 0) - { - if (atomic_increment_val (&ibarrier->b.left) == init_count) - /* We are done. */ - lll_unlock (ibarrier->b.lock, private); - } - else - { - unsigned int left; - /* Slightly more complicated. On pre-v9 CPUs, atomic_increment_val - is only atomic for threads within the same process, not for - multiple processes. */ - __sparc32_atomic_do_lock24 (&ibarrier->s.left_lock); - left = ++ibarrier->b.left; - __sparc32_atomic_do_unlock24 (&ibarrier->s.left_lock); - if (left == init_count) - /* We are done. */ - lll_unlock (ibarrier->b.lock, private); - } - - return result; -} -weak_alias (__pthread_barrier_wait, pthread_barrier_wait) +#error No support for pthread barriers on pre-v9 sparc. diff --git a/sysdeps/sparc/sparc32/sparcv9/pthread_barrier_wait.c b/sysdeps/sparc/sparc32/sparcv9/pthread_barrier_wait.c index 8336f5e00c..246c8d49de 100644 --- a/sysdeps/sparc/sparc32/sparcv9/pthread_barrier_wait.c +++ b/sysdeps/sparc/sparc32/sparcv9/pthread_barrier_wait.c @@ -1 +1 @@ -#include <sysdeps/sparc/nptl/pthread_barrier_wait.c> +#include <nptl/pthread_barrier_wait.c> |