Index: libgomp/config/linux/mutex.h
===================================================================
--- libgomp/config/linux/mutex.h	(revision 181718)
+++ libgomp/config/linux/mutex.h	(working copy)
@@ -33,39 +33,35 @@ 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;
+  __atomic_compare_exchange_4 (mutex, &oldval, 1, false,
+			       MEMMODEL_ACQUIRE, MEMMODEL_RELAXED);
+  if (__builtin_expect (oldval != 0, 0))
+    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_4 (mutex, 0, MEMMODEL_RELEASE);
+  if (__builtin_expect (wait < 0, 0))
+    gomp_mutex_unlock_slow (mutex);
 }
-
 #endif /* GOMP_MUTEX_H */
Index: libgomp/config/linux/mutex.c
===================================================================
--- libgomp/config/linux/mutex.c	(revision 181718)
+++ libgomp/config/linux/mutex.c	(working copy)
@@ -34,25 +34,33 @@ long int gomp_futex_wait = FUTEX_WAIT | 
 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_4 (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);
+	  /* Something changed.  If now unlocked, we're good to go.  */
+	  oldval = 0;
+	  __atomic_compare_exchange_4 (mutex, &oldval, 1, false,
+				       MEMMODEL_ACQUIRE, MEMMODEL_RELAXED);
 	  if (oldval == 0)
 	    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_4 (mutex, -1, MEMMODEL_ACQUIRE)))
+    do_wait (mutex, -1);
 }
 
 void
Index: libgomp/config/linux/omp-lock.h
===================================================================
--- libgomp/config/linux/omp-lock.h	(revision 181718)
+++ libgomp/config/linux/omp-lock.h	(working copy)
@@ -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;
Index: libgomp/config/linux/arm/mutex.h
===================================================================
--- libgomp/config/linux/arm/mutex.h	(revision 181718)
+++ libgomp/config/linux/arm/mutex.h	(working copy)
@@ -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"
Index: libgomp/config/linux/powerpc/mutex.h
===================================================================
--- libgomp/config/linux/powerpc/mutex.h	(revision 181718)
+++ libgomp/config/linux/powerpc/mutex.h	(working copy)
@@ -1,2 +0,0 @@
-/* On PowerPC __sync_lock_test_and_set isn't a full barrier.  */
-#include "config/linux/ia64/mutex.h"
Index: libgomp/config/linux/ia64/mutex.h
===================================================================
--- libgomp/config/linux/ia64/mutex.h	(revision 181718)
+++ libgomp/config/linux/ia64/mutex.h	(working copy)
@@ -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 */
Index: libgomp/config/linux/mips/mutex.h
===================================================================
--- libgomp/config/linux/mips/mutex.h	(revision 181718)
+++ libgomp/config/linux/mips/mutex.h	(working copy)
@@ -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"
