diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8cc43d3097329f493a010d99cc006c231255a042..6c6860be8dbb75728c345b05ab102e93a39138ab 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2004-12-27  Jason Merrill  <jason@redhat.com>
+
+	* doc/tm.texi (TARGET_RELAXED_ORDERING): Document.
+	* target.h (struct gcc_target): Add relaxed_ordering field.
+	* target-def.h (TARGET_RELAXED_ORDERING): Define default.
+	(TARGET_INITIALIZER): Add it.
+	* config/alpha/alpha.c (TARGET_RELAXED_ORDERING): Define.
+	* config/ia64/ia64.c (TARGET_RELAXED_ORDERING): Define.
+	* config/rs6000/rs6000.c (TARGET_RELAXED_ORDERING): Define.
+	* config/sparc/sparc.c (TARGET_RELAXED_ORDERING): Define.
+
 2004-12-27  Roger Sayle  <roger@eyesopen.com>
 
 	PR driver/16118
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 823cdbc18c4008919269bd545fc1109976ee9001..042ffa6abcc697e21c69cf427112d4a19bb909ab 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -9462,6 +9462,12 @@ alpha_init_libfuncs (void)
 #undef TARGET_BUILD_BUILTIN_VA_LIST
 #define TARGET_BUILD_BUILTIN_VA_LIST alpha_build_builtin_va_list
 
+/* The Alpha architecture does not require sequential consistency.  See
+   http://www.cs.umd.edu/~pugh/java/memoryModel/AlphaReordering.html
+   for an example of how it can be violated in practice.  */
+#undef TARGET_RELAXED_ORDERING
+#define TARGET_RELAXED_ORDERING true
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 64a4e54a56ca207a2192e978bf38dcbf2a7de6a3..332fa9be3ccaa82aaced39af90a2461d17dc42ae 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -420,6 +420,11 @@ static const struct attribute_spec ia64_attribute_table[] =
 #undef TARGET_SCALAR_MODE_SUPPORTED_P
 #define TARGET_SCALAR_MODE_SUPPORTED_P ia64_scalar_mode_supported_p
 
+/* ia64 architecture manual 4.4.7: ... reads, writes, and flushes may occur
+   in an order different from the specified program order.  */
+#undef TARGET_RELAXED_ORDERING
+#define TARGET_RELAXED_ORDERING true
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 typedef enum
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index cf7c8eec816bb4523132c12f264724ad20c4170b..95a7b1619bf7fce9d3c2f4893bbb3d1fa2ae5a17 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1004,6 +1004,17 @@ static const char alt_reg_names[][8] =
 #undef TARGET_VECTOR_MODE_SUPPORTED_P
 #define TARGET_VECTOR_MODE_SUPPORTED_P rs6000_vector_mode_supported_p
 
+/* MPC604EUM 3.5.2 Weak Consistency between Multiple Processors
+   The PowerPC architecture requires only weak consistency among
+   processors--that is, memory accesses between processors need not be
+   sequentially consistent and memory accesses among processors can occur
+   in any order. The ability to order memory accesses weakly provides
+   opportunities for more efficient use of the system bus. Unless a
+   dependency exists, the 604e allows read operations to precede store
+   operations.  */
+#undef TARGET_RELAXED_ORDERING
+#define TARGET_RELAXED_ORDERING true
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 0eff775bbb21c26f840e5f0ca0a0538f7bf9a672..dd83f544b4f7dd64848ab55763e81fa118357223 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -494,6 +494,11 @@ enum processor_type sparc_cpu;
 #define TARGET_ATTRIBUTE_TABLE sparc_attribute_table
 #endif
 
