This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PATCH [gcc and libstdc++] for memory barriers in staticinitalization


Here's the version I'm applying.  Only the SPARC support has changed from
my earlier post.

Some other ports may need to define _GLIBCXX_WRITE_MEM_BARRIER if stores
can reach main memory out of order.

2004-12-27  Jason Merrill  <jason@redhat.com>

libstdc++:
	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();

gcc:
	* 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.
	* cp/decl.c (expand_static_init): Don't use shortcut if
	targetm.relaxed_ordering.

*** ./gcc/config/alpha/alpha.c.~1~	2004-12-27 22:50:13.097710878 -0500
--- ./gcc/config/alpha/alpha.c	2004-12-27 23:29:00.430575505 -0500
*************** alpha_init_libfuncs (void)
*** 9462,9467 ****
--- 9462,9473 ----
  #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;
  
  
*** ./gcc/config/ia64/ia64.c.~1~	2004-12-27 22:50:13.110709600 -0500
--- ./gcc/config/ia64/ia64.c	2004-12-23 19:36:09.000000000 -0500
*************** static const struct attribute_spec ia64_
*** 420,425 ****
--- 420,430 ----
  #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
*** ./gcc/config/rs6000/rs6000.c.~1~	2004-12-27 22:50:13.132707437 -0500
--- ./gcc/config/rs6000/rs6000.c	2004-12-27 21:48:38.286456879 -0500
*************** static const char alt_reg_names[][8] =
*** 1004,1009 ****
--- 1004,1020 ----
  #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;
  
  
*** ./gcc/config/sparc/sparc.c.~1~	2004-12-27 22:50:13.144706257 -0500
--- ./gcc/config/sparc/sparc.c	2004-12-27 13:52:30.091957415 -0500
*************** enum processor_type sparc_cpu;
*** 494,499 ****
--- 494,504 ----
  #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
