diff options
author | amodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-11-30 04:02:53 +0000 |
---|---|---|
committer | amodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-11-30 04:02:53 +0000 |
commit | a28ddb67e7d93f5ba095c28af9a14b991b2cbcfd (patch) | |
tree | f2b455abcdef142ecdfee68c7c0c647af19edcdd /libgomp | |
parent | df17b94dcaa40e7e13e24a2a8ce6984d70254692 (diff) | |
download | gcc-a28ddb67e7d93f5ba095c28af9a14b991b2cbcfd.tar.gz |
* ordered.c (gomp_ordered_sync): Add MEMMODEL_ACQ_REL fence.
* critical.c (GOMP_critical_start): Add MEMMODEL_RELEASE fence.
* config/linux/mutex.h: Use atomic rather than sync builtins.
* config/linux/mutex.c: Likewise. Comment. Use -1 for waiting state.
* config/linux/omp-lock.h: Comment fix.
* config/linux/arm/mutex.h: Delete.
* config/linux/powerpc/mutex.h: Delete.
* config/linux/ia64/mutex.h: Delete.
* config/linux/mips/mutex.h: Delete.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@181832 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgomp')
-rw-r--r-- | libgomp/ChangeLog | 12 | ||||
-rw-r--r-- | libgomp/config/linux/arm/mutex.h | 28 | ||||
-rw-r--r-- | libgomp/config/linux/ia64/mutex.h | 66 | ||||
-rw-r--r-- | libgomp/config/linux/mips/mutex.h | 27 | ||||
-rw-r--r-- | libgomp/config/linux/mutex.c | 19 | ||||
-rw-r--r-- | libgomp/config/linux/mutex.h | 41 | ||||
-rw-r--r-- | libgomp/config/linux/omp-lock.h | 4 | ||||
-rw-r--r-- | libgomp/config/linux/powerpc/mutex.h | 2 | ||||
-rw-r--r-- | libgomp/critical.c | 4 | ||||
-rw-r--r-- | libgomp/ordered.c | 7 |
10 files changed, 54 insertions, 156 deletions
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index e9148f6375f..faa6749d824 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,5 +1,17 @@ 2011-11-30 Alan Modra <amodra@gmail.com> + * ordered.c (gomp_ordered_sync): Add MEMMODEL_ACQ_REL fence. + * critical.c (GOMP_critical_start): Add MEMMODEL_RELEASE fence. + * config/linux/mutex.h: Use atomic rather than sync builtins. + * config/linux/mutex.c: Likewise. Comment. Use -1 for waiting state. + * config/linux/omp-lock.h: Comment fix. + * config/linux/arm/mutex.h: Delete. + * config/linux/powerpc/mutex.h: Delete. + * config/linux/ia64/mutex.h: Delete. + * config/linux/mips/mutex.h: Delete. + +2011-11-30 Alan Modra <amodra@gmail.com> + PR libgomp/51249 * config/linux/sem.h: Rewrite. * config/linux/sem.c: Rewrite. diff --git a/libgomp/config/linux/arm/mutex.h b/libgomp/config/linux/arm/mutex.h deleted file mode 100644 index 30021d54746..00000000000 --- a/libgomp/config/linux/arm/mutex.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (C) 2010 Free Software Foundation, Inc. - Contributed by ARM Ltd. - - This file is part of the GNU OpenMP Library (libgomp). - - Libgomp is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - Libgomp 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 General Public License for - more details. - - Under Section 7 of GPL version 3, you are granted additional - permissions described in the GCC Runtime Library Exception, version - 3.1, as published by the Free Software Foundation. - - You should have received a copy of the GNU General Public License and - a copy of the GCC Runtime Library Exception along with this program; - see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - <http://www.gnu.org/licenses/>. */ - -/* ARM needs the same correct usage of __sync_synchronize and - __sync_lock_test_and_set as ia64. So we just use its mutex.h. */ - -#include "config/linux/ia64/mutex.h" diff --git a/libgomp/config/linux/ia64/mutex.h b/libgomp/config/linux/ia64/mutex.h deleted file mode 100644 index 8a67673df40..00000000000 --- a/libgomp/config/linux/ia64/mutex.h +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (C) 2005, 2008, 2009, 2011 Free Software Foundation, Inc. - Contributed by Richard Henderson <rth@redhat.com>. - - This file is part of the GNU OpenMP Library (libgomp). - - Libgomp is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - Libgomp 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 General Public License for - more details. - - Under Section 7 of GPL version 3, you are granted additional - permissions described in the GCC Runtime Library Exception, version - 3.1, as published by the Free Software Foundation. - - You should have received a copy of the GNU General Public License and - a copy of the GCC Runtime Library Exception along with this program; - see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - <http://www.gnu.org/licenses/>. */ - -/* This is a Linux specific implementation of a mutex synchronization - mechanism for libgomp. This type is private to the library. This - implementation uses atomic instructions and the futex syscall. */ - -#ifndef GOMP_MUTEX_H -#define GOMP_MUTEX_H 1 - -typedef int gomp_mutex_t; - -#define GOMP_MUTEX_INIT_0 1 - -static inline void gomp_mutex_init (gomp_mutex_t *mutex) -{ - *mutex = 0; -} - -extern void gomp_mutex_lock_slow (gomp_mutex_t *mutex, int); -static inline void gomp_mutex_lock (gomp_mutex_t *mutex) -{ - int oldval = __sync_val_compare_and_swap (mutex, 0, 1); - if (__builtin_expect (oldval, 0)) - gomp_mutex_lock_slow (mutex, oldval); -} - -extern void gomp_mutex_unlock_slow (gomp_mutex_t *mutex); - -/* IA64 needs a __sync_synchronize call before __sync_lock_test_and_set - because __sync_lock_test_and_set is not a full memory fence. */ -static inline void gomp_mutex_unlock (gomp_mutex_t *mutex) -{ - int val; - __sync_synchronize (); - val = __sync_lock_test_and_set (mutex, 0); - if (__builtin_expect (val > 1, 0)) - gomp_mutex_unlock_slow (mutex); -} - -static inline void gomp_mutex_destroy (gomp_mutex_t *mutex) -{ -} - -#endif /* GOMP_MUTEX_H */ diff --git a/libgomp/config/linux/mips/mutex.h b/libgomp/config/linux/mips/mutex.h deleted file mode 100644 index 668cc11b29a..00000000000 --- a/libgomp/config/linux/mips/mutex.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright (C) 2009 Free Software Foundation, Inc. - - This file is part of the GNU OpenMP Library (libgomp). - - Libgomp is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - Libgomp 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 General Public License for - more details. - - Under Section 7 of GPL version 3, you are granted additional - permissions described in the GCC Runtime Library Exception, version - 3.1, as published by the Free Software Foundation. - - You should have received a copy of the GNU General Public License and - a copy of the GCC Runtime Library Exception along with this program; - see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - <http://www.gnu.org/licenses/>. */ - -/* MIPS needs the same correct usage of __sync_synchronize and - __sync_lock_test_and_set as ia64. So we just use its mutex.h. */ - -#include "config/linux/ia64/mutex.h" diff --git a/libgomp/config/linux/mutex.c b/libgomp/config/linux/mutex.c index 2574f7be42a..1b84ffb0990 100644 --- a/libgomp/config/linux/mutex.c +++ b/libgomp/config/linux/mutex.c @@ -34,25 +34,32 @@ long int gomp_futex_wait = FUTEX_WAIT | FUTEX_PRIVATE_FLAG; void gomp_mutex_lock_slow (gomp_mutex_t *mutex, int oldval) { + /* First loop spins a while. */ while (oldval == 1) { if (do_spin (mutex, 1)) { - oldval = __sync_lock_test_and_set (mutex, 2); + /* Spin timeout, nothing changed. Set waiting flag. */ + oldval = __atomic_exchange_n (mutex, -1, MEMMODEL_ACQUIRE); if (oldval == 0) return; - futex_wait (mutex, 2); + futex_wait (mutex, -1); break; } else { - oldval = __sync_val_compare_and_swap (mutex, 0, 1); - if (oldval == 0) + /* Something changed. If now unlocked, we're good to go. */ + oldval = 0; + if (__atomic_compare_exchange_n (mutex, &oldval, 1, false, + MEMMODEL_ACQUIRE, MEMMODEL_RELAXED)) return; } } - while ((oldval = __sync_lock_test_and_set (mutex, 2))) - do_wait (mutex, 2); + + /* Second loop waits until mutex is unlocked. We always exit this + loop with wait flag set, so next unlock will awaken a thread. */ + while ((oldval = __atomic_exchange_n (mutex, -1, MEMMODEL_ACQUIRE))) + do_wait (mutex, -1); } void diff --git a/libgomp/config/linux/mutex.h b/libgomp/config/linux/mutex.h index eafb0e76734..912152ec3a1 100644 --- a/libgomp/config/linux/mutex.h +++ b/libgomp/config/linux/mutex.h @@ -33,39 +33,34 @@ typedef int gomp_mutex_t; #define GOMP_MUTEX_INIT_0 1 -static inline void gomp_mutex_init (gomp_mutex_t *mutex) +extern void gomp_mutex_lock_slow (gomp_mutex_t *mutex, int); +extern void gomp_mutex_unlock_slow (gomp_mutex_t *mutex); + +static inline void +gomp_mutex_init (gomp_mutex_t *mutex) { *mutex = 0; } -extern void gomp_mutex_lock_slow (gomp_mutex_t *mutex, int); -static inline void gomp_mutex_lock (gomp_mutex_t *mutex) +static inline void +gomp_mutex_destroy (gomp_mutex_t *mutex) { - int oldval = __sync_val_compare_and_swap (mutex, 0, 1); - if (__builtin_expect (oldval, 0)) - gomp_mutex_lock_slow (mutex, oldval); } -extern void gomp_mutex_unlock_slow (gomp_mutex_t *mutex); -static inline void gomp_mutex_unlock (gomp_mutex_t *mutex) +static inline void +gomp_mutex_lock (gomp_mutex_t *mutex) { - /* Warning: By definition __sync_lock_test_and_set() does not have - proper memory barrier semantics for a mutex unlock operation. - However, this default implementation is written assuming that it - does, which is true for some targets. - - Targets that require additional memory barriers before - __sync_lock_test_and_set to achieve the release semantics of - mutex unlock, are encouraged to include - "config/linux/ia64/mutex.h" in a target specific mutex.h instead - of using this file. */ - int val = __sync_lock_test_and_set (mutex, 0); - if (__builtin_expect (val > 1, 0)) - gomp_mutex_unlock_slow (mutex); + int oldval = 0; + if (!__atomic_compare_exchange_n (mutex, &oldval, 1, false, + MEMMODEL_ACQUIRE, MEMMODEL_RELAXED)) + gomp_mutex_lock_slow (mutex, oldval); } -static inline void gomp_mutex_destroy (gomp_mutex_t *mutex) +static inline void +gomp_mutex_unlock (gomp_mutex_t *mutex) { + int wait = __atomic_exchange_n (mutex, 0, MEMMODEL_RELEASE); + if (__builtin_expect (wait < 0, 0)) + gomp_mutex_unlock_slow (mutex); } - #endif /* GOMP_MUTEX_H */ diff --git a/libgomp/config/linux/omp-lock.h b/libgomp/config/linux/omp-lock.h index e65aff7fce7..2ca7c5e1d60 100644 --- a/libgomp/config/linux/omp-lock.h +++ b/libgomp/config/linux/omp-lock.h @@ -3,8 +3,8 @@ structures without polluting the namespace. When using the Linux futex primitive, non-recursive locks require - only one int. Recursive locks require we identify the owning task - and so require one int and a pointer. */ + one int. Recursive locks require we identify the owning task + and so require in addition one int and a pointer. */ typedef int omp_lock_t; typedef struct { int lock, count; void *owner; } omp_nest_lock_t; diff --git a/libgomp/config/linux/powerpc/mutex.h b/libgomp/config/linux/powerpc/mutex.h deleted file mode 100644 index e64ff077c83..00000000000 --- a/libgomp/config/linux/powerpc/mutex.h +++ /dev/null @@ -1,2 +0,0 @@ -/* On PowerPC __sync_lock_test_and_set isn't a full barrier. */ -#include "config/linux/ia64/mutex.h" diff --git a/libgomp/critical.c b/libgomp/critical.c index daf1ffc2137..414c4221626 100644 --- a/libgomp/critical.c +++ b/libgomp/critical.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005, 2009 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2009, 2011 Free Software Foundation, Inc. Contributed by Richard Henderson <rth@redhat.com>. This file is part of the GNU OpenMP Library (libgomp). @@ -33,6 +33,8 @@ static gomp_mutex_t default_lock; void GOMP_critical_start (void) { + /* There is an implicit flush on entry to a critical region. */ + __atomic_thread_fence (MEMMODEL_RELEASE); gomp_mutex_lock (&default_lock); } diff --git a/libgomp/ordered.c b/libgomp/ordered.c index e5673fe1c08..f84d52eb9ff 100644 --- a/libgomp/ordered.c +++ b/libgomp/ordered.c @@ -207,8 +207,13 @@ gomp_ordered_sync (void) post to our release semaphore. So the two cases are that we will either win the race an momentarily block on the semaphore, or lose the race and find the semaphore already unlocked and so not block. - Either way we get correct results. */ + Either way we get correct results. + However, there is an implicit flush on entry to an ordered region, + so we do need to have a barrier here. If we were taking a lock + this could be MEMMODEL_RELEASE since the acquire would be coverd + by the lock. */ + __atomic_thread_fence (MEMMODEL_ACQ_REL); if (ws->ordered_owner != thr->ts.team_id) { gomp_sem_wait (team->ordered_release[thr->ts.team_id]); |