+/* The SPARC v9 architecture defines a relaxed memory ordering model (RMO)
+   which requires this if enabled, though it is never used in userspace,
+   and the Ultra3 processors don't implement it.  */
+#define TARGET_RELAXED_ORDERING TARGET_V9
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Validate and override various options, and do some machine dependent
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a62a61e565c67a4ef095c1d323edf4f0df6b507e..622a0012a13ba1fdd9a2688084c8dac0608c2ba5 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,8 @@
+2004-12-27  Jason Merrill  <jason@redhat.com>
+
+	* decl.c (expand_static_init): Don't use shortcut if
+	targetm.relaxed_ordering.
+
 2004-12-27  Mark Mitchell  <mark@codesourcery.com>
 
 	PR c++/19149
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 991996bc3f56f8d3b5c9ffa242b1df7ed337c591..7a839d7f3bfc9acc0bef302a103ec9142264a26c 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5313,8 +5313,8 @@ expand_static_init (tree decl, tree init)
   if (DECL_FUNCTION_SCOPE_P (decl))
     {
       /* Emit code to perform this initialization but once.  */
-      tree if_stmt, inner_if_stmt = NULL_TREE;
-      tree then_clause, inner_then_clause = NULL_TREE;
+      tree if_stmt = NULL_TREE, inner_if_stmt = NULL_TREE;
+      tree then_clause = NULL_TREE, inner_then_clause = NULL_TREE;
       tree guard, guard_addr, guard_addr_list;
       tree acquire_fn, release_fn, abort_fn;
       tree flag, begin;
@@ -5353,10 +5353,16 @@ expand_static_init (tree decl, tree init)
       /* Create the guard variable.  */
       guard = get_guard (decl);
 
-      /* Begin the conditional initialization.  */
-      if_stmt = begin_if_stmt ();
-      finish_if_stmt_cond (get_guard_cond (guard), if_stmt);
-      then_clause = begin_compound_stmt (BCS_NO_SCOPE);
+      /* This optimization isn't safe on targets with relaxed memory
+	 consistency.  On such targets we force synchronization in
+	 __cxa_guard_acquire.  */
+      if (!targetm.relaxed_ordering || !flag_threadsafe_statics)
+	{
+	  /* Begin the conditional initialization.  */
+	  if_stmt = begin_if_stmt ();
+	  finish_if_stmt_cond (get_guard_cond (guard), if_stmt);
+	  then_clause = begin_compound_stmt (BCS_NO_SCOPE);
+	}
 
       if (flag_threadsafe_statics)
 	{
@@ -5419,9 +5425,12 @@ expand_static_init (tree decl, tree init)
 	  finish_if_stmt (inner_if_stmt);
 	}
 
-      finish_compound_stmt (then_clause);
-      finish_then_clause (if_stmt);
-      finish_if_stmt (if_stmt);
+      if (!targetm.relaxed_ordering || !flag_threadsafe_statics)
+	{
+	  finish_compound_stmt (then_clause);
+	  finish_then_clause (if_stmt);
+	  finish_if_stmt (if_stmt);
+	}
     }
   else
     static_aggregates = tree_cons (init, decl, static_aggregates);
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index fb45a6c8ea3d6b8d29094222a2fedfb72869c039..abcf7071763ecaf14f0ceb6d1fa805c9b06c030e 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -9574,6 +9574,16 @@ If defined, this macro is the number of entries in
 @code{TARGET_FORMAT_TYPES}.
 @end defmac
 
+@deftypefn {Target Hook} bool TARGET_RELAXED_ORDERING
+If set to @code{true}, means that the target's memory model does not
+guarantee that loads which do not depend on one another will access
+main memory in the order of the instruction stream; if ordering is
+important, an explicit memory barrier must be used.  This is true of
+many recent processors which implement a policy of ``relaxed,''
+``weak,'' or ``release'' memory consistency, such as Alpha, PowerPC,
+and ia64.  The default is @code{false}.
+@end deftypefn
+
 @defmac TARGET_USE_JCR_SECTION
 This macro determines whether to use the JCR section to register Java
 classes. By default, TARGET_USE_JCR_SECTION is defined to 1 if both
diff --git a/gcc/target-def.h b/gcc/target-def.h
index 75c949e9e2973bd81c7d193ed5a913ae2b46ade4..cd333c3b5e6ac9cc849640a0032e40a327ca8f07 100644
--- a/gcc/target-def.h
+++ b/gcc/target-def.h
@@ -394,6 +394,9 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 #define TARGET_GIMPLIFY_VA_ARG_EXPR std_gimplify_va_arg_expr
 #define TARGET_PASS_BY_REFERENCE hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false
+
+#define TARGET_RELAXED_ORDERING false
+
 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size_or_pad
 #define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false
 
@@ -533,6 +536,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   TARGET_ASM_FILE_START_FILE_DIRECTIVE,		\
   TARGET_HANDLE_PRAGMA_REDEFINE_EXTNAME,	\
   TARGET_HANDLE_PRAGMA_EXTERN_PREFIX,		\
+  TARGET_RELAXED_ORDERING,			\
 }
 
 #include "hooks.h"
diff --git a/gcc/target.h b/gcc/target.h
index 4f4b49ebb51265bb9c48ce1c9eea81192880e978..9ad460c18c9309c15c178822756447f4fef259c6 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -598,6 +598,10 @@ struct gcc_target
   /* True if #pragma extern_prefix is to be supported.  */
   bool handle_pragma_extern_prefix;
 