*** ./gcc/cp/decl.c.~1~	2004-12-27 22:50:13.169703799 -0500
--- ./gcc/cp/decl.c	2004-12-27 21:48:41.337160227 -0500
*************** expand_static_init (tree decl, tree init
*** 5313,5320 ****
    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 guard, guard_addr, guard_addr_list;
        tree acquire_fn, release_fn, abort_fn;
        tree flag, begin;
--- 5313,5320 ----
    if (DECL_FUNCTION_SCOPE_P (decl))
      {
        /* Emit code to perform this initialization but once.  */
!       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;
*************** expand_static_init (tree decl, tree init
*** 5353,5362 ****
        /* 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);
  
        if (flag_threadsafe_statics)
  	{
--- 5353,5368 ----
        /* Create the guard variable.  */
        guard = get_guard (decl);
  
!       /* 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)
  	{
*************** expand_static_init (tree decl, tree init
*** 5419,5427 ****
  	  finish_if_stmt (inner_if_stmt);
  	}
  
!       finish_compound_stmt (then_clause);
!       finish_then_clause (if_stmt);
!       finish_if_stmt (if_stmt);
      }
    else
      static_aggregates = tree_cons (init, decl, static_aggregates);
--- 5425,5436 ----
  	  finish_if_stmt (inner_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);
*** ./gcc/doc/tm.texi.~1~	2004-12-27 22:50:13.183702422 -0500
--- ./gcc/doc/tm.texi	2004-12-27 14:31:05.978030663 -0500
*************** If defined, this macro is the number of 
*** 9574,9579 ****
--- 9574,9589 ----
  @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
*** ./gcc/target-def.h.~1~	2004-12-27 22:50:13.082712353 -0500
--- ./gcc/target-def.h	2004-12-27 10:50:26.816420566 -0500
*************** Foundation, 59 Temple Place - Suite 330,
*** 394,399 ****
--- 394,402 ----
  
  #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
  
*************** Foundation, 59 Temple Place - Suite 330,
*** 533,538 ****
--- 536,542 ----
    TARGET_ASM_FILE_START_FILE_DIRECTIVE,		\
    TARGET_HANDLE_PRAGMA_REDEFINE_EXTNAME,	\
    TARGET_HANDLE_PRAGMA_EXTERN_PREFIX,		\
+   TARGET_RELAXED_ORDERING,			\
  }
  
  #include "hooks.h"
*** ./gcc/target.h.~1~	2004-12-27 22:50:13.085712058 -0500
--- ./gcc/target.h	2004-12-27 10:50:26.897412705 -0500
*************** struct gcc_target
*** 598,603 ****
--- 598,607 ----
    /* 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.  */
  };
  
*** ./libstdc++-v3/config/cpu/alpha/atomic_word.h.~1~	2004-12-27 23:27:59.389358367 -0500
--- ./libstdc++-v3/config/cpu/alpha/atomic_word.h	2004-12-23 11:38:55.000000000 -0500
***************
*** 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 
*** ./libstdc++-v3/config/cpu/generic/atomic_word.h.~1~	2004-12-27 22:50:13.194701341 -0500
--- ./libstdc++-v3/config/cpu/generic/atomic_word.h	2004-12-27 14:22:07.214701188 -0500
***************
*** 32,35 ****
--- 32,48 ----
  
  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 
*** ./libstdc++-v3/config/cpu/generic/cxxabi_tweaks.h.~1~	2004-12-27 22:50:13.195701242 -0500
--- ./libstdc++-v3/config/cpu/generic/cxxabi_tweaks.h	2004-12-23 11:39:30.000000000 -0500
*************** namespace __cxxabiv1
*** 36,43 ****
  #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
    __extension__ typedef int __guard __attribute__((mode (__DI__)));
  
    // __cxa_vec_ctor has void return type.
--- 36,43 ----
  #endif
  
    // The generic ABI uses the first byte of a 64-bit guard variable.
! #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.
*** ./libstdc++-v3/config/cpu/ia64/atomic_word.h.~1~	2004-12-27 23:28:15.610822705 -0500
--- ./libstdc++-v3/config/cpu/ia64/atomic_word.h	2004-12-23 14:30:31.000000000 -0500
***************
*** 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 
*** ./libstdc++-v3/config/cpu/powerpc/atomic_word.h.~1~	2004-12-27 23:28:07.441596178 -0500
--- ./libstdc++-v3/config/cpu/powerpc/atomic_word.h	2004-12-23 11:40:21.000000000 -0500
***************
*** 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 
*** ./libstdc++-v3/config/cpu/sparc/atomic_word.h.~1~	2004-12-27 22:50:13.196701144 -0500
--- ./libstdc++-v3/config/cpu/sparc/atomic_word.h	2004-12-27 14:24:21.584570437 -0500
***************
*** 36,39 ****
--- 36,53 ----
    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 
*** ./libstdc++-v3/config/cpu/arm/cxxabi_tweaks.h.~1~	2004-12-27 22:50:13.194701341 -0500
--- ./libstdc++-v3/config/cpu/arm/cxxabi_tweaks.h	2004-09-27 15:39:13.000000000 -0400
*************** namespace __cxxabiv1
*** 38,45 ****
  #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
    typedef int __guard;
  
    // We also want the element size in array cookies.
--- 38,45 ----
  #ifdef __ARM_EABI__
    // The ARM EABI uses the least significant bit of a 32-bit
    // guard variable.  */
! #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.
*************** namespace __cxxabiv1
*** 54,61 ****
  #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
    __extension__ typedef int __guard __attribute__((mode (__DI__)));
  
    // __cxa_vec_ctor has void return type.
--- 54,61 ----
  #else // __ARM_EABI__
  
    // The generic ABI uses the first byte of a 64-bit guard variable.
! #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.
*** ./libstdc++-v3/include/bits/atomicity.h.~1~	2004-12-27 22:50:13.197701046 -0500
--- ./libstdc++-v3/include/bits/atomicity.h	2004-12-23 11:36:29.000000000 -0500
*************** namespace __gnu_cxx
*** 48,51 ****
--- 48,60 ----
    __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 
*** ./libstdc++-v3/libsupc++/guard.cc.~1~	2004-12-27 22:50:13.198700947 -0500
--- ./libstdc++-v3/libsupc++/guard.cc	2004-12-23 11:44:01.000000000 -0500
***************
*** 27,37 ****
--- 27,39 ----
  // 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.
*************** namespace
*** 84,91 ****
--- 86,121 ----
      __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)
*************** namespace __gnu_cxx
*** 107,134 ****
  
  namespace __cxxabiv1 
  {
    static int
    acquire_1 (__guard *g)
    {
!     if (_GLIBCXX_GUARD_ACQUIRE (g))
        {
- 	if (((char *)g)[1]++)
- 	  {
  #ifdef __EXCEPTIONS
! 	    throw __gnu_cxx::recursive_init();
  #else
! 	    abort ();
  #endif
- 	  }
- 	return 1;
        }
!     return 0;
    }
!   
    extern "C"
    int __cxa_guard_acquire (__guard *g) 
    {
  #ifdef __GTHREADS
      if (__gthread_active_p ())
        {
  	// Simple wrapper for exception safety.
--- 137,182 ----
  
  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_TEST (g))
!       return 0;
! 
!     if (recursion_push (g))
        {
  #ifdef __EXCEPTIONS
! 	throw __gnu_cxx::recursive_init();
  #else
! 	// Use __builtin_trap so we don't require abort().
! 	__builtin_trap ();
  #endif
        }
!     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.
*************** namespace __cxxabiv1 
*** 162,168 ****
    extern "C"
    void __cxa_guard_abort (__guard *g)
    {
!     ((char *)g)[1]--;
  #ifdef __GTHREADS
      if (__gthread_active_p ())
        static_mutex::unlock ();
--- 210,216 ----
    extern "C"
    void __cxa_guard_abort (__guard *g)
    {
!     recursion_pop (g);
  #ifdef __GTHREADS
      if (__gthread_active_p ())
        static_mutex::unlock ();
*************** namespace __cxxabiv1 
*** 172,179 ****
    extern "C"
    void __cxa_guard_release (__guard *g)
    {
!     ((char *)g)[1]--;
!     _GLIBCXX_GUARD_RELEASE (g);
  #ifdef __GTHREADS
      if (__gthread_active_p ())
        static_mutex::unlock ();
--- 220,227 ----
    extern "C"
    void __cxa_guard_release (__guard *g)
    {
!     recursion_pop (g);
!     _GLIBCXX_GUARD_SET_AND_RELEASE (g);
  #ifdef __GTHREADS
      if (__gthread_active_p ())
        static_mutex::unlock ();

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]