+  /* True if the target is allowed to reorder memory accesses unless
+     synchronization is explicitly requested.  */
+  bool relaxed_ordering;
+
   /* Leave the boolean fields at the end.  */
 };
 
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index ba4b65ec707b4f8d0931b26c023b3de832c9363a..da33b5de852ed90cc2eb7f598ce09a8e8b424192 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,31 @@
+2004-12-27  Jason Merrill  <jason@redhat.com>
+
+	Add memory barriers to the double-checked locking used for static
+	initialization.
+	* libsupc++/guard.cc (__test_and_acquire): Define default.
+	(_GLIBCXX_GUARD_TEST_AND_ACQUIRE, __set_and_release) 
+	(_GLIBCXX_GUARD_SET_AND_RELEASE): Likewise.
+	(recursion_push, recursion_pop): New abstraction functions.
+	(__cxa_guard_acquire): Use _GLIBCXX_GUARD_TEST_AND_ACQUIRE.
+	(__cxa_guard_release): Use _GLIBCXX_GUARD_SET_AND_RELEASE.
+	* config/cpu/generic/cxxabi_tweaks.h (_GLIBCXX_GUARD_TEST): Rename
+	from _GLIBCXX_GUARD_ACQUIRE and reverse sense.
+	(_GLIBCXX_GUARD_SET): Rename from _GLIBCXX_GUARD_RELEASE.
+	* config/cpu/arm/cxxabi_tweaks.h: Likewise.
+	* config/cpu/alpha/atomic_word.h (_GLIBCXX_READ_MEM_BARRIER) 
+	(_GLIBCXX_WRITE_MEM_BARRIER): Define.
+	* config/cpu/powerpc/atomic_word.h: Likewise.
+	* config/cpu/sparc/atomic_word.h: Likewise.
+	* config/cpu/generic/atomic_word.h: Define them, commented out.
+	* include/bits/atomicity.h: Define defaults.
+	* config/cpu/ia64/atomic_word.h (__test_and_acquire)
+	(__set_and_release): New inlines.
+	(_GLIBCXX_GUARD_TEST_AND_ACQUIRE): Define.
+	(_GLIBCXX_GUARD_SET_AND_RELEASE): Define.
+
+	* libsupc++/guard.cc (acquire_1): Use __builtin_trap instead of
+	abort();
+
 2004-12-27  Paolo Carlini  <pcarlini@suse.de>
 
 	* include/tr1/type_traits: Rework the _DEFINE_SPEC* macros.
diff --git a/libstdc++-v3/config/cpu/alpha/atomic_word.h b/libstdc++-v3/config/cpu/alpha/atomic_word.h
new file mode 100644
index 0000000000000000000000000000000000000000..254e3d9ecb3053d3ef9cbe9899259fd9f6c47208
--- /dev/null
+++ b/libstdc++-v3/config/cpu/alpha/atomic_word.h
@@ -0,0 +1,38 @@
+// Low-level type for atomic operations -*- C++ -*-
+
+// Copyright (C) 2004 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library 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 2, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+#ifndef _GLIBCXX_ATOMIC_WORD_H
+#define _GLIBCXX_ATOMIC_WORD_H	1
+
+typedef int _Atomic_word;
+
+#define _GLIBCXX_READ_MEM_BARRIER __asm __volatile ("mb":::"memory")
+#define _GLIBCXX_WRITE_MEM_BARRIER __asm __volatile ("wmb":::"memory")
+
+#endif 
diff --git a/libstdc++-v3/config/cpu/arm/cxxabi_tweaks.h b/libstdc++-v3/config/cpu/arm/cxxabi_tweaks.h
index 06c16fa3993bc04cc9daaa4da421474ef4d6018b..39a10436c2e2f8676174668bbd4259bde9d7c88e 100644
--- a/libstdc++-v3/config/cpu/arm/cxxabi_tweaks.h
+++ b/libstdc++-v3/config/cpu/arm/cxxabi_tweaks.h
@@ -38,8 +38,8 @@ namespace __cxxabiv1
 #ifdef __ARM_EABI__
   // The ARM EABI uses the least significant bit of a 32-bit
   // guard variable.  */
-#define _GLIBCXX_GUARD_ACQUIRE(x) (!(*(x) & 1))
-#define _GLIBCXX_GUARD_RELEASE(x) *(x) = 1
+#define _GLIBCXX_GUARD_TEST(x) ((*(x) & 1) != 0)
+#define _GLIBCXX_GUARD_SET(x) *(x) = 1
   typedef int __guard;
 
   // We also want the element size in array cookies.
@@ -54,8 +54,8 @@ namespace __cxxabiv1
 #else // __ARM_EABI__
 
   // The generic ABI uses the first byte of a 64-bit guard variable.
-#define _GLIBCXX_GUARD_ACQUIRE(x) (!*(char *) (x))
-#define _GLIBCXX_GUARD_RELEASE(x) *(char *) (x) = 1
+#define _GLIBCXX_GUARD_TEST(x) (*(char *) (x) != 0)
+#define _GLIBCXX_GUARD_SET(x) *(char *) (x) = 1
   __extension__ typedef int __guard __attribute__((mode (__DI__)));
 
   // __cxa_vec_ctor has void return type.
diff --git a/libstdc++-v3/config/cpu/generic/atomic_word.h b/libstdc++-v3/config/cpu/generic/atomic_word.h
index b46adc2a4743efc75af3f53e4f6b607697625d3b..f03f1ecbce13d7df1dc891e3ec3ca244a3a4a174 100644
--- a/libstdc++-v3/config/cpu/generic/atomic_word.h
+++ b/libstdc++-v3/config/cpu/generic/atomic_word.h
@@ -32,4 +32,17 @@
 
 typedef int _Atomic_word;
 
+// Define these two macros using the appropriate memory barrier for the target.
+// The commented out versions below are the defaults.
+// See ia64/atomic_word.h for an alternative approach.
+
+// This one prevents loads from being hoisted across the barrier;
+// in other words, this is a Load-Load acquire barrier.
+// This is necessary iff TARGET_RELAXED_ORDERING is defined in tm.h.  
+// #define _GLIBCXX_READ_MEM_BARRIER __asm __volatile ("":::"memory")
+
+// This one prevents stores from being sunk across the barrier; in other
+// words, a Store-Store release barrier.
+// #define _GLIBCXX_WRITE_MEM_BARRIER __asm __volatile ("":::"memory")
+
 #endif 
diff --git a/libstdc++-v3/config/cpu/generic/cxxabi_tweaks.h b/libstdc++-v3/config/cpu/generic/cxxabi_tweaks.h
index 5cacb3c5531a20d3028a3a7586d05787c1a0987f..b5808a265dc14d795f439822a4f6d213674c5d28 100644
--- a/libstdc++-v3/config/cpu/generic/cxxabi_tweaks.h
+++ b/libstdc++-v3/config/cpu/generic/cxxabi_tweaks.h
@@ -36,8 +36,8 @@ namespace __cxxabiv1
 #endif
 
   // The generic ABI uses the first byte of a 64-bit guard variable.
-#define _GLIBCXX_GUARD_ACQUIRE(x) (!*(char *) (x))
-#define _GLIBCXX_GUARD_RELEASE(x) *(char *) (x) = 1
+#define _GLIBCXX_GUARD_TEST(x) (*(char *) (x) != 0)
+#define _GLIBCXX_GUARD_SET(x) *(char *) (x) = 1
   __extension__ typedef int __guard __attribute__((mode (__DI__)));
 
   // __cxa_vec_ctor has void return type.
diff --git a/libstdc++-v3/config/cpu/ia64/atomic_word.h b/libstdc++-v3/config/cpu/ia64/atomic_word.h
new file mode 100644
index 0000000000000000000000000000000000000000..2e49e2707368b6063469b548e7d4e3acbc472a45
--- /dev/null
+++ b/libstdc++-v3/config/cpu/ia64/atomic_word.h
@@ -0,0 +1,69 @@
+// Low-level type for atomic operations -*- C++ -*-
+
+// Copyright (C) 2004 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library 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 2, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+#ifndef _GLIBCXX_ATOMIC_WORD_H
+#define _GLIBCXX_ATOMIC_WORD_H	1
+
+#include <cxxabi.h>
+
+typedef int _Atomic_word;
+
+namespace __gnu_cxx
+{
+  // Test the first byte of __g and ensure that no loads are hoisted across
+  // the test.
+  inline bool
+  __test_and_acquire (__cxxabiv1::__guard *__g)
+  {
+    unsigned char __c;
+    unsigned char *__p = reinterpret_cast<unsigned char *>(__g);
+    // ldN.acq is a load with an implied hoist barrier.
+    // would ld8+mask be faster than just doing an ld1?
+    __asm __volatile ("ld1.acq %0 = %1" : "=r"(__c) : "m"(*__p) : "memory");
+    return __c != 0;
+  }
+
+  // Set the first byte of __g to 1 and ensure that no stores are sunk
+  // across the store.
+  inline void
+  __set_and_release (__cxxabiv1::__guard *__g)
+  {
+    unsigned char *__p = reinterpret_cast<unsigned char *>(__g);
+    // stN.rel is a store with an implied sink barrier.
+    // could load word, set flag, and CAS it back
+    __asm __volatile ("st1.rel %0 = %1" : "=m"(*__p) : "r"(1) : "memory");
+  }
+
+  // We don't define the _BARRIER macros on ia64 because the barriers are
+  // included in the test and set, above.
+#define _GLIBCXX_GUARD_TEST_AND_ACQUIRE(G) __gnu_cxx::__test_and_acquire (G)
+#define _GLIBCXX_GUARD_SET_AND_RELEASE(G) __gnu_cxx::__set_and_release (G)
+}
+
+#endif 
diff --git a/libstdc++-v3/config/cpu/powerpc/atomic_word.h b/libstdc++-v3/config/cpu/powerpc/atomic_word.h
new file mode 100644
index 0000000000000000000000000000000000000000..ff418cc540db87c4d9e31a6cd977dab4ba778a4f
--- /dev/null
+++ b/libstdc++-v3/config/cpu/powerpc/atomic_word.h
@@ -0,0 +1,38 @@
+// Low-level type for atomic operations -*- C++ -*-
+
+// Copyright (C) 2004 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library 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 2, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+#ifndef _GLIBCXX_ATOMIC_WORD_H
+#define _GLIBCXX_ATOMIC_WORD_H	1
+
+typedef int _Atomic_word;
+
+#define _GLIBCXX_READ_MEM_BARRIER __asm __volatile ("isync":::"memory")
+#define _GLIBCXX_WRITE_MEM_BARRIER __asm __volatile ("lwsync":::"memory")
+
+#endif 
diff --git a/libstdc++-v3/config/cpu/sparc/atomic_word.h b/libstdc++-v3/config/cpu/sparc/atomic_word.h
index 941fddd2b0e518832ac5914419578998cfc057eb..59b1a2c9df673fc24ebdd5652b148ea4d3a23689 100644
--- a/libstdc++-v3/config/cpu/sparc/atomic_word.h
+++ b/libstdc++-v3/config/cpu/sparc/atomic_word.h
@@ -36,4 +36,18 @@
   typedef int _Atomic_word;
 #endif
 
+#if defined(__sparc_v9__)
+// These are necessary under the V9 RMO model, though it is almost never
+// used in userspace.
+#define _GLIBCXX_READ_MEM_BARRIER \
+  __asm __volatile ("membar #LoadLoad":::"memory")
+#define _GLIBCXX_WRITE_MEM_BARRIER \
+  __asm __volatile ("membar #StoreStore":::"memory")
+
+#elif defined(__sparc_v8__)
+// This is necessary under the PSO model.
+#define _GLIBCXX_WRITE_MEM_BARRIER __asm __volatile ("stbar":::"memory")
+
+#endif
+
 #endif 
diff --git a/libstdc++-v3/include/bits/atomicity.h b/libstdc++-v3/include/bits/atomicity.h
index 932efe931ce3c733e72e662ccef40416157f6871..9ad25e0f34295c595e2f4061ea11184031b403d6 100644
--- a/libstdc++-v3/include/bits/atomicity.h
+++ b/libstdc++-v3/include/bits/atomicity.h
@@ -48,4 +48,13 @@ namespace __gnu_cxx
   __atomic_add(volatile _Atomic_word* __mem, int __val);
 } // namespace __gnu_cxx
 
+/* Even if the CPU doesn't need a memory barrier, we need to ensure that
+   the compiler doesn't reorder memory accesses across the barriers.  */
+#ifndef _GLIBCXX_READ_MEM_BARRIER
+#define _GLIBCXX_READ_MEM_BARRIER __asm __volatile ("":::"memory")
+#endif
+#ifndef _GLIBCXX_WRITE_MEM_BARRIER
+#define _GLIBCXX_WRITE_MEM_BARRIER __asm __volatile ("":::"memory")
+#endif
+
 #endif 
diff --git a/libstdc++-v3/libsupc++/guard.cc b/libstdc++-v3/libsupc++/guard.cc
index a9280bccdc54c548ef915b2aefe7e8f11346b6c7..e9e147037704bcadddc7c17bb4b13f970e505f85 100644
--- a/libstdc++-v3/libsupc++/guard.cc
+++ b/libstdc++-v3/libsupc++/guard.cc
@@ -27,11 +27,13 @@
 // the GNU General Public License.
 
 // Written by Mark Mitchell, CodeSourcery LLC, <mark@codesourcery.com>
+// Thread support written by Jason Merrill, Red Hat Inc. <jason@redhat.com>
 
 #include <cxxabi.h>
 #include <exception>
 #include <bits/c++config.h>
 #include <bits/gthr.h>
+#include <bits/atomicity.h>
 
 // The IA64/generic ABI uses the first byte of the guard variable.
 // The ARM EABI uses the least significant bit.
@@ -84,8 +86,36 @@ namespace
     __gthread_recursive_mutex_unlock (&mutex);
   }
 }
+
+#ifndef _GLIBCXX_GUARD_TEST_AND_ACQUIRE
+inline bool
+__test_and_acquire (__cxxabiv1::__guard *g)
+{
+  bool b = _GLIBCXX_GUARD_TEST (g);
+  _GLIBCXX_READ_MEM_BARRIER;
+  return b;
+}
+#define _GLIBCXX_GUARD_TEST_AND_ACQUIRE(G) __test_and_acquire (G)
 #endif
 
+#ifndef _GLIBCXX_GUARD_SET_AND_RELEASE
+inline void
+__set_and_release (__cxxabiv1::__guard *g)
+{
+  _GLIBCXX_WRITE_MEM_BARRIER;
+  _GLIBCXX_GUARD_SET (g);
+}
+#define _GLIBCXX_GUARD_SET_AND_RELEASE(G) __set_and_release (G)
+#endif
+
+#else /* !__GTHREADS */
+
+#undef _GLIBCXX_GUARD_TEST_AND_ACQUIRE
+#undef _GLIBCXX_GUARD_SET_AND_RELEASE
+#define _GLIBCXX_GUARD_SET_AND_RELEASE(G) _GLIBCXX_GUARD_SET (G)
+
+#endif /* __GTHREADS */
+
 namespace __gnu_cxx
 {
   // 6.7[stmt.dcl]/4: If control re-enters the declaration (recursively)
@@ -107,28 +137,46 @@ namespace __gnu_cxx
 
 namespace __cxxabiv1 
 {
+  static inline int
+  recursion_push (__guard* g)
+  {
+    return ((char *)g)[1]++;
+  }
+
+  static inline void
+  recursion_pop (__guard* g)
+  {
+    --((char *)g)[1];
+  }
+
   static int
   acquire_1 (__guard *g)
   {
-    if (_GLIBCXX_GUARD_ACQUIRE (g))
+    if (_GLIBCXX_GUARD_TEST (g))
+      return 0;
+
+    if (recursion_push (g))
       {
-	if (((char *)g)[1]++)
-	  {
 #ifdef __EXCEPTIONS
-	    throw __gnu_cxx::recursive_init();
+	throw __gnu_cxx::recursive_init();
 #else
-	    abort ();
+	// Use __builtin_trap so we don't require abort().
+	__builtin_trap ();
 #endif
-	  }
-	return 1;
       }
-    return 0;
+    return 1;
   }
-  
+
   extern "C"
   int __cxa_guard_acquire (__guard *g) 
   {
 #ifdef __GTHREADS
+    // If the target can reorder loads, we need to insert a read memory
+    // barrier so that accesses to the guarded variable happen after the
+    // guard test.
+    if (_GLIBCXX_GUARD_TEST_AND_ACQUIRE (g))
+      return 0;
+
     if (__gthread_active_p ())
       {
 	// Simple wrapper for exception safety.
@@ -162,7 +210,7 @@ namespace __cxxabiv1
   extern "C"
   void __cxa_guard_abort (__guard *g)
   {
-    ((char *)g)[1]--;
+    recursion_pop (g);
 #ifdef __GTHREADS
     if (__gthread_active_p ())
       static_mutex::unlock ();
@@ -172,8 +220,8 @@ namespace __cxxabiv1
   extern "C"
   void __cxa_guard_release (__guard *g)
   {
-    ((char *)g)[1]--;
-    _GLIBCXX_GUARD_RELEASE (g);
+    recursion_pop (g);
+    _GLIBCXX_GUARD_SET_AND_RELEASE (g);
 #ifdef __GTHREADS
     if (__gthread_active_p ())
       static_mutex::unlock ();