public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* cxx-mem-model merge [6 of 9] - libstdc++-v3
@ 2011-11-03 23:52 Andrew MacLeod
  2011-11-04 18:17 ` Jeff Law
  2011-11-07  0:54 ` Hans-Peter Nilsson
  0 siblings, 2 replies; 22+ messages in thread
From: Andrew MacLeod @ 2011-11-03 23:52 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 642 bytes --]

These are the changes to libstdc++ to make use of the new atomics.  I 
changed the files to use the new atomics, and bkoz did a shuffling of 
the include file layout to better suit the new c++ approach.

previously, libstdc++ provided a locked implementation in atomic_0.h 
with the theory that eventually it would be used.  The new scheme 
involves leaving non-lock-free implementations to an external library. 
This involved removing the old lock implementation and restructuring 
things now that multiple implementation dont have to be supported.   SO 
a lot fo this is churn... 2 include files deleted and one merged into 
another one..


[-- Attachment #2: libstdc++v3.diff --]
[-- Type: text/plain, Size: 94194 bytes --]

2011-11-02  Andrew MacLeod  <amacleod@redhat.com>

	* include/std/atomic (is_lock_free): Add object pointer to 
	__atomic_is_lock_free.
	* include/bits/atomic_base.h (LOCKFREE_PROP): Add 0 for object ptr.
	(is_lock_free): Add object pointer to __atomic_is_lock_free.

2011-10-27  Benjamin Kosnik  <bkoz@redhat.com>
	    Andrew MacLeod  <amacleod@redhat.com>

	* include/Makefile.am (bits_headers): Remove atomic_0.h, atomic_2.h.
	* include/Makefile.in: Regenerate.
	* src/Makefile.am (sources): Rename atomic.cc to
	compatibility-atomic-c++0x.cc.
	* src/Makefile.in: Regenerate.
	* include/bits/atomic_0.h: Remove.
	* include/bits/atomic_2.h: Incorporate into...
	* include/bits/atomic_base.h: ...this.
	* include/std/atomic: Add generic atomic calls to basic atomic class.
	* src/atomic.cc: Move...
	* src/compatibility-atomic-c++0x.cc: ...here.
	* src/compatibility-c++0x.cc: Tweak.
	* testsuite/29_atomics/atomic/cons/user_pod.cc: Fix.
	* testsuite/29_atomics/atomic/requirements/explicit_instantiation/1.cc:
	  Same.
	* testsuite/29_atomics/headers/atomic/macros.cc: Same.

2011-10-25  Andrew MacLeod  <amacleod@redhat.com>

	* include/bits/atomic_2.h: Rename __atomic_exchange, __atomic_load,
	__atomic_store, and __atomic_compare_exchange to '_n' variant.

2011-10-20  Andrew MacLeod  <amacleod@redhat.com>

	* include/bits/atomic_2.h: Use __atomic_compare_exchange.

2011-10-17  Andrew MacLeod  <amacleod@redhat.com>

	* include/bits/atomic_2.h: Rename __sync_mem to __atomic.

2011-09-16  Andrew MacLeod  <amacleod@redhat.com>

	* include/bits/atomic_2.h (__atomic2): Use new
	__sync_mem routines.


Index: src/atomic.cc
===================================================================
*** src/atomic.cc	(.../trunk/libstdc++-v3)	(revision 180780)
--- src/atomic.cc	(.../branches/cxx-mem-model/libstdc++-v3)	(revision 180832)
***************
*** 1,146 ****
- // Support for atomic operations -*- C++ -*-
- 
- // Copyright (C) 2008, 2009, 2010, 2011
- // 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 3, 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.
- 
- // 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/>.
- 
- #include "gstdint.h"
- #include <atomic>
- #include <mutex>
- 
- #define LOGSIZE 4
- 
- namespace
- {
- #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
-   std::mutex&
-   get_atomic_mutex()
-   {
-     static std::mutex atomic_mutex;
-     return atomic_mutex;
-   }
- #endif
- 
-   std::__atomic_flag_base flag_table[ 1 << LOGSIZE ] =
-     {
-       ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT,
-       ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT,
-       ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT,
-       ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT,
-     };
- } // anonymous namespace
- 
- namespace std _GLIBCXX_VISIBILITY(default)
- {
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
- 
-   namespace __atomic0
-   {
-     bool
-     atomic_flag::test_and_set(memory_order) noexcept
-     {
- #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
-       lock_guard<mutex> __lock(get_atomic_mutex());
- #endif
-       bool result = _M_i;
-       _M_i = true;
-       return result;
-     }
- 
-     void
-     atomic_flag::clear(memory_order) noexcept
-     {
- #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
-       lock_guard<mutex> __lock(get_atomic_mutex());
- #endif
-       _M_i = false;
-     }
- 
-   _GLIBCXX_BEGIN_EXTERN_C
- 
-   bool
-   atomic_flag_test_and_set_explicit(__atomic_flag_base* __a,
- 				    memory_order __m) _GLIBCXX_NOTHROW
-   {
-     atomic_flag* d = static_cast<atomic_flag*>(__a);
-     return d->test_and_set(__m);
-   }
- 
-   void
-   atomic_flag_clear_explicit(__atomic_flag_base* __a,
- 			     memory_order __m) _GLIBCXX_NOTHROW
-   {
-     atomic_flag* d = static_cast<atomic_flag*>(__a);
-     return d->clear(__m);
-   }
- 
-   void
-   __atomic_flag_wait_explicit(__atomic_flag_base* __a,
- 			      memory_order __x) _GLIBCXX_NOTHROW
-   {
-     while (atomic_flag_test_and_set_explicit(__a, __x))
-       { };
-   }
- 
-   _GLIBCXX_CONST __atomic_flag_base*
-   __atomic_flag_for_address(const volatile void* __z) _GLIBCXX_NOTHROW
-   {
-     uintptr_t __u = reinterpret_cast<uintptr_t>(__z);
-     __u += (__u >> 2) + (__u << 4);
-     __u += (__u >> 7) + (__u << 5);
-     __u += (__u >> 17) + (__u << 13);
-     if (sizeof(uintptr_t) > 4)
-       __u += (__u >> 31);
-     __u &= ~((~uintptr_t(0)) << LOGSIZE);
-     return flag_table + __u;
-   }
- 
-   _GLIBCXX_END_EXTERN_C
- 
-   } // namespace __atomic0
- 
- _GLIBCXX_END_NAMESPACE_VERSION
- } // namespace
- 
- 
- // XXX GLIBCXX_ABI Deprecated
- // gcc-4.5.0
- // <atomic> signature changes
- 
- // The rename syntax for default exported names is
- //   asm (".symver name1,exportedname@GLIBCXX_3.4")
- //   asm (".symver name2,exportedname@@GLIBCXX_3.4.5")
- // In the future, GLIBCXX_ABI > 6 should remove all uses of
- // _GLIBCXX_*_SYMVER macros in this file.
- 
- #if defined(_GLIBCXX_SYMVER_GNU) && defined(PIC) \
-     && defined(_GLIBCXX_HAVE_AS_SYMVER_DIRECTIVE) \
-     && defined(_GLIBCXX_HAVE_SYMVER_SYMBOL_RENAMING_RUNTIME_SUPPORT)
- 
- #define _GLIBCXX_ASM_SYMVER(cur, old, version) \
-    asm (".symver " #cur "," #old "@@" #version);
- 
- _GLIBCXX_ASM_SYMVER(_ZNSt9__atomic011atomic_flag5clearESt12memory_order, _ZNVSt9__atomic011atomic_flag5clearESt12memory_order, GLIBCXX_3.4.11)
- 
- _GLIBCXX_ASM_SYMVER(_ZNSt9__atomic011atomic_flag12test_and_setESt12memory_order, _ZNVSt9__atomic011atomic_flag12test_and_setESt12memory_order, GLIBCXX_3.4.11)
- 
- #endif
--- 0 ----
Index: src/Makefile.in
===================================================================
*** src/Makefile.in	(.../trunk/libstdc++-v3)	(revision 180780)
--- src/Makefile.in	(.../branches/cxx-mem-model/libstdc++-v3)	(revision 180832)
*************** am__objects_1 = atomicity.lo codecvt_mem
*** 105,113 ****
  @ENABLE_PARALLEL_TRUE@	compatibility-parallel_list-2.lo
  am__objects_5 = basic_file.lo c++locale.lo $(am__objects_2) \
  	$(am__objects_3) $(am__objects_4)
! am__objects_6 = atomic.lo bitmap_allocator.lo pool_allocator.lo \
! 	mt_allocator.lo codecvt.lo compatibility.lo \
! 	compatibility-c++0x.lo compatibility-debug_list.lo \
  	compatibility-debug_list-2.lo compatibility-list.lo \
  	compatibility-list-2.lo complex_io.lo ctype.lo debug.lo \
  	functexcept.lo functional.lo globals_io.lo hash_c++0x.lo \
--- 105,113 ----
  @ENABLE_PARALLEL_TRUE@	compatibility-parallel_list-2.lo
  am__objects_5 = basic_file.lo c++locale.lo $(am__objects_2) \
  	$(am__objects_3) $(am__objects_4)
! am__objects_6 = bitmap_allocator.lo pool_allocator.lo mt_allocator.lo \
! 	codecvt.lo compatibility.lo compatibility-c++0x.lo \
! 	compatibility-atomic-c++0x.lo compatibility-debug_list.lo \
  	compatibility-debug_list-2.lo compatibility-list.lo \
  	compatibility-list-2.lo complex_io.lo ctype.lo debug.lo \
  	functexcept.lo functional.lo globals_io.lo hash_c++0x.lo \
*************** host_sources_extra = \
*** 407,419 ****
  
  # Sources present in the src directory, always present.
  sources = \
- 	atomic.cc \
  	bitmap_allocator.cc \
  	pool_allocator.cc \
  	mt_allocator.cc \
  	codecvt.cc \
  	compatibility.cc \
  	compatibility-c++0x.cc \
  	compatibility-debug_list.cc \
  	compatibility-debug_list-2.cc \
  	compatibility-list.cc \
--- 407,419 ----
  
  # Sources present in the src directory, always present.
  sources = \
  	bitmap_allocator.cc \
  	pool_allocator.cc \
  	mt_allocator.cc \
  	codecvt.cc \
  	compatibility.cc \
  	compatibility-c++0x.cc \
+ 	compatibility-atomic-c++0x.cc \
  	compatibility-debug_list.cc \
  	compatibility-debug_list-2.cc \
  	compatibility-list.cc \
*************** compatibility-c++0x.lo: compatibility-c+
*** 917,922 ****
--- 917,927 ----
  compatibility-c++0x.o: compatibility-c++0x.cc
  	$(CXXCOMPILE) -std=gnu++0x -c $<
  
+ compatibility-atomic-c++0x.lo: compatibility-atomic-c++0x.cc
+ 	$(LTCXXCOMPILE) -std=gnu++0x -c $<
+ compatibility-atomic-c++0x.o: compatibility-atomic-c++0x.cc
+ 	$(CXXCOMPILE) -std=gnu++0x -c $<
+ 
  functional.lo: functional.cc
  	$(LTCXXCOMPILE) -std=gnu++0x -c $<
  functional.o: functional.cc
*************** limits.lo: limits.cc
*** 937,947 ****
  limits.o: limits.cc
  	$(CXXCOMPILE) -std=gnu++0x -c $<
  
- atomic.lo: atomic.cc
- 	$(LTCXXCOMPILE) -std=gnu++0x -c $<
- atomic.o: atomic.cc
- 	$(CXXCOMPILE) -std=gnu++0x -c $<
- 
  fstream-inst.lo: fstream-inst.cc
  	$(LTCXXCOMPILE) -std=gnu++0x -c $<
  fstream-inst.o: fstream-inst.cc
--- 942,947 ----
Index: src/compatibility-atomic-c++0x.cc
===================================================================
*** src/compatibility-atomic-c++0x.cc	(.../trunk/libstdc++-v3)	(revision 0)
--- src/compatibility-atomic-c++0x.cc	(.../branches/cxx-mem-model/libstdc++-v3)	(revision 180832)
***************
*** 0 ****
--- 1,158 ----
+ // <atomic> compatibility -*- C++ -*-
+ 
+ // Copyright (C) 2008, 2009, 2010, 2011
+ // 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 3, 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.
+ 
+ // 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/>.
+ 
+ #include "gstdint.h"
+ #include <atomic>
+ #include <mutex>
+ 
+ // XXX GLIBCXX_ABI Deprecated
+ // gcc-4.7.0
+ 
+ #define LOGSIZE 4
+ 
+ namespace
+ {
+ #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
+   std::mutex&
+   get_atomic_mutex()
+   {
+     static std::mutex atomic_mutex;
+     return atomic_mutex;
+   }
+ #endif
+ 
+   std::__atomic_flag_base flag_table[ 1 << LOGSIZE ] =
+     {
+       ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT,
+       ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT,
+       ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT,
+       ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT,
+     };
+ } // anonymous namespace
+ 
+ namespace std _GLIBCXX_VISIBILITY(default)
+ {
+ _GLIBCXX_BEGIN_NAMESPACE_VERSION
+ 
+   namespace __atomic0
+   {
+ 
+     struct atomic_flag : public __atomic_flag_base
+     {
+      bool
+      test_and_set(memory_order) noexcept;
+      
+      void
+      clear(memory_order) noexcept;
+     };
+ 
+     bool
+     atomic_flag::test_and_set(memory_order) noexcept
+     {
+ #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
+       lock_guard<mutex> __lock(get_atomic_mutex());
+ #endif
+       bool result = _M_i;
+       _M_i = true;
+       return result;
+     }
+ 
+     void
+     atomic_flag::clear(memory_order) noexcept
+     {
+ #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
+       lock_guard<mutex> __lock(get_atomic_mutex());
+ #endif
+       _M_i = false;
+     }
+   } // namespace __atomic0
+ 
+   _GLIBCXX_BEGIN_EXTERN_C
+ 
+   bool
+   atomic_flag_test_and_set_explicit(__atomic_flag_base* __a,
+ 				    memory_order __m) _GLIBCXX_NOTHROW
+   {
+     atomic_flag* d = static_cast<atomic_flag*>(__a);
+     return d->test_and_set(__m);
+   }
+ 
+   void
+   atomic_flag_clear_explicit(__atomic_flag_base* __a,
+ 			     memory_order __m) _GLIBCXX_NOTHROW
+   {
+     atomic_flag* d = static_cast<atomic_flag*>(__a);
+     return d->clear(__m);
+   }
+ 
+   void
+   __atomic_flag_wait_explicit(__atomic_flag_base* __a,
+ 			      memory_order __x) _GLIBCXX_NOTHROW
+   {
+     while (atomic_flag_test_and_set_explicit(__a, __x))
+       { };
+   }
+ 
+   _GLIBCXX_CONST __atomic_flag_base*
+   __atomic_flag_for_address(const volatile void* __z) _GLIBCXX_NOTHROW
+   {
+     uintptr_t __u = reinterpret_cast<uintptr_t>(__z);
+     __u += (__u >> 2) + (__u << 4);
+     __u += (__u >> 7) + (__u << 5);
+     __u += (__u >> 17) + (__u << 13);
+     if (sizeof(uintptr_t) > 4)
+       __u += (__u >> 31);
+     __u &= ~((~uintptr_t(0)) << LOGSIZE);
+     return flag_table + __u;
+   }
+ 
+   _GLIBCXX_END_EXTERN_C
+ 
+ _GLIBCXX_END_NAMESPACE_VERSION
+ } // namespace std
+ 
+ 
+ // XXX GLIBCXX_ABI Deprecated
+ // gcc-4.5.0
+ // <atomic> signature changes
+ 
+ // The rename syntax for default exported names is
+ //   asm (".symver name1,exportedname@GLIBCXX_3.4")
+ //   asm (".symver name2,exportedname@@GLIBCXX_3.4.5")
+ // In the future, GLIBCXX_ABI > 6 should remove all uses of
+ // _GLIBCXX_*_SYMVER macros in this file.
+ 
+ #if defined(_GLIBCXX_SYMVER_GNU) && defined(PIC) \
+     && defined(_GLIBCXX_HAVE_AS_SYMVER_DIRECTIVE) \
+     && defined(_GLIBCXX_HAVE_SYMVER_SYMBOL_RENAMING_RUNTIME_SUPPORT)
+ 
+ #define _GLIBCXX_ASM_SYMVER(cur, old, version) \
+    asm (".symver " #cur "," #old "@@" #version);
+ 
+ _GLIBCXX_ASM_SYMVER(_ZNSt9__atomic011atomic_flag5clearESt12memory_order, _ZNVSt9__atomic011atomic_flag5clearESt12memory_order, GLIBCXX_3.4.11)
+ 
+ _GLIBCXX_ASM_SYMVER(_ZNSt9__atomic011atomic_flag12test_and_setESt12memory_order, _ZNVSt9__atomic011atomic_flag12test_and_setESt12memory_order, GLIBCXX_3.4.11)
+ 
+ #endif
Index: src/Makefile.am
===================================================================
*** src/Makefile.am	(.../trunk/libstdc++-v3)	(revision 180780)
--- src/Makefile.am	(.../branches/cxx-mem-model/libstdc++-v3)	(revision 180832)
*************** endif
*** 190,202 ****
  
  # Sources present in the src directory, always present.
  sources = \
- 	atomic.cc \
  	bitmap_allocator.cc \
  	pool_allocator.cc \
  	mt_allocator.cc \
  	codecvt.cc \
  	compatibility.cc \
  	compatibility-c++0x.cc \
  	compatibility-debug_list.cc \
  	compatibility-debug_list-2.cc \
  	compatibility-list.cc \
--- 190,202 ----
  
  # Sources present in the src directory, always present.
  sources = \
  	bitmap_allocator.cc \
  	pool_allocator.cc \
  	mt_allocator.cc \
  	codecvt.cc \
  	compatibility.cc \
  	compatibility-c++0x.cc \
+ 	compatibility-atomic-c++0x.cc \
  	compatibility-debug_list.cc \
  	compatibility-debug_list-2.cc \
  	compatibility-list.cc \
*************** compatibility-c++0x.lo: compatibility-c+
*** 323,328 ****
--- 323,333 ----
  compatibility-c++0x.o: compatibility-c++0x.cc
  	$(CXXCOMPILE) -std=gnu++0x -c $<
  
+ compatibility-atomic-c++0x.lo: compatibility-atomic-c++0x.cc
+ 	$(LTCXXCOMPILE) -std=gnu++0x -c $<
+ compatibility-atomic-c++0x.o: compatibility-atomic-c++0x.cc
+ 	$(CXXCOMPILE) -std=gnu++0x -c $<
+ 
  functional.lo: functional.cc
  	$(LTCXXCOMPILE) -std=gnu++0x -c $<
  functional.o: functional.cc
*************** limits.lo: limits.cc
*** 343,353 ****
  limits.o: limits.cc
  	$(CXXCOMPILE) -std=gnu++0x -c $<
  
- atomic.lo: atomic.cc
- 	$(LTCXXCOMPILE) -std=gnu++0x -c $<
- atomic.o: atomic.cc
- 	$(CXXCOMPILE) -std=gnu++0x -c $<
- 
  fstream-inst.lo: fstream-inst.cc
  	$(LTCXXCOMPILE) -std=gnu++0x -c $<
  fstream-inst.o: fstream-inst.cc
--- 348,353 ----
Index: include/Makefile.in
===================================================================
*** include/Makefile.in	(.../trunk/libstdc++-v3)	(revision 180780)
--- include/Makefile.in	(.../branches/cxx-mem-model/libstdc++-v3)	(revision 180832)
*************** bits_headers = \
*** 335,342 ****
  	${bits_srcdir}/alloc_traits.h \
  	${bits_srcdir}/allocator.h \
  	${bits_srcdir}/atomic_base.h \
- 	${bits_srcdir}/atomic_0.h \
- 	${bits_srcdir}/atomic_2.h \
  	${bits_srcdir}/basic_ios.h \
  	${bits_srcdir}/basic_ios.tcc \
  	${bits_srcdir}/basic_string.h \
--- 335,340 ----
Index: include/std/atomic
===================================================================
*** include/std/atomic	(.../trunk/libstdc++-v3)	(revision 180780)
--- include/std/atomic	(.../branches/cxx-mem-model/libstdc++-v3)	(revision 180832)
***************
*** 39,46 ****
  #endif
  
  #include <bits/atomic_base.h>
- #include <bits/atomic_0.h>
- #include <bits/atomic_2.h>
  
  namespace std _GLIBCXX_VISIBILITY(default)
  {
--- 39,44 ----
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
*** 167,235 ****
  
        constexpr atomic(_Tp __i) noexcept : _M_i(__i) { }
  
!       operator _Tp() const noexcept;
  
!       operator _Tp() const volatile noexcept;
  
        _Tp
!       operator=(_Tp __i) noexcept { store(__i); return __i; }
  
        _Tp
!       operator=(_Tp __i) volatile noexcept { store(__i); return __i; }
  
        bool
!       is_lock_free() const noexcept;
  
        bool
!       is_lock_free() const volatile noexcept;
  
        void
!       store(_Tp, memory_order = memory_order_seq_cst) noexcept;
  
        void
!       store(_Tp, memory_order = memory_order_seq_cst) volatile noexcept;
  
        _Tp
!       load(memory_order = memory_order_seq_cst) const noexcept;
  
        _Tp
!       load(memory_order = memory_order_seq_cst) const volatile noexcept;
  
        _Tp
!       exchange(_Tp __i, memory_order = memory_order_seq_cst) noexcept;
  
        _Tp
!       exchange(_Tp __i, memory_order = memory_order_seq_cst) volatile noexcept;
  
        bool
!       compare_exchange_weak(_Tp&, _Tp, memory_order, memory_order) noexcept;
  
        bool
!       compare_exchange_weak(_Tp&, _Tp, memory_order,
! 			    memory_order) volatile noexcept;
  
        bool
!       compare_exchange_weak(_Tp&, _Tp,
! 			    memory_order = memory_order_seq_cst) noexcept;
  
        bool
!       compare_exchange_weak(_Tp&, _Tp,
! 		       memory_order = memory_order_seq_cst) volatile noexcept;
  
        bool
!       compare_exchange_strong(_Tp&, _Tp, memory_order, memory_order) noexcept;
  
        bool
!       compare_exchange_strong(_Tp&, _Tp, memory_order,
! 			      memory_order) volatile noexcept;
  
        bool
!       compare_exchange_strong(_Tp&, _Tp,
! 			      memory_order = memory_order_seq_cst) noexcept;
  
        bool
!       compare_exchange_strong(_Tp&, _Tp,
! 		       memory_order = memory_order_seq_cst) volatile noexcept;
      };
  
  
--- 165,280 ----
  
        constexpr atomic(_Tp __i) noexcept : _M_i(__i) { }
  
!       operator _Tp() const noexcept
!       { return load(); }
  
!       operator _Tp() const volatile noexcept
!       { return load(); }
  
        _Tp
!       operator=(_Tp __i) noexcept 
!       { store(__i); return __i; }
  
        _Tp
!       operator=(_Tp __i) volatile noexcept 
!       { store(__i); return __i; }
  
        bool
!       is_lock_free() const noexcept
!       { return __atomic_is_lock_free(sizeof(_M_i), &_M_i); }
  
        bool
!       is_lock_free() const volatile noexcept
!       { return __atomic_is_lock_free(sizeof(_M_i), &_M_i); }
  
        void
!       store(_Tp __i, memory_order _m = memory_order_seq_cst) noexcept
!       { __atomic_store(&_M_i, &__i, _m); }
  
        void
!       store(_Tp __i, memory_order _m = memory_order_seq_cst) volatile noexcept
!       { __atomic_store(&_M_i, &__i, _m); }
  
        _Tp
!       load(memory_order _m = memory_order_seq_cst) const noexcept
!       { 
!         _Tp tmp;
! 	__atomic_load(&_M_i, &tmp, _m); 
! 	return tmp;
!       }
  
        _Tp
!       load(memory_order _m = memory_order_seq_cst) const volatile noexcept
!       { 
!         _Tp tmp;
! 	__atomic_load(&_M_i, &tmp, _m); 
! 	return tmp;
!       }
  
        _Tp
!       exchange(_Tp __i, memory_order _m = memory_order_seq_cst) noexcept
!       { 
!         _Tp tmp;
! 	__atomic_exchange(&_M_i, &__i, &tmp, _m); 
! 	return tmp;
!       }
  
        _Tp
!       exchange(_Tp __i, 
! 	       memory_order _m = memory_order_seq_cst) volatile noexcept
!       { 
!         _Tp tmp;
! 	__atomic_exchange(&_M_i, &__i, &tmp, _m); 
! 	return tmp;
!       }
  
        bool
!       compare_exchange_weak(_Tp& __e, _Tp __i, memory_order __s, 
! 			    memory_order __f) noexcept
!       {
! 	return __atomic_compare_exchange(&_M_i, &__e, &__i, true, __s, __f); 
!       }
  
        bool
!       compare_exchange_weak(_Tp& __e, _Tp __i, memory_order __s, 
! 			    memory_order __f) volatile noexcept
!       {
! 	return __atomic_compare_exchange(&_M_i, &__e, &__i, true, __s, __f); 
!       }
  
        bool
!       compare_exchange_weak(_Tp& __e, _Tp __i,
! 			    memory_order __m = memory_order_seq_cst) noexcept
!       { return compare_exchange_weak(__e, __i, __m, __m); }
  
        bool
!       compare_exchange_weak(_Tp& __e, _Tp __i,
! 		     memory_order __m = memory_order_seq_cst) volatile noexcept
!       { return compare_exchange_weak(__e, __i, __m, __m); }
  
        bool
!       compare_exchange_strong(_Tp& __e, _Tp __i, memory_order __s, 
! 			      memory_order __f) noexcept
!       {
! 	return __atomic_compare_exchange(&_M_i, &__e, &__i, false, __s, __f); 
!       }
  
        bool
!       compare_exchange_strong(_Tp& __e, _Tp __i, memory_order __s, 
! 			      memory_order __f) volatile noexcept
!       {
! 	return __atomic_compare_exchange(&_M_i, &__e, &__i, false, __s, __f); 
!       }
  
        bool
!       compare_exchange_strong(_Tp& __e, _Tp __i,
! 			       memory_order __m = memory_order_seq_cst) noexcept
!       { return compare_exchange_strong(__e, __i, __m, __m); }
  
        bool
!       compare_exchange_strong(_Tp& __e, _Tp __i,
! 		     memory_order __m = memory_order_seq_cst) volatile noexcept
!       { return compare_exchange_strong(__e, __i, __m, __m); }
      };
  
  
Index: include/bits/atomic_0.h
===================================================================
*** include/bits/atomic_0.h	(.../trunk/libstdc++-v3)	(revision 180780)
--- include/bits/atomic_0.h	(.../branches/cxx-mem-model/libstdc++-v3)	(revision 180832)
***************
*** 1,677 ****
- // -*- C++ -*- header.
- 
- // Copyright (C) 2008, 2009, 2010, 2011
- // 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 3, 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.
- 
- // 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/>.
- 
- /** @file bits/atomic_0.h
-  *  This is an internal header file, included by other library headers.
-  *  Do not attempt to use it directly. @headername{atomic}
-  */
- 
- #ifndef _GLIBCXX_ATOMIC_0_H
- #define _GLIBCXX_ATOMIC_0_H 1
- 
- #pragma GCC system_header
- 
- namespace std _GLIBCXX_VISIBILITY(default)
- {
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
- 
- // 0 == __atomic0 == Never lock-free
- namespace __atomic0
- {
-   _GLIBCXX_BEGIN_EXTERN_C
- 
-   void
-   atomic_flag_clear_explicit(__atomic_flag_base*, memory_order)
-   _GLIBCXX_NOTHROW;
- 
-   void
-   __atomic_flag_wait_explicit(__atomic_flag_base*, memory_order)
-   _GLIBCXX_NOTHROW;
- 
-   _GLIBCXX_CONST __atomic_flag_base*
-   __atomic_flag_for_address(const volatile void* __z) _GLIBCXX_NOTHROW;
- 
-   _GLIBCXX_END_EXTERN_C
- 
-   // Implementation specific defines.
- #define _ATOMIC_MEMBER_ _M_i
- 
-   // Implementation specific defines.
- #define _ATOMIC_LOAD_(__a, __x)						   \
-   ({typedef __typeof__(_ATOMIC_MEMBER_) __i_type;                          \
-     __i_type* __p = &_ATOMIC_MEMBER_;	   				   \
-     __atomic_flag_base* __g = __atomic_flag_for_address(__p);	  	   \
-     __atomic_flag_wait_explicit(__g, __x);				   \
-     __i_type __r = *__p;						   \
-     atomic_flag_clear_explicit(__g, __x);		       		   \
-     __r; })
- 
- #define _ATOMIC_STORE_(__a, __n, __x)					   \
-   ({typedef __typeof__(_ATOMIC_MEMBER_) __i_type;                          \
-     __i_type* __p = &_ATOMIC_MEMBER_;	   				   \
-     __typeof__(__n) __w = (__n);			       		   \
-     __atomic_flag_base* __g = __atomic_flag_for_address(__p);	  	   \
-     __atomic_flag_wait_explicit(__g, __x);				   \
-     *__p = __w;								   \
-     atomic_flag_clear_explicit(__g, __x);		       		   \
-     __w; })
- 
- #define _ATOMIC_MODIFY_(__a, __o, __n, __x)				   \
-   ({typedef __typeof__(_ATOMIC_MEMBER_) __i_type;                          \
-     __i_type* __p = &_ATOMIC_MEMBER_;	   				   \
-     __typeof__(__n) __w = (__n);			       		   \
-     __atomic_flag_base* __g = __atomic_flag_for_address(__p);	  	   \
-     __atomic_flag_wait_explicit(__g, __x);				   \
-     __i_type __r = *__p;		       				   \
-     *__p __o __w;					       		   \
-     atomic_flag_clear_explicit(__g, __x);		       		   \
-     __r; })
- 
- #define _ATOMIC_CMPEXCHNG_(__a, __e, __n, __x)				   \
-   ({typedef __typeof__(_ATOMIC_MEMBER_) __i_type;                          \
-     __i_type* __p = &_ATOMIC_MEMBER_;	   				   \
-     __typeof__(__e) __q = (__e);			       		   \
-     __typeof__(__n) __w = (__n);			       		   \
-     bool __r;						       		   \
-     __atomic_flag_base* __g = __atomic_flag_for_address(__p);	   	   \
-     __atomic_flag_wait_explicit(__g, __x);				   \
-     __i_type __t = *__p;		       				   \
-     if (*__q == __t) 							   \
-       {									   \
- 	*__p = (__i_type)__w;						   \
- 	__r = true;							   \
-       }									   \
-     else { *__q = __t; __r = false; }		       			   \
-     atomic_flag_clear_explicit(__g, __x);		       		   \
-     __r; })
- 
- 
-   /// atomic_flag
-   struct atomic_flag : public __atomic_flag_base
-   {
-     atomic_flag() noexcept = default;
-     ~atomic_flag() noexcept = default;
-     atomic_flag(const atomic_flag&) = delete;
-     atomic_flag& operator=(const atomic_flag&) = delete;
-     atomic_flag& operator=(const atomic_flag&) volatile = delete;
- 
-     // Conversion to ATOMIC_FLAG_INIT.
-     atomic_flag(bool __i) noexcept : __atomic_flag_base({ __i }) { }
- 
-     bool
-     test_and_set(memory_order __m = memory_order_seq_cst) noexcept;
- 
-     bool
-     test_and_set(memory_order __m = memory_order_seq_cst) volatile noexcept;
- 
-     void
-     clear(memory_order __m = memory_order_seq_cst) noexcept;
- 
-     void
-     clear(memory_order __m = memory_order_seq_cst) volatile noexcept;
-   };
- 
- 
-   /// Base class for atomic integrals.
-   //
-   // For each of the integral types, define atomic_[integral type] struct
-   //
-   // atomic_bool     bool
-   // atomic_char     char
-   // atomic_schar    signed char
-   // atomic_uchar    unsigned char
-   // atomic_short    short
-   // atomic_ushort   unsigned short
-   // atomic_int      int
-   // atomic_uint     unsigned int
-   // atomic_long     long
-   // atomic_ulong    unsigned long
-   // atomic_llong    long long
-   // atomic_ullong   unsigned long long
-   // atomic_char16_t char16_t
-   // atomic_char32_t char32_t
-   // atomic_wchar_t  wchar_t
- 
-   // Base type.
-   // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or 8 bytes,
-   // since that is what GCC built-in functions for atomic memory access work on.
-   template<typename _ITp>
-     struct __atomic_base
-     {
-     private:
-       typedef _ITp 	__int_type;
- 
-       __int_type 	_M_i;
- 
-     public:
-       __atomic_base() noexcept = default;
-       ~__atomic_base() noexcept = default;
-       __atomic_base(const __atomic_base&) = delete;
-       __atomic_base& operator=(const __atomic_base&) = delete;
-       __atomic_base& operator=(const __atomic_base&) volatile = delete;
- 
-       // Requires __int_type convertible to _M_base._M_i.
-       constexpr __atomic_base(__int_type __i) noexcept : _M_i (__i) { }
- 
-       operator __int_type() const noexcept
-       { return load(); }
- 
-       operator __int_type() const volatile noexcept
-       { return load(); }
- 
-       __int_type
-       operator=(__int_type __i) noexcept
-       {
- 	store(__i);
- 	return __i;
-       }
- 
-       __int_type
-       operator=(__int_type __i) volatile noexcept
-       {
- 	store(__i);
- 	return __i;
-       }
- 
-       __int_type
-       operator++(int) noexcept
-       { return fetch_add(1); }
- 
-       __int_type
-       operator++(int) volatile noexcept
-       { return fetch_add(1); }
- 
-       __int_type
-       operator--(int) noexcept
-       { return fetch_sub(1); }
- 
-       __int_type
-       operator--(int) volatile noexcept
-       { return fetch_sub(1); }
- 
-       __int_type
-       operator++() noexcept
-       { return fetch_add(1) + 1; }
- 
-       __int_type
-       operator++() volatile noexcept
-       { return fetch_add(1) + 1; }
- 
-       __int_type
-       operator--() noexcept
-       { return fetch_sub(1) - 1; }
- 
-       __int_type
-       operator--() volatile noexcept
-       { return fetch_sub(1) - 1; }
- 
-       __int_type
-       operator+=(__int_type __i) noexcept
-       { return fetch_add(__i) + __i; }
- 
-       __int_type
-       operator+=(__int_type __i) volatile noexcept
-       { return fetch_add(__i) + __i; }
- 
-       __int_type
-       operator-=(__int_type __i) noexcept
-       { return fetch_sub(__i) - __i; }
- 
-       __int_type
-       operator-=(__int_type __i) volatile noexcept
-       { return fetch_sub(__i) - __i; }
- 
-       __int_type
-       operator&=(__int_type __i) noexcept
-       { return fetch_and(__i) & __i; }
- 
-       __int_type
-       operator&=(__int_type __i) volatile noexcept
-       { return fetch_and(__i) & __i; }
- 
-       __int_type
-       operator|=(__int_type __i) noexcept
-       { return fetch_or(__i) | __i; }
- 
-       __int_type
-       operator|=(__int_type __i) volatile noexcept
-       { return fetch_or(__i) | __i; }
- 
-       __int_type
-       operator^=(__int_type __i) noexcept
-       { return fetch_xor(__i) ^ __i; }
- 
-       __int_type
-       operator^=(__int_type __i) volatile noexcept
-       { return fetch_xor(__i) ^ __i; }
- 
-       bool
-       is_lock_free() const noexcept
-       { return false; }
- 
-       bool
-       is_lock_free() const volatile noexcept
-       { return false; }
- 
-       void
-       store(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept
-       {
- 	__glibcxx_assert(__m != memory_order_acquire);
- 	__glibcxx_assert(__m != memory_order_acq_rel);
- 	__glibcxx_assert(__m != memory_order_consume);
- 	_ATOMIC_STORE_(this, __i, __m);
-       }
- 
-       void
-       store(__int_type __i,
- 	    memory_order __m = memory_order_seq_cst) volatile noexcept
-       {
- 	__glibcxx_assert(__m != memory_order_acquire);
- 	__glibcxx_assert(__m != memory_order_acq_rel);
- 	__glibcxx_assert(__m != memory_order_consume);
- 	_ATOMIC_STORE_(this, __i, __m);
-       }
- 
-       __int_type
-       load(memory_order __m = memory_order_seq_cst) const noexcept
-       {
- 	__glibcxx_assert(__m != memory_order_release);
- 	__glibcxx_assert(__m != memory_order_acq_rel);
- 	return _ATOMIC_LOAD_(this, __m);
-       }
- 
-       __int_type
-       load(memory_order __m = memory_order_seq_cst) const volatile noexcept
-       {
- 	__glibcxx_assert(__m != memory_order_release);
- 	__glibcxx_assert(__m != memory_order_acq_rel);
- 	return _ATOMIC_LOAD_(this, __m);
-       }
- 
-       __int_type
-       exchange(__int_type __i,
- 	       memory_order __m = memory_order_seq_cst) noexcept
-       { return _ATOMIC_MODIFY_(this, =, __i, __m); }
- 
-       __int_type
-       exchange(__int_type __i,
- 	       memory_order __m = memory_order_seq_cst) volatile noexcept
-       { return _ATOMIC_MODIFY_(this, =, __i, __m); }
- 
-       bool
-       compare_exchange_weak(__int_type& __i1, __int_type __i2,
- 			    memory_order __m1, memory_order __m2) noexcept
-       {
- 	__glibcxx_assert(__m2 != memory_order_release);
- 	__glibcxx_assert(__m2 != memory_order_acq_rel);
- 	__glibcxx_assert(__m2 <= __m1);
- 	return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
-       }
- 
-       bool
-       compare_exchange_weak(__int_type& __i1, __int_type __i2,
- 			    memory_order __m1,
- 			    memory_order __m2) volatile noexcept
-       {
- 	__glibcxx_assert(__m2 != memory_order_release);
- 	__glibcxx_assert(__m2 != memory_order_acq_rel);
- 	__glibcxx_assert(__m2 <= __m1);
- 	return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
-       }
- 
-       bool
-       compare_exchange_weak(__int_type& __i1, __int_type __i2,
- 			    memory_order __m = memory_order_seq_cst) noexcept
-       {
- 	return compare_exchange_weak(__i1, __i2, __m,
- 				     __calculate_memory_order(__m));
-       }
- 
-       bool
-       compare_exchange_weak(__int_type& __i1, __int_type __i2,
- 		    memory_order __m = memory_order_seq_cst) volatile noexcept
-       {
- 	return compare_exchange_weak(__i1, __i2, __m,
- 				     __calculate_memory_order(__m));
-       }
- 
-       bool
-       compare_exchange_strong(__int_type& __i1, __int_type __i2,
- 			      memory_order __m1, memory_order __m2) noexcept
-       {
- 	__glibcxx_assert(__m2 != memory_order_release);
- 	__glibcxx_assert(__m2 != memory_order_acq_rel);
- 	__glibcxx_assert(__m2 <= __m1);
- 	return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
-       }
- 
-       bool
-       compare_exchange_strong(__int_type& __i1, __int_type __i2,
- 			      memory_order __m1,
- 			      memory_order __m2) volatile noexcept
-       {
- 	__glibcxx_assert(__m2 != memory_order_release);
- 	__glibcxx_assert(__m2 != memory_order_acq_rel);
- 	__glibcxx_assert(__m2 <= __m1);
- 	return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
-       }
- 
-       bool
-       compare_exchange_strong(__int_type& __i1, __int_type __i2,
- 			      memory_order __m = memory_order_seq_cst) noexcept
-       {
- 	return compare_exchange_strong(__i1, __i2, __m,
- 				       __calculate_memory_order(__m));
-       }
- 
-       bool
-       compare_exchange_strong(__int_type& __i1, __int_type __i2,
- 		    memory_order __m = memory_order_seq_cst) volatile noexcept
-       {
- 	return compare_exchange_strong(__i1, __i2, __m,
- 				       __calculate_memory_order(__m));
-       }
- 
-       __int_type
-       fetch_add(__int_type __i,
- 		memory_order __m = memory_order_seq_cst) noexcept
-       { return _ATOMIC_MODIFY_(this, +=, __i, __m); }
- 
-       __int_type
-       fetch_add(__int_type __i,
- 		memory_order __m = memory_order_seq_cst) volatile noexcept
-       { return _ATOMIC_MODIFY_(this, +=, __i, __m); }
- 
-       __int_type
-       fetch_sub(__int_type __i,
- 		memory_order __m = memory_order_seq_cst) noexcept
-       { return _ATOMIC_MODIFY_(this, -=, __i, __m); }
- 
-       __int_type
-       fetch_sub(__int_type __i,
- 		memory_order __m = memory_order_seq_cst) volatile noexcept
-       { return _ATOMIC_MODIFY_(this, -=, __i, __m); }
- 
-       __int_type
-       fetch_and(__int_type __i,
- 		memory_order __m = memory_order_seq_cst) noexcept
-       { return _ATOMIC_MODIFY_(this, &=, __i, __m); }
- 
-       __int_type
-       fetch_and(__int_type __i,
- 		memory_order __m = memory_order_seq_cst) volatile noexcept
-       { return _ATOMIC_MODIFY_(this, &=, __i, __m); }
- 
-       __int_type
-       fetch_or(__int_type __i,
- 	       memory_order __m = memory_order_seq_cst) noexcept
-       { return _ATOMIC_MODIFY_(this, |=, __i, __m); }
- 
-       __int_type
-       fetch_or(__int_type __i,
- 	       memory_order __m = memory_order_seq_cst) volatile noexcept
-       { return _ATOMIC_MODIFY_(this, |=, __i, __m); }
- 
-       __int_type
-       fetch_xor(__int_type __i,
- 		memory_order __m = memory_order_seq_cst) noexcept
-       { return _ATOMIC_MODIFY_(this, ^=, __i, __m); }
- 
-       __int_type
-       fetch_xor(__int_type __i,
- 		memory_order __m = memory_order_seq_cst) volatile noexcept
-       { return _ATOMIC_MODIFY_(this, ^=, __i, __m); }
-     };
- 
- 
-   /// Partial specialization for pointer types.
-   template<typename _PTp>
-     struct __atomic_base<_PTp*>
-     {
-     private:
-       typedef _PTp* 	__return_pointer_type;
-       typedef void* 	__pointer_type;
-       __pointer_type 	_M_i;
- 
-     public:
-       __atomic_base() noexcept = default;
-       ~__atomic_base() noexcept = default;
-       __atomic_base(const __atomic_base&) = delete;
-       __atomic_base& operator=(const __atomic_base&) = delete;
-       __atomic_base& operator=(const __atomic_base&) volatile = delete;
- 
-       // Requires __pointer_type convertible to _M_i.
-       constexpr __atomic_base(__return_pointer_type __p) noexcept
-       : _M_i (__p) { }
- 
-       operator __return_pointer_type() const noexcept
-       { return reinterpret_cast<__return_pointer_type>(load()); }
- 
-       operator __return_pointer_type() const volatile noexcept
-       { return reinterpret_cast<__return_pointer_type>(load()); }
- 
-       __return_pointer_type
-       operator=(__pointer_type __p) noexcept
-       {
- 	store(__p);
- 	return reinterpret_cast<__return_pointer_type>(__p);
-       }
- 
-       __return_pointer_type
-       operator=(__pointer_type __p) volatile noexcept
-       {
- 	store(__p);
- 	return reinterpret_cast<__return_pointer_type>(__p);
-       }
- 
-       __return_pointer_type
-       operator++(int) noexcept
-       { return reinterpret_cast<__return_pointer_type>(fetch_add(1)); }
- 
-       __return_pointer_type
-       operator++(int) volatile noexcept
-       { return reinterpret_cast<__return_pointer_type>(fetch_add(1)); }
- 
-       __return_pointer_type
-       operator--(int) noexcept
-       { return reinterpret_cast<__return_pointer_type>(fetch_sub(1)); }
- 
-       __return_pointer_type
-       operator--(int) volatile noexcept
-       { return reinterpret_cast<__return_pointer_type>(fetch_sub(1)); }
- 
-       __return_pointer_type
-       operator++() noexcept
-       { return reinterpret_cast<__return_pointer_type>(fetch_add(1) + 1); }
- 
-       __return_pointer_type
-       operator++() volatile noexcept
-       { return reinterpret_cast<__return_pointer_type>(fetch_add(1) + 1); }
- 
-       __return_pointer_type
-       operator--() noexcept
-       { return reinterpret_cast<__return_pointer_type>(fetch_sub(1) - 1); }
- 
-       __return_pointer_type
-       operator--() volatile noexcept
-       { return reinterpret_cast<__return_pointer_type>(fetch_sub(1) - 1); }
- 
-       __return_pointer_type
-       operator+=(ptrdiff_t __d) noexcept
-       { return reinterpret_cast<__return_pointer_type>(fetch_add(__d) + __d); }
- 
-       __return_pointer_type
-       operator+=(ptrdiff_t __d) volatile noexcept
-       { return reinterpret_cast<__return_pointer_type>(fetch_add(__d) + __d); }
- 
-       __return_pointer_type
-       operator-=(ptrdiff_t __d) noexcept
-       { return reinterpret_cast<__return_pointer_type>(fetch_sub(__d) - __d); }
- 
-       __return_pointer_type
-       operator-=(ptrdiff_t __d) volatile noexcept
-       { return reinterpret_cast<__return_pointer_type>(fetch_sub(__d) - __d); }
- 
-       bool
-       is_lock_free() const noexcept
-       { return true; }
- 
-       bool
-       is_lock_free() const volatile noexcept
-       { return true; }
- 
-       void
-       store(__pointer_type __p,
- 	    memory_order __m = memory_order_seq_cst) noexcept
-       {
- 	__glibcxx_assert(__m != memory_order_acquire);
- 	__glibcxx_assert(__m != memory_order_acq_rel);
- 	__glibcxx_assert(__m != memory_order_consume);
- 	_ATOMIC_STORE_(this, __p, __m);
-       }
- 
-       void
-       store(__pointer_type __p,
- 	    memory_order __m = memory_order_seq_cst) volatile noexcept
-       {
- 	__glibcxx_assert(__m != memory_order_acquire);
- 	__glibcxx_assert(__m != memory_order_acq_rel);
- 	__glibcxx_assert(__m != memory_order_consume);
- 	volatile __pointer_type* __p2 = &_M_i;
- 	__typeof__(__p) __w = (__p);
- 	__atomic_flag_base* __g = __atomic_flag_for_address(__p2);
- 	__atomic_flag_wait_explicit(__g, __m);
- 	*__p2 = reinterpret_cast<__pointer_type>(__w);
- 	atomic_flag_clear_explicit(__g, __m);
- 	__w;
-       }
- 
-       __return_pointer_type
-       load(memory_order __m = memory_order_seq_cst) const noexcept
-       {
- 	__glibcxx_assert(__m != memory_order_release);
- 	__glibcxx_assert(__m != memory_order_acq_rel);
- 	void* __v = _ATOMIC_LOAD_(this, __m);
- 	return reinterpret_cast<__return_pointer_type>(__v);
-       }
- 
-       __return_pointer_type
-       load(memory_order __m = memory_order_seq_cst) const volatile noexcept
-       {
- 	__glibcxx_assert(__m != memory_order_release);
- 	__glibcxx_assert(__m != memory_order_acq_rel);
- 	void* __v = _ATOMIC_LOAD_(this, __m);
- 	return reinterpret_cast<__return_pointer_type>(__v);
-       }
- 
-       __return_pointer_type
-       exchange(__pointer_type __p,
- 	       memory_order __m = memory_order_seq_cst) noexcept
-       {
- 	void* __v = _ATOMIC_MODIFY_(this, =, __p, __m);
- 	return reinterpret_cast<__return_pointer_type>(__v);
-       }
- 
-       __return_pointer_type
-       exchange(__pointer_type __p,
- 	       memory_order __m = memory_order_seq_cst) volatile noexcept
-       {
- 	volatile __pointer_type* __p2 = &_M_i;
- 	__typeof__(__p) __w = (__p);
- 	__atomic_flag_base* __g = __atomic_flag_for_address(__p2);
- 	__atomic_flag_wait_explicit(__g, __m);
- 	__pointer_type __r = *__p2;
- 	*__p2 = __w;
- 	atomic_flag_clear_explicit(__g, __m);
- 	__r;
- 	return reinterpret_cast<__return_pointer_type>(_M_i);
-       }
- 
-       bool
-       compare_exchange_strong(__return_pointer_type& __rp1, __pointer_type __p2,
- 			      memory_order __m1, memory_order __m2) noexcept
-       {
- 	__glibcxx_assert(__m2 != memory_order_release);
- 	__glibcxx_assert(__m2 != memory_order_acq_rel);
- 	__glibcxx_assert(__m2 <= __m1);
- 	__pointer_type& __p1 = reinterpret_cast<void*&>(__rp1);
- 	return _ATOMIC_CMPEXCHNG_(this, &__p1, __p2, __m1);
-       }
- 
-       bool
-       compare_exchange_strong(__return_pointer_type& __rp1, __pointer_type __p2,
- 			      memory_order __m1,
- 			      memory_order __m2) volatile noexcept
-       {
- 	__glibcxx_assert(__m2 != memory_order_release);
- 	__glibcxx_assert(__m2 != memory_order_acq_rel);
- 	__glibcxx_assert(__m2 <= __m1);
- 	__pointer_type& __p1 = reinterpret_cast<void*&>(__rp1);
- 	return _ATOMIC_CMPEXCHNG_(this, &__p1, __p2, __m1);
-       }
- 
-       __return_pointer_type
-       fetch_add(ptrdiff_t __d,
- 		memory_order __m = memory_order_seq_cst) noexcept
-       {
- 	void* __v = _ATOMIC_MODIFY_(this, +=, __d, __m);
- 	return reinterpret_cast<__return_pointer_type>(__v);
-       }
- 
-       __return_pointer_type
-       fetch_add(ptrdiff_t __d,
- 		memory_order __m = memory_order_seq_cst) volatile noexcept
-       {
- 	void* __v = _ATOMIC_MODIFY_(this, +=, __d, __m);
- 	return reinterpret_cast<__return_pointer_type>(__v);
-       }
- 
-       __return_pointer_type
-       fetch_sub(ptrdiff_t __d,
- 		memory_order __m = memory_order_seq_cst) noexcept
-       {
- 	void* __v = _ATOMIC_MODIFY_(this, -=, __d, __m);
- 	return reinterpret_cast<__return_pointer_type>(__v);
-       }
- 
-       __return_pointer_type
-       fetch_sub(ptrdiff_t __d,
- 		memory_order __m = memory_order_seq_cst) volatile noexcept
-       {
- 	void* __v = _ATOMIC_MODIFY_(this, -=, __d, __m);
- 	return reinterpret_cast<__return_pointer_type>(__v);
-       }
-     };
- 
- #undef _ATOMIC_LOAD_
- #undef _ATOMIC_STORE_
- #undef _ATOMIC_MODIFY_
- #undef _ATOMIC_CMPEXCHNG_
- } // namespace __atomic0
- 
- _GLIBCXX_END_NAMESPACE_VERSION
- } // namespace std
- 
- #endif
--- 0 ----
Index: include/bits/atomic_2.h
===================================================================
*** include/bits/atomic_2.h	(.../trunk/libstdc++-v3)	(revision 180780)
--- include/bits/atomic_2.h	(.../branches/cxx-mem-model/libstdc++-v3)	(revision 180832)
***************
*** 1,685 ****
- // -*- C++ -*- header.
- 
- // Copyright (C) 2008, 2009, 2010, 2011
- // 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 3, 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.
- 
- // 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/>.
- 
- /** @file bits/atomic_2.h
-  *  This is an internal header file, included by other library headers.
-  *  Do not attempt to use it directly. @headername{atomic}
-  */
- 
- #ifndef _GLIBCXX_ATOMIC_2_H
- #define _GLIBCXX_ATOMIC_2_H 1
- 
- #pragma GCC system_header
- 
- namespace std _GLIBCXX_VISIBILITY(default)
- {
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
- 
- // 2 == __atomic2 == Always lock-free
- // Assumed:
- // _GLIBCXX_ATOMIC_BUILTINS_1
- // _GLIBCXX_ATOMIC_BUILTINS_2
- // _GLIBCXX_ATOMIC_BUILTINS_4
- // _GLIBCXX_ATOMIC_BUILTINS_8
- namespace __atomic2
- {
-   /// atomic_flag
-   struct atomic_flag : public __atomic_flag_base
-   {
-     atomic_flag() noexcept = default;
-     ~atomic_flag() noexcept = default;
-     atomic_flag(const atomic_flag&) = delete;
-     atomic_flag& operator=(const atomic_flag&) = delete;
-     atomic_flag& operator=(const atomic_flag&) volatile = delete;
- 
-     // Conversion to ATOMIC_FLAG_INIT.
-     atomic_flag(bool __i) noexcept : __atomic_flag_base({ __i }) { }
- 
-     bool
-     test_and_set(memory_order __m = memory_order_seq_cst) noexcept
-     {
-       // Redundant synchronize if built-in for lock is a full barrier.
-       if (__m != memory_order_acquire && __m != memory_order_acq_rel)
- 	__sync_synchronize();
-       return __sync_lock_test_and_set(&_M_i, 1);
-     }
- 
-     bool
-     test_and_set(memory_order __m = memory_order_seq_cst) volatile noexcept
-     {
-       // Redundant synchronize if built-in for lock is a full barrier.
-       if (__m != memory_order_acquire && __m != memory_order_acq_rel)
- 	__sync_synchronize();
-       return __sync_lock_test_and_set(&_M_i, 1);
-     }
- 
-     void
-     clear(memory_order __m = memory_order_seq_cst) noexcept
-     {
-       __glibcxx_assert(__m != memory_order_consume);
-       __glibcxx_assert(__m != memory_order_acquire);
-       __glibcxx_assert(__m != memory_order_acq_rel);
- 
-       __sync_lock_release(&_M_i);
-       if (__m != memory_order_acquire && __m != memory_order_acq_rel)
- 	__sync_synchronize();
-     }
- 
-     void
-     clear(memory_order __m = memory_order_seq_cst) volatile noexcept
-     {
-       __glibcxx_assert(__m != memory_order_consume);
-       __glibcxx_assert(__m != memory_order_acquire);
-       __glibcxx_assert(__m != memory_order_acq_rel);
- 
-       __sync_lock_release(&_M_i);
-       if (__m != memory_order_acquire && __m != memory_order_acq_rel)
- 	__sync_synchronize();
-     }
-   };
- 
- 
-   /// Base class for atomic integrals.
-   //
-   // For each of the integral types, define atomic_[integral type] struct
-   //
-   // atomic_bool     bool
-   // atomic_char     char
-   // atomic_schar    signed char
-   // atomic_uchar    unsigned char
-   // atomic_short    short
-   // atomic_ushort   unsigned short
-   // atomic_int      int
-   // atomic_uint     unsigned int
-   // atomic_long     long
-   // atomic_ulong    unsigned long
-   // atomic_llong    long long
-   // atomic_ullong   unsigned long long
-   // atomic_char16_t char16_t
-   // atomic_char32_t char32_t
-   // atomic_wchar_t  wchar_t
-   //
-   // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or
-   // 8 bytes, since that is what GCC built-in functions for atomic
-   // memory access expect.
-   template<typename _ITp>
-     struct __atomic_base
-     {
-     private:
-       typedef _ITp 	__int_type;
- 
-       __int_type 	_M_i;
- 
-     public:
-       __atomic_base() noexcept = default;
-       ~__atomic_base() noexcept = default;
-       __atomic_base(const __atomic_base&) = delete;
-       __atomic_base& operator=(const __atomic_base&) = delete;
-       __atomic_base& operator=(const __atomic_base&) volatile = delete;
- 
-       // Requires __int_type convertible to _M_i.
-       constexpr __atomic_base(__int_type __i) noexcept : _M_i (__i) { }
- 
-       operator __int_type() const noexcept
-       { return load(); }
- 
-       operator __int_type() const volatile noexcept
-       { return load(); }
- 
-       __int_type
-       operator=(__int_type __i) noexcept
-       {
- 	store(__i);
- 	return __i;
-       }
- 
-       __int_type
-       operator=(__int_type __i) volatile noexcept
-       {
- 	store(__i);
- 	return __i;
-       }
- 
-       __int_type
-       operator++(int) noexcept
-       { return fetch_add(1); }
- 
-       __int_type
-       operator++(int) volatile noexcept
-       { return fetch_add(1); }
- 
-       __int_type
-       operator--(int) noexcept
-       { return fetch_sub(1); }
- 
-       __int_type
-       operator--(int) volatile noexcept
-       { return fetch_sub(1); }
- 
-       __int_type
-       operator++() noexcept
-       { return __sync_add_and_fetch(&_M_i, 1); }
- 
-       __int_type
-       operator++() volatile noexcept
-       { return __sync_add_and_fetch(&_M_i, 1); }
- 
-       __int_type
-       operator--() noexcept
-       { return __sync_sub_and_fetch(&_M_i, 1); }
- 
-       __int_type
-       operator--() volatile noexcept
-       { return __sync_sub_and_fetch(&_M_i, 1); }
- 
-       __int_type
-       operator+=(__int_type __i) noexcept
-       { return __sync_add_and_fetch(&_M_i, __i); }
- 
-       __int_type
-       operator+=(__int_type __i) volatile noexcept
-       { return __sync_add_and_fetch(&_M_i, __i); }
- 
-       __int_type
-       operator-=(__int_type __i) noexcept
-       { return __sync_sub_and_fetch(&_M_i, __i); }
- 
-       __int_type
-       operator-=(__int_type __i) volatile noexcept
-       { return __sync_sub_and_fetch(&_M_i, __i); }
- 
-       __int_type
-       operator&=(__int_type __i) noexcept
-       { return __sync_and_and_fetch(&_M_i, __i); }
- 
-       __int_type
-       operator&=(__int_type __i) volatile noexcept
-       { return __sync_and_and_fetch(&_M_i, __i); }
- 
-       __int_type
-       operator|=(__int_type __i) noexcept
-       { return __sync_or_and_fetch(&_M_i, __i); }
- 
-       __int_type
-       operator|=(__int_type __i) volatile noexcept
-       { return __sync_or_and_fetch(&_M_i, __i); }
- 
-       __int_type
-       operator^=(__int_type __i) noexcept
-       { return __sync_xor_and_fetch(&_M_i, __i); }
- 
-       __int_type
-       operator^=(__int_type __i) volatile noexcept
-       { return __sync_xor_and_fetch(&_M_i, __i); }
- 
-       bool
-       is_lock_free() const noexcept
-       { return true; }
- 
-       bool
-       is_lock_free() const volatile noexcept
-       { return true; }
- 
-       void
-       store(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept
-       {
- 	__glibcxx_assert(__m != memory_order_acquire);
- 	__glibcxx_assert(__m != memory_order_acq_rel);
- 	__glibcxx_assert(__m != memory_order_consume);
- 
- 	if (__m == memory_order_relaxed)
- 	  _M_i = __i;
- 	else
- 	  {
- 	    // write_mem_barrier();
- 	    _M_i = __i;
- 	    if (__m == memory_order_seq_cst)
- 	      __sync_synchronize();
- 	  }
-       }
- 
-       void
-       store(__int_type __i,
- 	    memory_order __m = memory_order_seq_cst) volatile noexcept
-       {
- 	__glibcxx_assert(__m != memory_order_acquire);
- 	__glibcxx_assert(__m != memory_order_acq_rel);
- 	__glibcxx_assert(__m != memory_order_consume);
- 
- 	if (__m == memory_order_relaxed)
- 	  _M_i = __i;
- 	else
- 	  {
- 	    // write_mem_barrier();
- 	    _M_i = __i;
- 	    if (__m == memory_order_seq_cst)
- 	      __sync_synchronize();
- 	  }
-       }
- 
-       __int_type
-       load(memory_order __m = memory_order_seq_cst) const noexcept
-       {
- 	__glibcxx_assert(__m != memory_order_release);
- 	__glibcxx_assert(__m != memory_order_acq_rel);
- 
- 	__sync_synchronize();
- 	__int_type __ret = _M_i;
- 	__sync_synchronize();
- 	return __ret;
-       }
- 
-       __int_type
-       load(memory_order __m = memory_order_seq_cst) const volatile noexcept
-       {
- 	__glibcxx_assert(__m != memory_order_release);
- 	__glibcxx_assert(__m != memory_order_acq_rel);
- 
- 	__sync_synchronize();
- 	__int_type __ret = _M_i;
- 	__sync_synchronize();
- 	return __ret;
-       }
- 
-       __int_type
-       exchange(__int_type __i,
- 	       memory_order __m = memory_order_seq_cst) noexcept
-       {
- 	// XXX built-in assumes memory_order_acquire.
- 	return __sync_lock_test_and_set(&_M_i, __i);
-       }
- 
- 
-       __int_type
-       exchange(__int_type __i,
- 	       memory_order __m = memory_order_seq_cst) volatile noexcept
-       {
- 	// XXX built-in assumes memory_order_acquire.
- 	return __sync_lock_test_and_set(&_M_i, __i);
-       }
- 
-       bool
-       compare_exchange_weak(__int_type& __i1, __int_type __i2,
- 			    memory_order __m1, memory_order __m2) noexcept
-       { return compare_exchange_strong(__i1, __i2, __m1, __m2); }
- 
-       bool
-       compare_exchange_weak(__int_type& __i1, __int_type __i2,
- 			    memory_order __m1,
- 			    memory_order __m2) volatile noexcept
-       { return compare_exchange_strong(__i1, __i2, __m1, __m2); }
- 
-       bool
-       compare_exchange_weak(__int_type& __i1, __int_type __i2,
- 			    memory_order __m = memory_order_seq_cst) noexcept
-       {
- 	return compare_exchange_weak(__i1, __i2, __m,
- 				     __calculate_memory_order(__m));
-       }
- 
-       bool
-       compare_exchange_weak(__int_type& __i1, __int_type __i2,
- 		   memory_order __m = memory_order_seq_cst) volatile noexcept
-       {
- 	return compare_exchange_weak(__i1, __i2, __m,
- 				     __calculate_memory_order(__m));
-       }
- 
-       bool
-       compare_exchange_strong(__int_type& __i1, __int_type __i2,
- 			      memory_order __m1, memory_order __m2) noexcept
-       {
- 	__glibcxx_assert(__m2 != memory_order_release);
- 	__glibcxx_assert(__m2 != memory_order_acq_rel);
- 	__glibcxx_assert(__m2 <= __m1);
- 
- 	__int_type __i1o = __i1;
- 	__int_type __i1n = __sync_val_compare_and_swap(&_M_i, __i1o, __i2);
- 
- 	// Assume extra stores (of same value) allowed in true case.
- 	__i1 = __i1n;
- 	return __i1o == __i1n;
-       }
- 
-       bool
-       compare_exchange_strong(__int_type& __i1, __int_type __i2,
- 			      memory_order __m1,
- 			      memory_order __m2) volatile noexcept
-       {
- 	__glibcxx_assert(__m2 != memory_order_release);
- 	__glibcxx_assert(__m2 != memory_order_acq_rel);
- 	__glibcxx_assert(__m2 <= __m1);
- 
- 	__int_type __i1o = __i1;
- 	__int_type __i1n = __sync_val_compare_and_swap(&_M_i, __i1o, __i2);
- 
- 	// Assume extra stores (of same value) allowed in true case.
- 	__i1 = __i1n;
- 	return __i1o == __i1n;
-       }
- 
-       bool
-       compare_exchange_strong(__int_type& __i1, __int_type __i2,
- 			      memory_order __m = memory_order_seq_cst) noexcept
-       {
- 	return compare_exchange_strong(__i1, __i2, __m,
- 				       __calculate_memory_order(__m));
-       }
- 
-       bool
-       compare_exchange_strong(__int_type& __i1, __int_type __i2,
- 		 memory_order __m = memory_order_seq_cst) volatile noexcept
-       {
- 	return compare_exchange_strong(__i1, __i2, __m,
- 				       __calculate_memory_order(__m));
-       }
- 
-       __int_type
-       fetch_add(__int_type __i,
- 		memory_order __m = memory_order_seq_cst) noexcept
-       { return __sync_fetch_and_add(&_M_i, __i); }
- 
-       __int_type
-       fetch_add(__int_type __i,
- 		memory_order __m = memory_order_seq_cst) volatile noexcept
-       { return __sync_fetch_and_add(&_M_i, __i); }
- 
-       __int_type
-       fetch_sub(__int_type __i,
- 		memory_order __m = memory_order_seq_cst) noexcept
-       { return __sync_fetch_and_sub(&_M_i, __i); }
- 
-       __int_type
-       fetch_sub(__int_type __i,
- 		memory_order __m = memory_order_seq_cst) volatile noexcept
-       { return __sync_fetch_and_sub(&_M_i, __i); }
- 
-       __int_type
-       fetch_and(__int_type __i,
- 		memory_order __m = memory_order_seq_cst) noexcept
-       { return __sync_fetch_and_and(&_M_i, __i); }
- 
-       __int_type
-       fetch_and(__int_type __i,
- 		memory_order __m = memory_order_seq_cst) volatile noexcept
-       { return __sync_fetch_and_and(&_M_i, __i); }
- 
-       __int_type
-       fetch_or(__int_type __i,
- 	       memory_order __m = memory_order_seq_cst) noexcept
-       { return __sync_fetch_and_or(&_M_i, __i); }
- 
-       __int_type
-       fetch_or(__int_type __i,
- 	       memory_order __m = memory_order_seq_cst) volatile noexcept
-       { return __sync_fetch_and_or(&_M_i, __i); }
- 
-       __int_type
-       fetch_xor(__int_type __i,
- 		memory_order __m = memory_order_seq_cst) noexcept
-       { return __sync_fetch_and_xor(&_M_i, __i); }
- 
-       __int_type
-       fetch_xor(__int_type __i,
- 		memory_order __m = memory_order_seq_cst) volatile noexcept
-       { return __sync_fetch_and_xor(&_M_i, __i); }
-     };
- 
- 
-   /// Partial specialization for pointer types.
-   template<typename _PTp>
-     struct __atomic_base<_PTp*>
-     {
-     private:
-       typedef _PTp* 	__pointer_type;
- 
-       __pointer_type 	_M_p;
- 
-     public:
-       __atomic_base() noexcept = default;
-       ~__atomic_base() noexcept = default;
-       __atomic_base(const __atomic_base&) = delete;
-       __atomic_base& operator=(const __atomic_base&) = delete;
-       __atomic_base& operator=(const __atomic_base&) volatile = delete;
- 
-       // Requires __pointer_type convertible to _M_p.
-       constexpr __atomic_base(__pointer_type __p) noexcept : _M_p (__p) { }
- 
-       operator __pointer_type() const noexcept
-       { return load(); }
- 
-       operator __pointer_type() const volatile noexcept
-       { return load(); }
- 
-       __pointer_type
-       operator=(__pointer_type __p) noexcept
-       {
- 	store(__p);
- 	return __p;
-       }
- 
-       __pointer_type
-       operator=(__pointer_type __p) volatile noexcept
-       {
- 	store(__p);
- 	return __p;
-       }
- 
-       __pointer_type
-       operator++(int) noexcept
-       { return fetch_add(1); }
- 
-       __pointer_type
-       operator++(int) volatile noexcept
-       { return fetch_add(1); }
- 
-       __pointer_type
-       operator--(int) noexcept
-       { return fetch_sub(1); }
- 
-       __pointer_type
-       operator--(int) volatile noexcept
-       { return fetch_sub(1); }
- 
-       __pointer_type
-       operator++() noexcept
-       { return fetch_add(1) + 1; }
- 
-       __pointer_type
-       operator++() volatile noexcept
-       { return fetch_add(1) + 1; }
- 
-       __pointer_type
-       operator--() noexcept
-       { return fetch_sub(1) -1; }
- 
-       __pointer_type
-       operator--() volatile noexcept
-       { return fetch_sub(1) -1; }
- 
-       __pointer_type
-       operator+=(ptrdiff_t __d) noexcept
-       { return fetch_add(__d) + __d; }
- 
-       __pointer_type
-       operator+=(ptrdiff_t __d) volatile noexcept
-       { return fetch_add(__d) + __d; }
- 
-       __pointer_type
-       operator-=(ptrdiff_t __d) noexcept
-       { return fetch_sub(__d) - __d; }
- 
-       __pointer_type
-       operator-=(ptrdiff_t __d) volatile noexcept
-       { return fetch_sub(__d) - __d; }
- 
-       bool
-       is_lock_free() const noexcept
-       { return true; }
- 
-       bool
-       is_lock_free() const volatile noexcept
-       { return true; }
- 
-       void
-       store(__pointer_type __p,
- 	    memory_order __m = memory_order_seq_cst) noexcept
-       {
- 	__glibcxx_assert(__m != memory_order_acquire);
- 	__glibcxx_assert(__m != memory_order_acq_rel);
- 	__glibcxx_assert(__m != memory_order_consume);
- 
- 	if (__m == memory_order_relaxed)
- 	  _M_p = __p;
- 	else
- 	  {
- 	    // write_mem_barrier();
- 	    _M_p = __p;
- 	    if (__m == memory_order_seq_cst)
- 	      __sync_synchronize();
- 	  }
-       }
- 
-       void
-       store(__pointer_type __p,
- 	    memory_order __m = memory_order_seq_cst) volatile noexcept
-       {
- 	__glibcxx_assert(__m != memory_order_acquire);
- 	__glibcxx_assert(__m != memory_order_acq_rel);
- 	__glibcxx_assert(__m != memory_order_consume);
- 
- 	if (__m == memory_order_relaxed)
- 	  _M_p = __p;
- 	else
- 	  {
- 	    // write_mem_barrier();
- 	    _M_p = __p;
- 	    if (__m == memory_order_seq_cst)
- 	      __sync_synchronize();
- 	  }
-       }
- 
-       __pointer_type
-       load(memory_order __m = memory_order_seq_cst) const noexcept
-       {
- 	__glibcxx_assert(__m != memory_order_release);
- 	__glibcxx_assert(__m != memory_order_acq_rel);
- 
- 	__sync_synchronize();
- 	__pointer_type __ret = _M_p;
- 	__sync_synchronize();
- 	return __ret;
-       }
- 
-       __pointer_type
-       load(memory_order __m = memory_order_seq_cst) const volatile noexcept
-       {
- 	__glibcxx_assert(__m != memory_order_release);
- 	__glibcxx_assert(__m != memory_order_acq_rel);
- 
- 	__sync_synchronize();
- 	__pointer_type __ret = _M_p;
- 	__sync_synchronize();
- 	return __ret;
-       }
- 
-       __pointer_type
-       exchange(__pointer_type __p,
- 	       memory_order __m = memory_order_seq_cst) noexcept
-       {
- 	// XXX built-in assumes memory_order_acquire.
- 	return __sync_lock_test_and_set(&_M_p, __p);
-       }
- 
- 
-       __pointer_type
-       exchange(__pointer_type __p,
- 	       memory_order __m = memory_order_seq_cst) volatile noexcept
-       {
- 	// XXX built-in assumes memory_order_acquire.
- 	return __sync_lock_test_and_set(&_M_p, __p);
-       }
- 
-       bool
-       compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2,
- 			      memory_order __m1,
- 			      memory_order __m2) noexcept
-       {
- 	__glibcxx_assert(__m2 != memory_order_release);
- 	__glibcxx_assert(__m2 != memory_order_acq_rel);
- 	__glibcxx_assert(__m2 <= __m1);
- 
- 	__pointer_type __p1o = __p1;
- 	__pointer_type __p1n = __sync_val_compare_and_swap(&_M_p, __p1o, __p2);
- 
- 	// Assume extra stores (of same value) allowed in true case.
- 	__p1 = __p1n;
- 	return __p1o == __p1n;
-       }
- 
-       bool
-       compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2,
- 			      memory_order __m1,
- 			      memory_order __m2) volatile noexcept
-       {
- 	__glibcxx_assert(__m2 != memory_order_release);
- 	__glibcxx_assert(__m2 != memory_order_acq_rel);
- 	__glibcxx_assert(__m2 <= __m1);
- 
- 	__pointer_type __p1o = __p1;
- 	__pointer_type __p1n = __sync_val_compare_and_swap(&_M_p, __p1o, __p2);
- 
- 	// Assume extra stores (of same value) allowed in true case.
- 	__p1 = __p1n;
- 	return __p1o == __p1n;
-       }
- 
-       __pointer_type
-       fetch_add(ptrdiff_t __d,
- 		memory_order __m = memory_order_seq_cst) noexcept
-       { return __sync_fetch_and_add(&_M_p, __d); }
- 
-       __pointer_type
-       fetch_add(ptrdiff_t __d,
- 		memory_order __m = memory_order_seq_cst) volatile noexcept
-       { return __sync_fetch_and_add(&_M_p, __d); }
- 
-       __pointer_type
-       fetch_sub(ptrdiff_t __d,
- 		memory_order __m = memory_order_seq_cst) noexcept
-       { return __sync_fetch_and_sub(&_M_p, __d); }
- 
-       __pointer_type
-       fetch_sub(ptrdiff_t __d,
- 		memory_order __m = memory_order_seq_cst) volatile noexcept
-       { return __sync_fetch_and_sub(&_M_p, __d); }
-     };
- 
- } // namespace __atomic2
- 
- _GLIBCXX_END_NAMESPACE_VERSION
- } // namespace std
- 
- #endif
--- 0 ----
Index: include/bits/atomic_base.h
===================================================================
*** include/bits/atomic_base.h	(.../trunk/libstdc++-v3)	(revision 180780)
--- include/bits/atomic_base.h	(.../branches/cxx-mem-model/libstdc++-v3)	(revision 180832)
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
*** 83,168 ****
        return __ret;
      }
  
!   /**
!    *  @brief Base type for atomic_flag.
!    *
!    *  Base type is POD with data, allowing atomic_flag to derive from
!    *  it and meet the standard layout type requirement. In addition to
!    *  compatibilty with a C interface, this allows different
!    *  implementations of atomic_flag to use the same atomic operation
!    *  functions, via a standard conversion to the __atomic_flag_base
!    *  argument.
!   */
!   _GLIBCXX_BEGIN_EXTERN_C
! 
!   struct __atomic_flag_base
!   {
!     bool _M_i;
!   };
  
!   _GLIBCXX_END_EXTERN_C
  
! #define ATOMIC_FLAG_INIT { false }
  
  
    // Base types for atomics.
!   //
!   // Three nested namespaces for atomic implementation details.
!   //
!   // The nested namespace inlined into std:: is determined by the value
!   // of the _GLIBCXX_ATOMIC_PROPERTY macro and the resulting
!   // ATOMIC_*_LOCK_FREE macros.
!   //
!   // 0 == __atomic0 == Never lock-free
!   // 1 == __atomic1 == Best available, sometimes lock-free
!   // 2 == __atomic2 == Always lock-free
! 
!   namespace __atomic0
!   {
!     struct atomic_flag;
! 
!     template<typename _IntTp>
!       struct __atomic_base;
!   }
! 
!   namespace __atomic2
!   {
!     struct atomic_flag;
! 
!     template<typename _IntTp>
!       struct __atomic_base;
!   }
! 
!   namespace __atomic1
!   {
!     using __atomic2::atomic_flag;
!     using __atomic0::__atomic_base;
!   }
! 
!   /// Lock-free Property
! #if defined(_GLIBCXX_ATOMIC_BUILTINS_1) && defined(_GLIBCXX_ATOMIC_BUILTINS_2) \
!   && defined(_GLIBCXX_ATOMIC_BUILTINS_4) && defined(_GLIBCXX_ATOMIC_BUILTINS_8)
! # define _GLIBCXX_ATOMIC_PROPERTY 2
! # define _GLIBCXX_ATOMIC_NAMESPACE __atomic2
! #elif defined(_GLIBCXX_ATOMIC_BUILTINS_1)
! # define _GLIBCXX_ATOMIC_PROPERTY 1
! # define _GLIBCXX_ATOMIC_NAMESPACE __atomic1
! #else
! # define _GLIBCXX_ATOMIC_PROPERTY 0
! # define _GLIBCXX_ATOMIC_NAMESPACE __atomic0
! #endif
! 
! #define ATOMIC_CHAR_LOCK_FREE _GLIBCXX_ATOMIC_PROPERTY
! #define ATOMIC_CHAR16_T_LOCK_FREE _GLIBCXX_ATOMIC_PROPERTY
! #define ATOMIC_CHAR32_T_LOCK_FREE _GLIBCXX_ATOMIC_PROPERTY
! #define ATOMIC_WCHAR_T_LOCK_FREE _GLIBCXX_ATOMIC_PROPERTY
! #define ATOMIC_SHORT_LOCK_FREE _GLIBCXX_ATOMIC_PROPERTY
! #define ATOMIC_INT_LOCK_FREE _GLIBCXX_ATOMIC_PROPERTY
! #define ATOMIC_LONG_LOCK_FREE _GLIBCXX_ATOMIC_PROPERTY
! #define ATOMIC_LLONG_LOCK_FREE _GLIBCXX_ATOMIC_PROPERTY
! 
!   inline namespace _GLIBCXX_ATOMIC_NAMESPACE { }
! 
  
    /// atomic_char
    typedef __atomic_base<char>  	       		atomic_char;
--- 83,105 ----
        return __ret;
      }
  
!   /// Lock-free Property
  
! #define LOCKFREE_PROP(T) (__atomic_always_lock_free (sizeof (T), 0) ? 2 : 1)
  
! #define ATOMIC_CHAR_LOCK_FREE 		LOCKFREE_PROP (char)
! #define ATOMIC_CHAR16_T_LOCK_FREE	LOCKFREE_PROP (char16_t)
! #define ATOMIC_CHAR32_T_LOCK_FREE	LOCKFREE_PROP (char32_t)
! #define ATOMIC_WCHAR_T_LOCK_FREE	LOCKFREE_PROP (wchar_t)
! #define ATOMIC_SHORT_LOCK_FREE		LOCKFREE_PROP (short)
! #define ATOMIC_INT_LOCK_FREE		LOCKFREE_PROP (int)
! #define ATOMIC_LONG_LOCK_FREE		LOCKFREE_PROP (long)
! #define ATOMIC_LLONG_LOCK_FREE		LOCKFREE_PROP (long long)
  
  
    // Base types for atomics.
!   template<typename _IntTp>
!     struct __atomic_base;
  
    /// atomic_char
    typedef __atomic_base<char>  	       		atomic_char;
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
*** 287,292 ****
--- 224,817 ----
    template<typename _Tp>
      struct atomic<_Tp*>;
  
+ 
+   /**
+    *  @brief Base type for atomic_flag.
+    *
+    *  Base type is POD with data, allowing atomic_flag to derive from
+    *  it and meet the standard layout type requirement. In addition to
+    *  compatibilty with a C interface, this allows different
+    *  implementations of atomic_flag to use the same atomic operation
+    *  functions, via a standard conversion to the __atomic_flag_base
+    *  argument.
+   */
+   _GLIBCXX_BEGIN_EXTERN_C
+ 
+   struct __atomic_flag_base
+   {
+     bool _M_i;
+   };
+ 
+   _GLIBCXX_END_EXTERN_C
+ 
+ #define ATOMIC_FLAG_INIT { false }
+ 
+   /// atomic_flag
+   struct atomic_flag : public __atomic_flag_base
+   {
+     atomic_flag() noexcept = default;
+     ~atomic_flag() noexcept = default;
+     atomic_flag(const atomic_flag&) = delete;
+     atomic_flag& operator=(const atomic_flag&) = delete;
+     atomic_flag& operator=(const atomic_flag&) volatile = delete;
+ 
+     // Conversion to ATOMIC_FLAG_INIT.
+     atomic_flag(bool __i) noexcept : __atomic_flag_base({ __i }) { }
+ 
+     bool
+     test_and_set(memory_order __m = memory_order_seq_cst) noexcept
+     {
+       return __atomic_exchange_n(&_M_i, 1, __m);
+     }
+ 
+     bool
+     test_and_set(memory_order __m = memory_order_seq_cst) volatile noexcept
+     {
+       return __atomic_exchange_n(&_M_i, 1, __m);
+     }
+ 
+     void
+     clear(memory_order __m = memory_order_seq_cst) noexcept
+     {
+       __glibcxx_assert(__m != memory_order_consume);
+       __glibcxx_assert(__m != memory_order_acquire);
+       __glibcxx_assert(__m != memory_order_acq_rel);
+ 
+       __atomic_store_n(&_M_i, 0, __m);
+     }
+ 
+     void
+     clear(memory_order __m = memory_order_seq_cst) volatile noexcept
+     {
+       __glibcxx_assert(__m != memory_order_consume);
+       __glibcxx_assert(__m != memory_order_acquire);
+       __glibcxx_assert(__m != memory_order_acq_rel);
+ 
+       __atomic_store_n(&_M_i, 0, __m);
+     }
+   };
+ 
+ 
+   /// Base class for atomic integrals.
+   //
+   // For each of the integral types, define atomic_[integral type] struct
+   //
+   // atomic_bool     bool
+   // atomic_char     char
+   // atomic_schar    signed char
+   // atomic_uchar    unsigned char
+   // atomic_short    short
+   // atomic_ushort   unsigned short
+   // atomic_int      int
+   // atomic_uint     unsigned int
+   // atomic_long     long
+   // atomic_ulong    unsigned long
+   // atomic_llong    long long
+   // atomic_ullong   unsigned long long
+   // atomic_char16_t char16_t
+   // atomic_char32_t char32_t
+   // atomic_wchar_t  wchar_t
+   //
+   // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or
+   // 8 bytes, since that is what GCC built-in functions for atomic
+   // memory access expect.
+   template<typename _ITp>
+     struct __atomic_base
+     {
+     private:
+       typedef _ITp 	__int_type;
+ 
+       __int_type 	_M_i;
+ 
+     public:
+       __atomic_base() noexcept = default;
+       ~__atomic_base() noexcept = default;
+       __atomic_base(const __atomic_base&) = delete;
+       __atomic_base& operator=(const __atomic_base&) = delete;
+       __atomic_base& operator=(const __atomic_base&) volatile = delete;
+ 
+       // Requires __int_type convertible to _M_i.
+       constexpr __atomic_base(__int_type __i) noexcept : _M_i (__i) { }
+ 
+       operator __int_type() const noexcept
+       { return load(); }
+ 
+       operator __int_type() const volatile noexcept
+       { return load(); }
+ 
+       __int_type
+       operator=(__int_type __i) noexcept
+       {
+ 	store(__i);
+ 	return __i;
+       }
+ 
+       __int_type
+       operator=(__int_type __i) volatile noexcept
+       {
+ 	store(__i);
+ 	return __i;
+       }
+ 
+       __int_type
+       operator++(int) noexcept
+       { return fetch_add(1); }
+ 
+       __int_type
+       operator++(int) volatile noexcept
+       { return fetch_add(1); }
+ 
+       __int_type
+       operator--(int) noexcept
+       { return fetch_sub(1); }
+ 
+       __int_type
+       operator--(int) volatile noexcept
+       { return fetch_sub(1); }
+ 
+       __int_type
+       operator++() noexcept
+       { return __atomic_add_fetch(&_M_i, 1, memory_order_seq_cst); }
+ 
+       __int_type
+       operator++() volatile noexcept
+       { return __atomic_add_fetch(&_M_i, 1, memory_order_seq_cst); }
+ 
+       __int_type
+       operator--() noexcept
+       { return __atomic_sub_fetch(&_M_i, 1, memory_order_seq_cst); }
+ 
+       __int_type
+       operator--() volatile noexcept
+       { return __atomic_sub_fetch(&_M_i, 1, memory_order_seq_cst); }
+ 
+       __int_type
+       operator+=(__int_type __i) noexcept
+       { return __atomic_add_fetch(&_M_i, __i, memory_order_seq_cst); }
+ 
+       __int_type
+       operator+=(__int_type __i) volatile noexcept
+       { return __atomic_add_fetch(&_M_i, __i, memory_order_seq_cst); }
+ 
+       __int_type
+       operator-=(__int_type __i) noexcept
+       { return __atomic_sub_fetch(&_M_i, __i, memory_order_seq_cst); }
+ 
+       __int_type
+       operator-=(__int_type __i) volatile noexcept
+       { return __atomic_sub_fetch(&_M_i, __i, memory_order_seq_cst); }
+ 
+       __int_type
+       operator&=(__int_type __i) noexcept
+       { return __atomic_and_fetch(&_M_i, __i, memory_order_seq_cst); }
+ 
+       __int_type
+       operator&=(__int_type __i) volatile noexcept
+       { return __atomic_and_fetch(&_M_i, __i, memory_order_seq_cst); }
+ 
+       __int_type
+       operator|=(__int_type __i) noexcept
+       { return __atomic_or_fetch(&_M_i, __i, memory_order_seq_cst); }
+ 
+       __int_type
+       operator|=(__int_type __i) volatile noexcept
+       { return __atomic_or_fetch(&_M_i, __i, memory_order_seq_cst); }
+ 
+       __int_type
+       operator^=(__int_type __i) noexcept
+       { return __atomic_xor_fetch(&_M_i, __i, memory_order_seq_cst); }
+ 
+       __int_type
+       operator^=(__int_type __i) volatile noexcept
+       { return __atomic_xor_fetch(&_M_i, __i, memory_order_seq_cst); }
+ 
+       bool
+       is_lock_free() const noexcept
+       { return __atomic_is_lock_free (sizeof (_M_i), &_M_i); }
+ 
+       bool
+       is_lock_free() const volatile noexcept
+       { return __atomic_is_lock_free (sizeof (_M_i), &_M_i); }
+ 
+       void
+       store(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept
+       {
+ 	__glibcxx_assert(__m != memory_order_acquire);
+ 	__glibcxx_assert(__m != memory_order_acq_rel);
+ 	__glibcxx_assert(__m != memory_order_consume);
+ 
+ 	__atomic_store_n(&_M_i, __i, __m);
+       }
+ 
+       void
+       store(__int_type __i,
+ 	    memory_order __m = memory_order_seq_cst) volatile noexcept
+       {
+ 	__glibcxx_assert(__m != memory_order_acquire);
+ 	__glibcxx_assert(__m != memory_order_acq_rel);
+ 	__glibcxx_assert(__m != memory_order_consume);
+ 
+ 	__atomic_store_n(&_M_i, __i, __m);
+       }
+ 
+       __int_type
+       load(memory_order __m = memory_order_seq_cst) const noexcept
+       {
+ 	__glibcxx_assert(__m != memory_order_release);
+ 	__glibcxx_assert(__m != memory_order_acq_rel);
+ 
+ 	return __atomic_load_n(&_M_i, __m);
+       }
+ 
+       __int_type
+       load(memory_order __m = memory_order_seq_cst) const volatile noexcept
+       {
+ 	__glibcxx_assert(__m != memory_order_release);
+ 	__glibcxx_assert(__m != memory_order_acq_rel);
+ 
+ 	return __atomic_load_n(&_M_i, __m);
+       }
+ 
+       __int_type
+       exchange(__int_type __i,
+ 	       memory_order __m = memory_order_seq_cst) noexcept
+       {
+ 	return __atomic_exchange_n(&_M_i, __i, __m);
+       }
+ 
+ 
+       __int_type
+       exchange(__int_type __i,
+ 	       memory_order __m = memory_order_seq_cst) volatile noexcept
+       {
+ 	return __atomic_exchange_n(&_M_i, __i, __m);
+       }
+ 
+       bool
+       compare_exchange_weak(__int_type& __i1, __int_type __i2,
+ 			    memory_order __m1, memory_order __m2) noexcept
+       {
+ 	__glibcxx_assert(__m2 != memory_order_release);
+ 	__glibcxx_assert(__m2 != memory_order_acq_rel);
+ 	__glibcxx_assert(__m2 <= __m1);
+ 
+ 	return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, __m1, __m2);
+       }
+ 
+       bool
+       compare_exchange_weak(__int_type& __i1, __int_type __i2,
+ 			    memory_order __m1,
+ 			    memory_order __m2) volatile noexcept
+       {
+ 	__glibcxx_assert(__m2 != memory_order_release);
+ 	__glibcxx_assert(__m2 != memory_order_acq_rel);
+ 	__glibcxx_assert(__m2 <= __m1);
+ 
+ 	return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, __m1, __m2);
+       }
+ 
+       bool
+       compare_exchange_weak(__int_type& __i1, __int_type __i2,
+ 			    memory_order __m = memory_order_seq_cst) noexcept
+       {
+ 	return compare_exchange_weak(__i1, __i2, __m,
+ 				     __calculate_memory_order(__m));
+       }
+ 
+       bool
+       compare_exchange_weak(__int_type& __i1, __int_type __i2,
+ 		   memory_order __m = memory_order_seq_cst) volatile noexcept
+       {
+ 	return compare_exchange_weak(__i1, __i2, __m,
+ 				     __calculate_memory_order(__m));
+       }
+ 
+       bool
+       compare_exchange_strong(__int_type& __i1, __int_type __i2,
+ 			      memory_order __m1, memory_order __m2) noexcept
+       {
+ 	__glibcxx_assert(__m2 != memory_order_release);
+ 	__glibcxx_assert(__m2 != memory_order_acq_rel);
+ 	__glibcxx_assert(__m2 <= __m1);
+ 
+ 	return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, __m1, __m2);
+       }
+ 
+       bool
+       compare_exchange_strong(__int_type& __i1, __int_type __i2,
+ 			      memory_order __m1,
+ 			      memory_order __m2) volatile noexcept
+       {
+ 	__glibcxx_assert(__m2 != memory_order_release);
+ 	__glibcxx_assert(__m2 != memory_order_acq_rel);
+ 	__glibcxx_assert(__m2 <= __m1);
+ 
+ 	return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, __m1, __m2);
+       }
+ 
+       bool
+       compare_exchange_strong(__int_type& __i1, __int_type __i2,
+ 			      memory_order __m = memory_order_seq_cst) noexcept
+       {
+ 	return compare_exchange_strong(__i1, __i2, __m,
+ 				       __calculate_memory_order(__m));
+       }
+ 
+       bool
+       compare_exchange_strong(__int_type& __i1, __int_type __i2,
+ 		 memory_order __m = memory_order_seq_cst) volatile noexcept
+       {
+ 	return compare_exchange_strong(__i1, __i2, __m,
+ 				       __calculate_memory_order(__m));
+       }
+ 
+       __int_type
+       fetch_add(__int_type __i,
+ 		memory_order __m = memory_order_seq_cst) noexcept
+       { return __atomic_fetch_add(&_M_i, __i, __m); }
+ 
+       __int_type
+       fetch_add(__int_type __i,
+ 		memory_order __m = memory_order_seq_cst) volatile noexcept
+       { return __atomic_fetch_add(&_M_i, __i, __m); }
+ 
+       __int_type
+       fetch_sub(__int_type __i,
+ 		memory_order __m = memory_order_seq_cst) noexcept
+       { return __atomic_fetch_sub(&_M_i, __i, __m); }
+ 
+       __int_type
+       fetch_sub(__int_type __i,
+ 		memory_order __m = memory_order_seq_cst) volatile noexcept
+       { return __atomic_fetch_sub(&_M_i, __i, __m); }
+ 
+       __int_type
+       fetch_and(__int_type __i,
+ 		memory_order __m = memory_order_seq_cst) noexcept
+       { return __atomic_fetch_and(&_M_i, __i, __m); }
+ 
+       __int_type
+       fetch_and(__int_type __i,
+ 		memory_order __m = memory_order_seq_cst) volatile noexcept
+       { return __atomic_fetch_and(&_M_i, __i, __m); }
+ 
+       __int_type
+       fetch_or(__int_type __i,
+ 	       memory_order __m = memory_order_seq_cst) noexcept
+       { return __atomic_fetch_or(&_M_i, __i, __m); }
+ 
+       __int_type
+       fetch_or(__int_type __i,
+ 	       memory_order __m = memory_order_seq_cst) volatile noexcept
+       { return __atomic_fetch_or(&_M_i, __i, __m); }
+ 
+       __int_type
+       fetch_xor(__int_type __i,
+ 		memory_order __m = memory_order_seq_cst) noexcept
+       { return __atomic_fetch_xor(&_M_i, __i, __m); }
+ 
+       __int_type
+       fetch_xor(__int_type __i,
+ 		memory_order __m = memory_order_seq_cst) volatile noexcept
+       { return __atomic_fetch_xor(&_M_i, __i, __m); }
+     };
+ 
+ 
+   /// Partial specialization for pointer types.
+   template<typename _PTp>
+     struct __atomic_base<_PTp*>
+     {
+     private:
+       typedef _PTp* 	__pointer_type;
+ 
+       __pointer_type 	_M_p;
+ 
+     public:
+       __atomic_base() noexcept = default;
+       ~__atomic_base() noexcept = default;
+       __atomic_base(const __atomic_base&) = delete;
+       __atomic_base& operator=(const __atomic_base&) = delete;
+       __atomic_base& operator=(const __atomic_base&) volatile = delete;
+ 
+       // Requires __pointer_type convertible to _M_p.
+       constexpr __atomic_base(__pointer_type __p) noexcept : _M_p (__p) { }
+ 
+       operator __pointer_type() const noexcept
+       { return load(); }
+ 
+       operator __pointer_type() const volatile noexcept
+       { return load(); }
+ 
+       __pointer_type
+       operator=(__pointer_type __p) noexcept
+       {
+ 	store(__p);
+ 	return __p;
+       }
+ 
+       __pointer_type
+       operator=(__pointer_type __p) volatile noexcept
+       {
+ 	store(__p);
+ 	return __p;
+       }
+ 
+       __pointer_type
+       operator++(int) noexcept
+       { return fetch_add(1); }
+ 
+       __pointer_type
+       operator++(int) volatile noexcept
+       { return fetch_add(1); }
+ 
+       __pointer_type
+       operator--(int) noexcept
+       { return fetch_sub(1); }
+ 
+       __pointer_type
+       operator--(int) volatile noexcept
+       { return fetch_sub(1); }
+ 
+       __pointer_type
+       operator++() noexcept
+       { return __atomic_add_fetch(&_M_p, 1, memory_order_seq_cst); }
+ 
+       __pointer_type
+       operator++() volatile noexcept
+       { return __atomic_add_fetch(&_M_p, 1, memory_order_seq_cst); }
+ 
+       __pointer_type
+       operator--() noexcept
+       { return __atomic_sub_fetch(&_M_p, 1, memory_order_seq_cst); }
+ 
+       __pointer_type
+       operator--() volatile noexcept
+       { return __atomic_sub_fetch(&_M_p, 1, memory_order_seq_cst); }
+ 
+       __pointer_type
+       operator+=(ptrdiff_t __d) noexcept
+       { return __atomic_add_fetch(&_M_p, __d, memory_order_seq_cst); }
+ 
+       __pointer_type
+       operator+=(ptrdiff_t __d) volatile noexcept
+       { return __atomic_add_fetch(&_M_p, __d, memory_order_seq_cst); }
+ 
+       __pointer_type
+       operator-=(ptrdiff_t __d) noexcept
+       { return __atomic_sub_fetch(&_M_p, __d, memory_order_seq_cst); }
+ 
+       __pointer_type
+       operator-=(ptrdiff_t __d) volatile noexcept
+       { return __atomic_sub_fetch(&_M_p, __d, memory_order_seq_cst); }
+ 
+       bool
+       is_lock_free() const noexcept
+       { return __atomic_is_lock_free (sizeof (_M_p), &_M_p); }
+ 
+       bool
+       is_lock_free() const volatile noexcept
+       { return __atomic_is_lock_free (sizeof (_M_p), &_M_p); }
+ 
+       void
+       store(__pointer_type __p,
+ 	    memory_order __m = memory_order_seq_cst) noexcept
+       {
+ 	__glibcxx_assert(__m != memory_order_acquire);
+ 	__glibcxx_assert(__m != memory_order_acq_rel);
+ 	__glibcxx_assert(__m != memory_order_consume);
+ 
+ 	__atomic_store_n(&_M_p, __p, __m);
+       }
+ 
+       void
+       store(__pointer_type __p,
+ 	    memory_order __m = memory_order_seq_cst) volatile noexcept
+       {
+ 	__glibcxx_assert(__m != memory_order_acquire);
+ 	__glibcxx_assert(__m != memory_order_acq_rel);
+ 	__glibcxx_assert(__m != memory_order_consume);
+ 
+ 	__atomic_store_n(&_M_p, __p, __m);
+       }
+ 
+       __pointer_type
+       load(memory_order __m = memory_order_seq_cst) const noexcept
+       {
+ 	__glibcxx_assert(__m != memory_order_release);
+ 	__glibcxx_assert(__m != memory_order_acq_rel);
+ 
+ 	return __atomic_load_n(&_M_p, __m);
+       }
+ 
+       __pointer_type
+       load(memory_order __m = memory_order_seq_cst) const volatile noexcept
+       {
+ 	__glibcxx_assert(__m != memory_order_release);
+ 	__glibcxx_assert(__m != memory_order_acq_rel);
+ 
+ 	return __atomic_load_n(&_M_p, __m);
+       }
+ 
+       __pointer_type
+       exchange(__pointer_type __p,
+ 	       memory_order __m = memory_order_seq_cst) noexcept
+       {
+ 	return __atomic_exchange_n(&_M_p, __p, __m);
+       }
+ 
+ 
+       __pointer_type
+       exchange(__pointer_type __p,
+ 	       memory_order __m = memory_order_seq_cst) volatile noexcept
+       {
+ 	return __atomic_exchange_n(&_M_p, __p, __m);
+       }
+ 
+       bool
+       compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2,
+ 			      memory_order __m1,
+ 			      memory_order __m2) noexcept
+       {
+ 	__glibcxx_assert(__m2 != memory_order_release);
+ 	__glibcxx_assert(__m2 != memory_order_acq_rel);
+ 	__glibcxx_assert(__m2 <= __m1);
+ 
+ 	return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, __m1, __m2);
+       }
+ 
+       bool
+       compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2,
+ 			      memory_order __m1,
+ 			      memory_order __m2) volatile noexcept
+       {
+ 	__glibcxx_assert(__m2 != memory_order_release);
+ 	__glibcxx_assert(__m2 != memory_order_acq_rel);
+ 	__glibcxx_assert(__m2 <= __m1);
+ 
+ 	return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, __m1, __m2);
+       }
+ 
+       __pointer_type
+       fetch_add(ptrdiff_t __d,
+ 		memory_order __m = memory_order_seq_cst) noexcept
+       { return __atomic_fetch_add(&_M_p, __d, __m); }
+ 
+       __pointer_type
+       fetch_add(ptrdiff_t __d,
+ 		memory_order __m = memory_order_seq_cst) volatile noexcept
+       { return __atomic_fetch_add(&_M_p, __d, __m); }
+ 
+       __pointer_type
+       fetch_sub(ptrdiff_t __d,
+ 		memory_order __m = memory_order_seq_cst) noexcept
+       { return __atomic_fetch_sub(&_M_p, __d, __m); }
+ 
+       __pointer_type
+       fetch_sub(ptrdiff_t __d,
+ 		memory_order __m = memory_order_seq_cst) volatile noexcept
+       { return __atomic_fetch_sub(&_M_p, __d, __m); }
+     };
+ 
    // @} group atomics
  
  _GLIBCXX_END_NAMESPACE_VERSION
Index: include/Makefile.am
===================================================================
*** include/Makefile.am	(.../trunk/libstdc++-v3)	(revision 180780)
--- include/Makefile.am	(.../branches/cxx-mem-model/libstdc++-v3)	(revision 180832)
*************** bits_headers = \
*** 83,90 ****
  	${bits_srcdir}/alloc_traits.h \
  	${bits_srcdir}/allocator.h \
  	${bits_srcdir}/atomic_base.h \
- 	${bits_srcdir}/atomic_0.h \
- 	${bits_srcdir}/atomic_2.h \
  	${bits_srcdir}/basic_ios.h \
  	${bits_srcdir}/basic_ios.tcc \
  	${bits_srcdir}/basic_string.h \
--- 83,88 ----
Index: testsuite/29_atomics/headers/atomic/macros.cc
===================================================================
*** testsuite/29_atomics/headers/atomic/macros.cc	(.../trunk/libstdc++-v3)	(revision 180780)
--- testsuite/29_atomics/headers/atomic/macros.cc	(.../branches/cxx-mem-model/libstdc++-v3)	(revision 180832)
***************
*** 20,97 ****
  
  #include <atomic>
  
- namespace gnu
- {
  #ifndef ATOMIC_CHAR_LOCK_FREE 
  # error "ATOMIC_CHAR_LOCK_FREE must be a macro"
- #else
- # if ATOMIC_CHAR_LOCK_FREE != 0 \
-     && ATOMIC_CHAR_LOCK_FREE != 1 && ATOMIC_CHAR_LOCK_FREE != 2
- # error "ATOMIC_CHAR_LOCK_FREE must be 0, 1, or 2"
- # endif
  #endif
  
  #ifndef ATOMIC_CHAR16_T_LOCK_FREE 
  # error "ATOMIC_CHAR16_T_LOCK_FREE must be a macro"
- #else
- # if ATOMIC_CHAR16_T_LOCK_FREE != 0 \
-     && ATOMIC_CHAR16_T_LOCK_FREE != 1 && ATOMIC_CHAR16_T_LOCK_FREE != 2
- # error "ATOMIC_CHAR16_T_LOCK_FREE must be 0, 1, or 2"
- # endif
  #endif
  
  #ifndef ATOMIC_CHAR32_T_LOCK_FREE 
  # error "ATOMIC_CHAR32_T_LOCK_FREE must be a macro"
- #else
- # if ATOMIC_CHAR32_T_LOCK_FREE != 0 \
-     && ATOMIC_CHAR32_T_LOCK_FREE != 1 && ATOMIC_CHAR32_T_LOCK_FREE != 2
- # error "ATOMIC_CHAR32_T_LOCK_FREE must be 0, 1, or 2"
- # endif
  #endif
  
  #ifndef ATOMIC_WCHAR_T_LOCK_FREE 
  # error "ATOMIC_WCHAR_T_LOCK_FREE must be a macro"
- #else
- # if ATOMIC_WCHAR_T_LOCK_FREE != 0 \
-     && ATOMIC_WCHAR_T_LOCK_FREE != 1 && ATOMIC_WCHAR_T_LOCK_FREE != 2
- # error "ATOMIC_WCHAR_T_LOCK_FREE must be 0, 1, or 2"
- # endif
  #endif
  
  #ifndef ATOMIC_SHORT_LOCK_FREE 
  # error "ATOMIC_SHORT_LOCK_FREE must be a macro"
- #else
- # if ATOMIC_SHORT_LOCK_FREE != 0 \
-     && ATOMIC_SHORT_LOCK_FREE != 1 && ATOMIC_SHORT_LOCK_FREE != 2
- # error "ATOMIC_SHORT_LOCK_FREE must be 0, 1, or 2"
- # endif
  #endif
  
  #ifndef ATOMIC_INT_LOCK_FREE 
  # error "ATOMIC_INT_LOCK_FREE must be a macro"
- #else
- # if ATOMIC_INT_LOCK_FREE != 0 \
-     && ATOMIC_INT_LOCK_FREE != 1 && ATOMIC_INT_LOCK_FREE != 2
- # error "ATOMIC_INT_LOCK_FREE must be 0, 1, or 2"
- # endif
  #endif
  
  #ifndef ATOMIC_LONG_LOCK_FREE 
  # error "ATOMIC_LONG_LOCK_FREE must be a macro"
- #else
- # if ATOMIC_LONG_LOCK_FREE != 0 \
-     && ATOMIC_LONG_LOCK_FREE != 1 && ATOMIC_LONG_LOCK_FREE != 2
- # error "ATOMIC_LONG_LOCK_FREE must be 0, 1, or 2"
- # endif
  #endif
  
  #ifndef ATOMIC_LLONG_LOCK_FREE 
  # error "ATOMIC_LLONG_LOCK_FREE must be a macro"
- #else
- # if ATOMIC_LLONG_LOCK_FREE != 0 \
-     && ATOMIC_LLONG_LOCK_FREE != 1 && ATOMIC_LLONG_LOCK_FREE != 2
- # error "ATOMIC_LLONG_LOCK_FREE must be 0, 1, or 2"
- # endif
  #endif
  
  #ifndef ATOMIC_FLAG_INIT
--- 20,55 ----
*************** namespace gnu
*** 101,104 ****
--- 59,99 ----
  #ifndef ATOMIC_VAR_INIT
      #error "ATOMIC_VAR_INIT_must_be_a_macro"
  #endif
+ 
+ 
+ extern void abort(void);
+ 
+ main ()
+ {
+  if (ATOMIC_CHAR_LOCK_FREE != 0 && ATOMIC_CHAR_LOCK_FREE != 1
+      && ATOMIC_CHAR_LOCK_FREE != 2)
+    abort ();
+ 
+  if (ATOMIC_CHAR16_T_LOCK_FREE != 0 && ATOMIC_CHAR16_T_LOCK_FREE != 1
+      && ATOMIC_CHAR16_T_LOCK_FREE != 2)
+    abort ();
+ 
+  if (ATOMIC_CHAR32_T_LOCK_FREE != 0 && ATOMIC_CHAR32_T_LOCK_FREE != 1
+      && ATOMIC_CHAR32_T_LOCK_FREE != 2)
+    abort ();
+ 
+  if (ATOMIC_WCHAR_T_LOCK_FREE != 0 && ATOMIC_WCHAR_T_LOCK_FREE != 1
+      && ATOMIC_WCHAR_T_LOCK_FREE != 2)
+    abort ();
+ 
+  if (ATOMIC_SHORT_LOCK_FREE != 0 && ATOMIC_SHORT_LOCK_FREE != 1
+      && ATOMIC_SHORT_LOCK_FREE != 2)
+    abort ();
+ 
+  if (ATOMIC_INT_LOCK_FREE != 0 && ATOMIC_INT_LOCK_FREE != 1
+      && ATOMIC_INT_LOCK_FREE != 2)
+    abort ();
+ 
+  if (ATOMIC_LONG_LOCK_FREE != 0 && ATOMIC_LONG_LOCK_FREE != 1
+      && ATOMIC_LONG_LOCK_FREE != 2)
+    abort ();
+ 
+  if (ATOMIC_LLONG_LOCK_FREE != 0 && ATOMIC_LLONG_LOCK_FREE != 1
+      && ATOMIC_LLONG_LOCK_FREE != 2)
+    abort ();
  }
Index: testsuite/29_atomics/atomic/cons/user_pod.cc
===================================================================
*** testsuite/29_atomics/atomic/cons/user_pod.cc	(.../trunk/libstdc++-v3)	(revision 180780)
--- testsuite/29_atomics/atomic/cons/user_pod.cc	(.../branches/cxx-mem-model/libstdc++-v3)	(revision 180832)
***************
*** 1,7 ****
  // { dg-options "-std=gnu++0x" }
! // { dg-do link { xfail *-*-* } }
  
! // Copyright (C) 2009 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
--- 1,7 ----
  // { dg-options "-std=gnu++0x" }
! // { dg-do link }
  
! // Copyright (C) 2009, 2011 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
*************** struct dwordp
*** 29,35 ****
  void atomics()
  {
    std::atomic<dwordp> a;
!   bool b = a.is_lock_free(); // { dg-excess-errors "undefined reference to" }
  }
  
  int main()
--- 29,35 ----
  void atomics()
  {
    std::atomic<dwordp> a;
!   bool b = a.is_lock_free();
  }
  
  int main()
Index: testsuite/29_atomics/atomic/requirements/explicit_instantiation/1.cc
===================================================================
*** testsuite/29_atomics/atomic/requirements/explicit_instantiation/1.cc	(.../trunk/libstdc++-v3)	(revision 180780)
--- testsuite/29_atomics/atomic/requirements/explicit_instantiation/1.cc	(.../branches/cxx-mem-model/libstdc++-v3)	(revision 180832)
***************
*** 23,27 ****
  #include <atomic>
  #include <testsuite_character.h>
  
! template class std::atomic<__gnu_test::pod_char>;
  template class std::atomic<__gnu_test::pod_char*>;
--- 23,27 ----
  #include <atomic>
  #include <testsuite_character.h>
  
! template class std::atomic<__gnu_test::pod_state>;
  template class std::atomic<__gnu_test::pod_char*>;

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-03 23:52 cxx-mem-model merge [6 of 9] - libstdc++-v3 Andrew MacLeod
@ 2011-11-04 18:17 ` Jeff Law
  2011-11-04 18:53   ` Andrew MacLeod
  2011-11-07  0:54 ` Hans-Peter Nilsson
  1 sibling, 1 reply; 22+ messages in thread
From: Jeff Law @ 2011-11-04 18:17 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: gcc-patches

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 11/03/11 17:50, Andrew MacLeod wrote:
> These are the changes to libstdc++ to make use of the new atomics.
> I changed the files to use the new atomics, and bkoz did a
> shuffling of the include file layout to better suit the new c++
> approach.
> 
> previously, libstdc++ provided a locked implementation in
> atomic_0.h with the theory that eventually it would be used.  The
> new scheme involves leaving non-lock-free implementations to an
> external library. This involved removing the old lock
> implementation and restructuring things now that multiple
> implementation dont have to be supported.   SO a lot fo this is
> churn... 2 include files deleted and one merged into another one..
Is there an ABI/API impact to all this churn?  Or was the atomic_0.h
stuff never used?  Was it an exposed API or strictly internal?  I get
the impression that is_lock_free wasn't ever defined, which is
probably good in this context.

Given these are primarily Benjamin's changes, I'm going to defer to
his wisdom :-)    If he doesn't chime in, ping him directly.

jeff


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJOtCuOAAoJEBRtltQi2kC7M34H/2B9f1DsPE9oK5DfvHYyclxZ
hvFGlSnw5r9q7UGsWrCGDd/J4mmkXOJMHMfpzjowuWUYUYDNZ5b2FuZ9fMij2K5f
wJOfN9wslWTNyafJb/hjVMEzy1dmCUB2YV4N0e5cy39lvfWfNzM/9EfYbz5UEQpO
VCODtS0WbsSUTkt7HeDkD7U21mpSsn1fGx4gBJyBpODihIq7Qk4uFqGtvrKGve26
7Pi3aP64TQl3zwF2lAkOV4KgzPLQUv4RIWOiYuyzEf13XpfJivWPLTUkJqJka+lp
8W+LFOLl3ygnNUAe9ugwRNCE+agfHG+Hp7+l8ypCpWSsrBwJB8m7rY1sMDA2HJw=
=E/Sj
-----END PGP SIGNATURE-----

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-04 18:17 ` Jeff Law
@ 2011-11-04 18:53   ` Andrew MacLeod
  0 siblings, 0 replies; 22+ messages in thread
From: Andrew MacLeod @ 2011-11-04 18:53 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches, Benjamin Kosnik

On 11/04/2011 02:14 PM, Jeff Law wrote:
> These are the changes to libstdc++ to make use of the new atomics.
>> I changed the files to use the new atomics, and bkoz did a
>> shuffling of the include file layout to better suit the new c++
>> approach.
>>
>> previously, libstdc++ provided a locked implementation in
>> atomic_0.h with the theory that eventually it would be used.  The
>> new scheme involves leaving non-lock-free implementations to an
>> external library. This involved removing the old lock
>> implementation and restructuring things now that multiple
>> implementation dont have to be supported.   SO a lot fo this is
>> churn... 2 include files deleted and one merged into another one..
> Is there an ABI/API impact to all this churn?  Or was the atomic_0.h
> stuff never used?  Was it an exposed API or strictly internal?  I get
> the impression that is_lock_free wasn't ever defined, which is
> probably good in this context.
>
> Given these are primarily Benjamin's changes, I'm going to defer to
> his wisdom :-)    If he doesn't chime in, ping him directly.
well, actually, the way it was setup, I don't think it was ever used.  
Things defaulted to using the lockfree __sync routines, and if you tried 
to do something that didn't map to one of those, you got either a 
compiler error (in the case of non-integral classes),  or external 
__sync calls.  It was in a transitional state, and never fully flushed 
out. At least thats was my impression when I started trying to work with 
it to get full support.  I dont think you could trigger the code in 
atomic_0.h without changing the compiler/headerfiles yourself.    At 
least I dont think so.   Well, It may have been possible by explicitly 
specifying the __atomic0 namespace with baseclasses... Im not sure.    
I'll let bkoz deal with answering that :-)   Since support was 
experimental, I dont think anyone was suppose to count on it anyway :-P

I believe that any atomic integral that worked before will work today 
with these changes and without an external library...  With the addition 
of the forthcoming atomic library (which is not a part of gcc) you 
should be able to compile and run anything, including arbitrary user 
PODs.  WIth any luck at all, the atomic library ABI I set up is defined 
enough now to continue to function as is in future releases.

Andrew

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-03 23:52 cxx-mem-model merge [6 of 9] - libstdc++-v3 Andrew MacLeod
  2011-11-04 18:17 ` Jeff Law
@ 2011-11-07  0:54 ` Hans-Peter Nilsson
  2011-11-07  4:48   ` Andrew MacLeod
  1 sibling, 1 reply; 22+ messages in thread
From: Hans-Peter Nilsson @ 2011-11-07  0:54 UTC (permalink / raw)
  To: amacleod; +Cc: gcc-patches, libstdc++

> From: Andrew MacLeod <amacleod@redhat.com>
> Date: Fri, 4 Nov 2011 00:50:47 +0100

> These are the changes to libstdc++ to make use of the new atomics.  I
> changed the files to use the new atomics, and bkoz did a shuffling of
> the include file layout to better suit the new c++ approach.
> 
> previously, libstdc++ provided a locked implementation in atomic_0.h
> with the theory that eventually it would be used.  The new scheme
> involves leaving non-lock-free implementations to an external library.
> This involved removing the old lock implementation and restructuring
> things now that multiple implementation dont have to be supported.   SO
> a lot fo this is churn... 2 include files deleted and one merged into
> another one..

This (formally a change in the range 181027:181034) got me three
libstdc++ regressions for cris-elf, which has no "atomic"
support whatsoever (well, not the version represented in
"cris-elf"), so something is amiss at the bottom of the default
path:

Running /tmp/hpautotest-gcc1/gcc/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp ...
...
FAIL: 29_atomics/atomic_flag/clear/1.cc (test for excess errors)
WARNING: 29_atomics/atomic_flag/clear/1.cc compilation failed to produce executable
FAIL: 29_atomics/atomic_flag/test_and_set/explicit.cc (test for excess errors)
WARNING: 29_atomics/atomic_flag/test_and_set/explicit.cc compilation failed to produce executable
FAIL: 29_atomics/atomic_flag/test_and_set/implicit.cc (test for excess errors)

And the linker message is:
Executing on host: /tmp/hpautotest-gcc1/cris-elf/gccobj/./gcc/g++ -shared-libgcc -B/tmp/hpautotest-gcc1/cris-elf/gccobj/./gcc -nostdinc++ -L/tmp/hpautotest-gcc1/cris-elf/gccobj/cris-elf/libstdc++-v3/src -L/tmp/hpautotest-gcc1/cris-elf/gccobj/cris-elf/libstdc++-v3/src/.libs -nostdinc -B/tmp/hpautotest-gcc1/cris-elf/gccobj/cris-elf/newlib/ -isystem /tmp/hpautotest-gcc1/cris-elf/gccobj/cris-elf/newlib/targ-include -isystem /tmp/hpautotest-gcc1/gcc/newlib/libc/include -B/tmp/hpautotest-gcc1/cris-elf/gccobj/cris-elf/libgloss/cris -L/tmp/hpautotest-gcc1/cris-elf/gccobj/cris-elf/libgloss/libnosys -L/tmp/hpautotest-gcc1/gcc/libgloss/cris -B/tmp/hpautotest-gcc1/cris-elf/pre/cris-elf/bin/ -B/tmp/hpautotest-gcc1/cris-elf/pre/cris-elf/lib/ -isystem /tmp/hpautotest-gcc1/cris-elf/pre/cris-elf/include -isystem /tmp/hpautotest-gcc1/cris-elf/pre/cris-elf/sys-include -B/tmp/hpautotest-gcc1/cris-elf/gccobj/cris-elf/./libgloss/cris/ -L/tmp/hpautotest-gcc1/cris-elf/gccobj/cris-elf/./libgloss/cris
  -L/tmp/hpautotest-gcc1/gcc/libgloss/cris -B/tmp/hpautotest-gcc1/cris-elf/gccobj/cris-elf/./libstdc++-v3/src/.libs -g -O2 -D_GLIBCXX_ASSERT -fmessage-length=0 -ffunction-sections -fdata-sections -g -O2 -g -O2 -DLOCALEDIR="." -nostdinc++ -I/tmp/hpautotest-gcc1/cris-elf/gccobj/cris-elf/libstdc++-v3/include/cris-elf -I/tmp/hpautotest-gcc1/cris-elf/gccobj/cris-elf/libstdc++-v3/include -I/tmp/hpautotest-gcc1/gcc/libstdc++-v3/libsupc++ -I/tmp/hpautotest-gcc1/gcc/libstdc++-v3/include/backward -I/tmp/hpautotest-gcc1/gcc/libstdc++-v3/testsuite/util /tmp/hpautotest-gcc1/gcc/libstdc++-v3/testsuite/29_atomics/atomic_flag/test_and_set/explicit.cc   -std=gnu++0x ./libtestc++.a    -isystem /tmp/hpautotest-gcc1/cris-elf/gccobj/cris-elf/./newlib/targ-include -isystem /tmp/hpautotest-gcc1/gcc/newlib/libc/include -B/tmp/hpautotest-gcc1/cris-elf/gccobj/cris-elf/./libgloss/cris/ -L/tmp/hpautotest-gcc1/cris-elf/gccobj/cris-elf/./libgloss/cris -L/tmp/hpautotest-gcc1/gcc/libgloss/cris  -B/tmp/hpaut
 otest-gcc1/cris-elf/gccobj/cris-elf/./newlib/ -L/tmp/hpautot!
 est-gcc1
/cris-elf/gccobj/cris-elf/./newlib -sim3  -lm   -o ./explicit.exe    (timeout = 600)
/tmp/cc21Ui3S.o: In function `ZNSt11atomic_flag12test_and_setESt12memory_order':
/tmp/hpautotest-gcc1/cris-elf/gccobj/cris-elf/libstdc++-v3/include/bits/atomic_base.h:264: undefined reference to `__atomic_exchange_1'
collect2: error: ld returned 1 exit status
compiler exited with status 1
output is:
/tmp/cc21Ui3S.o: In function `ZNSt11atomic_flag12test_and_setESt12memory_order':
/tmp/hpautotest-gcc1/cris-elf/gccobj/cris-elf/libstdc++-v3/include/bits/atomic_base.h:264: undefined reference to `__atomic_exchange_1'
collect2: error: ld returned 1 exit status

brgds, H-P

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-07  0:54 ` Hans-Peter Nilsson
@ 2011-11-07  4:48   ` Andrew MacLeod
  2011-11-07 11:36     ` Hans-Peter Nilsson
  0 siblings, 1 reply; 22+ messages in thread
From: Andrew MacLeod @ 2011-11-07  4:48 UTC (permalink / raw)
  To: Hans-Peter Nilsson; +Cc: gcc-patches, libstdc++

[-- Attachment #1: Type: text/plain, Size: 756 bytes --]

On 11/06/2011 07:38 PM, Hans-Peter Nilsson wrote:
>
> This (formally a change in the range 181027:181034) got me three
> libstdc++ regressions for cris-elf, which has no "atomic"
> support whatsoever (well, not the version represented in
> "cris-elf"), so something is amiss at the bottom of the default
> path:
yes, I have a final pending patch which didn't make it to the branch 
before the merge.  It changes the behaviour of atomic_flag on targets 
with no compare_and_swap.  I *think* it will resolve your problem.

I've attached the early version of the patch which you can try. Its 
missing a documentation change I was going to add tomorrow before 
submitting, but we can see if it resolves your problem.  Give it a shot 
and let me know.

Andrew


[-- Attachment #2: TAS.diff --]
[-- Type: text/plain, Size: 9642 bytes --]



	gcc
	* expr.h (expand_atomic_exchange): Add extra parameter.
	* builtins.c (expand_builtin_sync_lock_test_and_set): Call
	expand_atomic_exchange with true.
	(expand_builtin_atomic_exchange): Call expand_atomic_exchange with
	false.
	* optabs.c (expand_atomic_exchange): Add use_test_and_set param and
	only fall back to __sync_test_and_set when true.
	(expand_atomic_store): Add false to expand_atomic_exchange call.

	libstdc++-v3
	* include/bits/atomic_base.h (test_and_set): Call __atomic_exchange
	only if it is always lock free, otherwise __sync_lock_test_and_set.


Index: gcc/expr.h
===================================================================
*** gcc/expr.h	(revision 180770)
--- gcc/expr.h	(working copy)
*************** rtx emit_conditional_add (rtx, enum rtx_
*** 215,221 ****
  rtx expand_sync_operation (rtx, rtx, enum rtx_code);
  rtx expand_sync_fetch_operation (rtx, rtx, enum rtx_code, bool, rtx);
  
! rtx expand_atomic_exchange (rtx, rtx, rtx, enum memmodel);
  rtx expand_atomic_load (rtx, rtx, enum memmodel);
  rtx expand_atomic_store (rtx, rtx, enum memmodel);
  rtx expand_atomic_fetch_op (rtx, rtx, rtx, enum rtx_code, enum memmodel, 
--- 215,221 ----
  rtx expand_sync_operation (rtx, rtx, enum rtx_code);
  rtx expand_sync_fetch_operation (rtx, rtx, enum rtx_code, bool, rtx);
  
! rtx expand_atomic_exchange (rtx, rtx, rtx, enum memmodel, bool);
  rtx expand_atomic_load (rtx, rtx, enum memmodel);
  rtx expand_atomic_store (rtx, rtx, enum memmodel);
  rtx expand_atomic_fetch_op (rtx, rtx, rtx, enum rtx_code, enum memmodel, 
Index: gcc/builtins.c
===================================================================
*** gcc/builtins.c	(revision 180789)
--- gcc/builtins.c	(working copy)
*************** expand_builtin_sync_lock_test_and_set (e
*** 5221,5227 ****
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
  
!   return expand_atomic_exchange (target, mem, val, MEMMODEL_ACQUIRE);
  }
  
  /* Expand the __sync_lock_release intrinsic.  EXP is the CALL_EXPR.  */
--- 5221,5227 ----
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
  
!   return expand_atomic_exchange (target, mem, val, MEMMODEL_ACQUIRE, true);
  }
  
  /* Expand the __sync_lock_release intrinsic.  EXP is the CALL_EXPR.  */
*************** expand_builtin_atomic_exchange (enum mac
*** 5284,5290 ****
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
  
!   return expand_atomic_exchange (target, mem, val, model);
  }
  
  /* Expand the __atomic_compare_exchange intrinsic:
--- 5284,5290 ----
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
  
!   return expand_atomic_exchange (target, mem, val, model, false);
  }
  
  /* Expand the __atomic_compare_exchange intrinsic:
Index: gcc/optabs.c
===================================================================
*** gcc/optabs.c	(revision 180770)
--- gcc/optabs.c	(working copy)
*************** expand_compare_and_swap_loop (rtx mem, r
*** 6872,6881 ****
     atomically store VAL in MEM and return the previous value in MEM.
  
     MEMMODEL is the memory model variant to use.
!    TARGET is an option place to stick the return value.  */
  
  rtx
! expand_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model)
  {
    enum machine_mode mode = GET_MODE (mem);
    enum insn_code icode;
--- 6872,6884 ----
     atomically store VAL in MEM and return the previous value in MEM.
  
     MEMMODEL is the memory model variant to use.
!    TARGET is an optional place to stick the return value.  
!    USE_TEST_AND_SET indicates whether __sync_lock_test_and_set should be used
!    as a fall back if the atomic_exchange pattern does not exist.  */
  
  rtx
! expand_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model,
! 			bool use_test_and_set)			
  {
    enum machine_mode mode = GET_MODE (mem);
    enum insn_code icode;
*************** expand_atomic_exchange (rtx target, rtx 
*** 6900,6930 ****
       acquire barrier.  If the pattern exists, and the memory model is stronger
       than acquire, add a release barrier before the instruction.
       The barrier is not needed if sync_lock_test_and_set doesn't exist since
!      it will expand into a compare-and-swap loop.  */
  
!   icode = direct_optab_handler (sync_lock_test_and_set_optab, mode);
!   last_insn = get_last_insn ();
!   if ((icode != CODE_FOR_nothing) && (model == MEMMODEL_SEQ_CST || 
! 				      model == MEMMODEL_RELEASE ||
! 				      model == MEMMODEL_ACQ_REL))
!     expand_builtin_mem_thread_fence (model);
  
!   if (icode != CODE_FOR_nothing)
!     {
!       struct expand_operand ops[3];
  
!       create_output_operand (&ops[0], target, mode);
!       create_fixed_operand (&ops[1], mem);
!       /* VAL may have been promoted to a wider mode.  Shrink it if so.  */
!       create_convert_operand_to (&ops[2], val, mode, true);
!       if (maybe_expand_insn (icode, 3, ops))
! 	return ops[0].value;
!     }
  
!   /* Remove any fence we may have inserted since a compare and swap loop is a
!      full memory barrier.  */
!   if (last_insn != get_last_insn ())
!     delete_insns_since (last_insn);
  
    /* Otherwise, use a compare-and-swap loop for the exchange.  */
    if (can_compare_and_swap_p (mode))
--- 6903,6941 ----
       acquire barrier.  If the pattern exists, and the memory model is stronger
       than acquire, add a release barrier before the instruction.
       The barrier is not needed if sync_lock_test_and_set doesn't exist since
!      it will expand into a compare-and-swap loop.
  
!      Some targets have non-compliant test_and_sets, so it would be incorrect
!      to emit a test_and_set in place of an __atomic_exchange.  The test_and_set
!      builtin shares this expander since exchange can always replace the
!      test_and_set.  */
! 
!   if (use_test_and_set)
!     {
!       icode = direct_optab_handler (sync_lock_test_and_set_optab, mode);
!       last_insn = get_last_insn ();
!       if ((icode != CODE_FOR_nothing) && (model == MEMMODEL_SEQ_CST || 
! 					  model == MEMMODEL_RELEASE ||
! 					  model == MEMMODEL_ACQ_REL))
! 	expand_builtin_mem_thread_fence (model);
  
!       if (icode != CODE_FOR_nothing)
! 	{
! 	  struct expand_operand ops[3];
  
! 	  create_output_operand (&ops[0], target, mode);
! 	  create_fixed_operand (&ops[1], mem);
! 	  /* VAL may have been promoted to a wider mode.  Shrink it if so.  */
! 	  create_convert_operand_to (&ops[2], val, mode, true);
! 	  if (maybe_expand_insn (icode, 3, ops))
! 	    return ops[0].value;
! 	}
  
!       /* Remove any fence that was inserted since a compare and swap loop is
! 	 already a full memory barrier.  */
!       if (last_insn != get_last_insn ())
! 	delete_insns_since (last_insn);
!     }
  
    /* Otherwise, use a compare-and-swap loop for the exchange.  */
    if (can_compare_and_swap_p (mode))
*************** expand_atomic_store (rtx mem, rtx val, e
*** 7130,7136 ****
       the result.  If that doesn't work, don't do anything.  */
    if (GET_MODE_PRECISION(mode) > BITS_PER_WORD)
      {
!       rtx target = expand_atomic_exchange (NULL_RTX, mem, val, model);
        if (target)
          return const0_rtx;
        else
--- 7141,7147 ----
       the result.  If that doesn't work, don't do anything.  */
    if (GET_MODE_PRECISION(mode) > BITS_PER_WORD)
      {
!       rtx target = expand_atomic_exchange (NULL_RTX, mem, val, model, false);
        if (target)
          return const0_rtx;
        else
Index: libstdc++-v3/include/bits/atomic_base.h
===================================================================
*** libstdc++-v3/include/bits/atomic_base.h	(revision 180789)
--- libstdc++-v3/include/bits/atomic_base.h	(working copy)
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
*** 261,273 ****
      bool
      test_and_set(memory_order __m = memory_order_seq_cst) noexcept
      {
!       return __atomic_exchange_n(&_M_i, 1, __m);
      }
  
      bool
      test_and_set(memory_order __m = memory_order_seq_cst) volatile noexcept
      {
!       return __atomic_exchange_n(&_M_i, 1, __m);
      }
  
      void
--- 261,295 ----
      bool
      test_and_set(memory_order __m = memory_order_seq_cst) noexcept
      {
!       /* The standard *requires* this to be lock free.  If exchange is not
! 	 always lock free, the resort to the old test_and_set.  */
!       if (__atomic_always_lock_free (sizeof (_M_i), 0))
! 	return __atomic_exchange_n(&_M_i, 1, __m);
!       else
!         {
! 	  /* Sync test and set is only guaranteed to be acquire.  */
! 	  if (__m == memory_order_seq_cst || __m == memory_order_release
! 	      || __m == memory_order_acq_rel)
! 	    atomic_thread_fence (__m);
! 	  return __sync_lock_test_and_set (&_M_i, 1);
! 	}
      }
  
      bool
      test_and_set(memory_order __m = memory_order_seq_cst) volatile noexcept
      {
!       /* The standard *requires* this to be lock free.  If exchange is not
! 	 always lock free, the resort to the old test_and_set.  */
!       if (__atomic_always_lock_free (sizeof (_M_i), 0))
! 	return __atomic_exchange_n(&_M_i, 1, __m);
!       else
!         {
! 	  /* Sync test and set is only guaranteed to be acquire.  */
! 	  if (__m == memory_order_seq_cst || __m == memory_order_release
! 	      || __m == memory_order_acq_rel)
! 	    atomic_thread_fence (__m);
! 	  return __sync_lock_test_and_set (&_M_i, 1);
! 	}
      }
  
      void

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-07  4:48   ` Andrew MacLeod
@ 2011-11-07 11:36     ` Hans-Peter Nilsson
  2011-11-07 14:41       ` Andrew MacLeod
  2011-11-07 14:56       ` Andrew MacLeod
  0 siblings, 2 replies; 22+ messages in thread
From: Hans-Peter Nilsson @ 2011-11-07 11:36 UTC (permalink / raw)
  To: amacleod; +Cc: hp, gcc-patches, libstdc++

> From: Andrew MacLeod <amacleod@redhat.com>
> Date: Mon, 7 Nov 2011 05:25:15 +0100

> On 11/06/2011 07:38 PM, Hans-Peter Nilsson wrote:
> >
> > This (formally a change in the range 181027:181034) got me three
> > libstdc++ regressions for cris-elf, which has no "atomic"
> > support whatsoever (well, not the version represented in
> > "cris-elf"), so something is amiss at the bottom of the default
> > path:
> yes, I have a final pending patch which didn't make it to the branch
> before the merge.  It changes the behaviour of atomic_flag on targets
> with no compare_and_swap.  I *think* it will resolve your problem.
> 
> I've attached the early version of the patch which you can try. Its
> missing a documentation change I was going to add tomorrow before
> submitting, but we can see if it resolves your problem.  Give it a shot
> and let me know.

Sorry, no it didn't help.  No additional regressions either
though, but the undef'd reference changed to two:

Excess errors:
/tmp/atreg1/gccobj/cris-elf/libstdc++-v3/include/bits/atomic_base.h:273: undefined reference to `std::atomic_thread_fence(std::memory_order)'
/tmp/atreg1/gccobj/cris-elf/libstdc++-v3/include/bits/atomic_base.h:274: undefined reference to `__sync_lock_test_and_set_1'
collect2: error: ld returned 1 exit status

brgds, H-P

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-07 11:36     ` Hans-Peter Nilsson
@ 2011-11-07 14:41       ` Andrew MacLeod
  2011-11-07 14:56       ` Andrew MacLeod
  1 sibling, 0 replies; 22+ messages in thread
From: Andrew MacLeod @ 2011-11-07 14:41 UTC (permalink / raw)
  To: Hans-Peter Nilsson; +Cc: hp, gcc-patches, libstdc++

On 11/07/2011 06:17 AM, Hans-Peter Nilsson wrote:
>
> Sorry, no it didn't help.  No additional regressions either
> though, but the undef'd reference changed to two:
>
> Excess errors:
> /tmp/atreg1/gccobj/cris-elf/libstdc++-v3/include/bits/atomic_base.h:273: undefined reference to `std::atomic_thread_fence(std::memory_order)'
> /tmp/atreg1/gccobj/cris-elf/libstdc++-v3/include/bits/atomic_base.h:274: undefined reference to `__sync_lock_test_and_set_1'
> collect2: error: ld returned 1 exit status

OK, cool. Its good to have the example of something with no support 
whatsoever.    I'll have a look today.

Andrew

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-07 11:36     ` Hans-Peter Nilsson
  2011-11-07 14:41       ` Andrew MacLeod
@ 2011-11-07 14:56       ` Andrew MacLeod
  2011-11-07 15:38         ` Hans-Peter Nilsson
                           ` (3 more replies)
  1 sibling, 4 replies; 22+ messages in thread
From: Andrew MacLeod @ 2011-11-07 14:56 UTC (permalink / raw)
  To: Hans-Peter Nilsson
  Cc: hp, gcc-patches, libstdc++, Benjamin Kosnik, Richard Henderson


>> On 11/06/2011 07:38 PM, Hans-Peter Nilsson wrote:
>>> This (formally a change in the range 181027:181034) got me three
>>> libstdc++ regressions for cris-elf, which has no "atomic"
>>> support whatsoever (well, not the version represented in
>>> "cris-elf"), so something is amiss at the bottom of the default
>>> path:
>> yes, I have a final pending patch which didn't make it to the branch
>> before the merge.  It changes the behaviour of atomic_flag on targets
>> with no compare_and_swap.  I *think* it will resolve your problem.
>>
>> I've attached the early version of the patch which you can try. Its
>> missing a documentation change I was going to add tomorrow before
>> submitting, but we can see if it resolves your problem.  Give it a shot
>> and let me know.
> Sorry, no it didn't help.  No additional regressions either
> though, but the undef'd reference changed to two:
>
> Excess errors:
> /tmp/atreg1/gccobj/cris-elf/libstdc++-v3/include/bits/atomic_base.h:273: undefined reference to `std::atomic_thread_fence(std::memory_order)'
> /tmp/atreg1/gccobj/cris-elf/libstdc++-v3/include/bits/atomic_base.h:274: undefined reference to `__sync_lock_test_and_set_1'
> collect2: error: ld returned 1 exit status
>

Actually, this target has no lock free support whatsoever?  ie, no 
compare_and_swap instruction, nor an implementation of 
sync_lock_test_and_set and sync_lock_release?

I think the libstdc++ standard now requires the class atomic_flag to be 
lock free in order to conform (n3242 29.7.2)

So I guess this is the situation which all the atomic tests are not even 
suppose to be run since they aren't supported.  My guess is that in the 
previous releases the c++ header files probably provided a locked 
implementation of test_and_set, and so the tests would run.

bkoz:  I guess what we need is a way to disable all atomic support for 
targets which do not have an implementable atomic_flag class?

Thats why we're getting the unresolved external 
__sync_lock_test_and_set_1 ,  in order to get his far, we assume that 
minimal level of support...

rth: __sync_lock_test_and_set_1  could be provided by libgcc if the OS 
has hooks in it to provide functionality...  How can we tell when 
compiling a C++ program whether that is going to be an unresolved 
external or whether libgcc is going to provide it? I know you have a 
pending patch for libgcc support fo the __atomics, but Im unsure how we 
check this from the compiler

I should also change it so that the compiler issues an error if 
atomic_thread_fence doesn't resolve to a something since that implies 
there is no __sync_sychronize() either, which is also minimally expected 
at this point.  It should never become  an external reference.

Andrew

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-07 14:56       ` Andrew MacLeod
@ 2011-11-07 15:38         ` Hans-Peter Nilsson
  2011-11-07 16:28         ` Joseph S. Myers
                           ` (2 subsequent siblings)
  3 siblings, 0 replies; 22+ messages in thread
From: Hans-Peter Nilsson @ 2011-11-07 15:38 UTC (permalink / raw)
  To: amacleod; +Cc: hp, hp, gcc-patches, libstdc++, bkoz, rth

> From: Andrew MacLeod <amacleod@redhat.com>
> Date: Mon, 7 Nov 2011 15:44:47 +0100

> Actually, this target has no lock free support whatsoever?  ie, no 
> compare_and_swap instruction, nor an implementation of 
> sync_lock_test_and_set and sync_lock_release?

In CRIS versions where such support would make sense: of course!
For cris-elf with the default multilib: no.

> I think the libstdc++ standard now requires the class atomic_flag to be 
> lock free in order to conform (n3242 29.7.2)

An early error would be the graceful way, even better to
fallback to something that works when simultaneity does not
apply in the system.  I'm on the edge if a linker warning would
be a bonus or badness. :)

> How can we tell when 
> compiling a C++ program whether that is going to be an unresolved 
> external or whether libgcc is going to provide it?

From within gcc,
 if (HAVE_sync_really_basic_operation_somethingorotherpatternname)

which we could translate to builtin_define("__GNU_SYNC_SUPPORT")
if needed.

brgds, H-P

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-07 14:56       ` Andrew MacLeod
  2011-11-07 15:38         ` Hans-Peter Nilsson
@ 2011-11-07 16:28         ` Joseph S. Myers
  2011-11-07 17:24           ` Andrew MacLeod
  2011-11-07 17:43           ` Hans-Peter Nilsson
  2011-11-07 16:32         ` Richard Henderson
  2011-11-08 20:22         ` Hans-Peter Nilsson
  3 siblings, 2 replies; 22+ messages in thread
From: Joseph S. Myers @ 2011-11-07 16:28 UTC (permalink / raw)
  To: Andrew MacLeod
  Cc: Hans-Peter Nilsson, hp, gcc-patches, libstdc++,
	Benjamin Kosnik, Richard Henderson

On Mon, 7 Nov 2011, Andrew MacLeod wrote:

> Actually, this target has no lock free support whatsoever?  ie, no
> compare_and_swap instruction, nor an implementation of sync_lock_test_and_set
> and sync_lock_release?
> 
> I think the libstdc++ standard now requires the class atomic_flag to be lock
> free in order to conform (n3242 29.7.2)
> 
> So I guess this is the situation which all the atomic tests are not even
> suppose to be run since they aren't supported.  My guess is that in the
> previous releases the c++ header files probably provided a locked
> implementation of test_and_set, and so the tests would run.

For bare-metal targets there should maybe be an option to presume there is 
just one thread and map all atomic operations to dumb non-atomic versions, 
which is perfectly valid in such a case.  But that's a new feature; we 
didn't have it for __sync_* either.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-07 14:56       ` Andrew MacLeod
  2011-11-07 15:38         ` Hans-Peter Nilsson
  2011-11-07 16:28         ` Joseph S. Myers
@ 2011-11-07 16:32         ` Richard Henderson
  2011-11-08 20:22         ` Hans-Peter Nilsson
  3 siblings, 0 replies; 22+ messages in thread
From: Richard Henderson @ 2011-11-07 16:32 UTC (permalink / raw)
  To: Andrew MacLeod
  Cc: Hans-Peter Nilsson, hp, gcc-patches, libstdc++, Benjamin Kosnik

On 11/07/2011 06:44 AM, Andrew MacLeod wrote:
> rth: __sync_lock_test_and_set_1  could be provided by libgcc if the
> OS has hooks in it to provide functionality...  How can we tell when
> compiling a C++ program whether that is going to be an unresolved
> external or whether libgcc is going to provide it? I know you have a
> pending patch for libgcc support fo the __atomics, but Im unsure how
> we check this from the compiler

In the pending patch, several of the direct_optabs get transformed
to normal optabs, and have the opportunity to have their libcall
fields filled in.

At which point one checks both optab_handler and optab_libcall for
the availability of the feature.


r~

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-07 16:28         ` Joseph S. Myers
@ 2011-11-07 17:24           ` Andrew MacLeod
  2011-11-07 17:43           ` Hans-Peter Nilsson
  1 sibling, 0 replies; 22+ messages in thread
From: Andrew MacLeod @ 2011-11-07 17:24 UTC (permalink / raw)
  To: Joseph S. Myers
  Cc: Hans-Peter Nilsson, hp, gcc-patches, libstdc++,
	Benjamin Kosnik, Richard Henderson

On 11/07/2011 11:24 AM, Joseph S. Myers wrote:
> On Mon, 7 Nov 2011, Andrew MacLeod wrote:
>
>> Actually, this target has no lock free support whatsoever?  ie, no
>> compare_and_swap instruction, nor an implementation of sync_lock_test_and_set
>> and sync_lock_release?
>>
>> I think the libstdc++ standard now requires the class atomic_flag to be lock
>> free in order to conform (n3242 29.7.2)
>>
>> So I guess this is the situation which all the atomic tests are not even
>> suppose to be run since they aren't supported.  My guess is that in the
>> previous releases the c++ header files probably provided a locked
>> implementation of test_and_set, and so the tests would run.
> For bare-metal targets there should maybe be an option to presume there is
> just one thread and map all atomic operations to dumb non-atomic versions,
> which is perfectly valid in such a case.  But that's a new feature; we
> didn't have it for __sync_* either.
>
Hmm. actually, there is a proposed option flag which I noticed never got 
implemented when I was looking back through stuff on the weekend:
http://gcc.gnu.org/wiki/Atomic/GCCMM/ExecutiveSummary

Exposure to the normal users can be provided through something along the 
lines of:

-fmemory-model=c++0x - Disable data races as per architectural requirements.
-fmemory-model=safe - Disable all data race introductions. (enforce all 
4 internal restrictions.)
-fmemory-model=single - Enable all data races introductions, as they are 
today. (relax all 4 internal restrictions.)

we could do that with -fmemory-model=single and it would be pretty 
natural...and easy.  The just fall back to a load for test and set and 
then atomic_flag would work fine.  Such targets would make that the 
default, and since the option isn't set to C++11, it wouldn't have to be 
conforming anyway.

Mostly I think it the option wasn't implemented because we never 
finished up with the load/store data race work.

We continue to count on  __sync_test_and_set and sync_lock_release for 
targets without a compare and swap operation to provide the atomic_flag 
implementation.

As for all the rest of the atomics, it defined right now that if the 
compiler cannot generate lock free instructions, it generates  a call to 
the external library.  I would suggest on such a limited  target that 
they build the library, and it would provide locked routines for all the 
rest of the external calls.  The library could also be configured for 
single thread operation which would then just provide the operation 
without locks if desired.

A buildable library is forthcoming in the next few months.

Andrew





^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-07 16:28         ` Joseph S. Myers
  2011-11-07 17:24           ` Andrew MacLeod
@ 2011-11-07 17:43           ` Hans-Peter Nilsson
  2011-11-07 18:27             ` Andrew MacLeod
  1 sibling, 1 reply; 22+ messages in thread
From: Hans-Peter Nilsson @ 2011-11-07 17:43 UTC (permalink / raw)
  To: joseph; +Cc: amacleod, hp, hp, gcc-patches, libstdc++, bkoz, rth

> From: "Joseph S. Myers" <joseph@codesourcery.com>
> Date: Mon, 7 Nov 2011 17:24:04 +0100

> On Mon, 7 Nov 2011, Andrew MacLeod wrote:
> 
> > Actually, this target has no lock free support whatsoever?  ie, no
> > compare_and_swap instruction, nor an implementation of sync_lock_test_and_set
> > and sync_lock_release?
> > 
> > I think the libstdc++ standard now requires the class atomic_flag to be lock
> > free in order to conform (n3242 29.7.2)
> > 
> > So I guess this is the situation which all the atomic tests are not even
> > suppose to be run since they aren't supported.  My guess is that in the
> > previous releases the c++ header files probably provided a locked
> > implementation of test_and_set, and so the tests would run.
> 
> For bare-metal targets there should maybe be an option to presume there is 
> just one thread and map all atomic operations to dumb non-atomic versions, 
> which is perfectly valid in such a case.  But that's a new feature; we 
> didn't have it for __sync_* either.

It'd not be a new feature, that's apparently how it worked until
it broke now ...unless you mean something different.

brgds, H-P

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-07 17:43           ` Hans-Peter Nilsson
@ 2011-11-07 18:27             ` Andrew MacLeod
  2011-11-08  6:45               ` Hans-Peter Nilsson
  0 siblings, 1 reply; 22+ messages in thread
From: Andrew MacLeod @ 2011-11-07 18:27 UTC (permalink / raw)
  To: Hans-Peter Nilsson; +Cc: joseph, hp, gcc-patches, libstdc++, bkoz, rth

On 11/07/2011 12:32 PM, Hans-Peter Nilsson wrote:
>> From: "Joseph S. Myers"<joseph@codesourcery.com>
>> Date: Mon, 7 Nov 2011 17:24:04 +0100
>> On Mon, 7 Nov 2011, Andrew MacLeod wrote:
>>
>>> Actually, this target has no lock free support whatsoever?  ie, no
>>> compare_and_swap instruction, nor an implementation of sync_lock_test_and_set
>>> and sync_lock_release?
>>>
>>> I think the libstdc++ standard now requires the class atomic_flag to be lock
>>> free in order to conform (n3242 29.7.2)
>>>
>>> So I guess this is the situation which all the atomic tests are not even
>>> suppose to be run since they aren't supported.  My guess is that in the
>>> previous releases the c++ header files probably provided a locked
>>> implementation of test_and_set, and so the tests would run.
>> For bare-metal targets there should maybe be an option to presume there is
>> just one thread and map all atomic operations to dumb non-atomic versions,
>> which is perfectly valid in such a case.  But that's a new feature; we
>> didn't have it for __sync_* either.
> It'd not be a new feature, that's apparently how it worked until
> it broke now ...unless you mean something different.
>
Libstdc++-v3 use to supply a locked version of class atomic_flag 
(atomic_0.h implemented locked classes)  if there were no lock free 
routines (_GLIBCXX_ATOMIC_BUILTINS_1 was not set to true in configuration):

  /// 29.2 Lock-free Property
#if defined(_GLIBCXX_ATOMIC_BUILTINS_1) && 
defined(_GLIBCXX_ATOMIC_BUILTINS_2) \
&& defined(_GLIBCXX_ATOMIC_BUILTINS_4) && 
defined(_GLIBCXX_ATOMIC_BUILTINS_8)
# define _GLIBCXX_ATOMIC_PROPERTY 2
# define _GLIBCXX_ATOMIC_NAMESPACE __atomic2
#elif defined(_GLIBCXX_ATOMIC_BUILTINS_1)
# define _GLIBCXX_ATOMIC_PROPERTY 1
# define _GLIBCXX_ATOMIC_NAMESPACE __atomic1
#else
# define _GLIBCXX_ATOMIC_PROPERTY 0
# define _GLIBCXX_ATOMIC_NAMESPACE __atomic0
#endif


This meant it would compile and run fine...  That is no longer standard 
compliant, so we cant fall back to that any more.  This is the first 
time we've had to face not being able to supply atomic_flag, so we need 
to decide what to do.

So, what DO we do if there is no basic level of atomic support...  I 
think it is reasonable to have __sync_lock_test_and_set() and 
__sync_lock_release() perform simple loads and stores if we can decide 
how best to communicate to the expanders that we only ever operating in 
a  single threaded environment.  the as-yet unimplemented  
-fmemory-model flag seems like the best bet unless there is something 
else already being set.

Another option would be to have the libstdc++ header files resort to a 
simple load and store rather than calling a __sync routine when they 
know its not present.  Then we aren't tainting the compiler with this 
arguably offbeat requirement.

Andrew


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-07 18:27             ` Andrew MacLeod
@ 2011-11-08  6:45               ` Hans-Peter Nilsson
  2011-11-08 13:43                 ` Andrew MacLeod
  0 siblings, 1 reply; 22+ messages in thread
From: Hans-Peter Nilsson @ 2011-11-08  6:45 UTC (permalink / raw)
  To: amacleod; +Cc: joseph, gcc-patches, libstdc++, bkoz, rth

> From: Andrew MacLeod <amacleod@redhat.com>
> Date: Mon, 7 Nov 2011 19:08:26 +0100

> So, what DO we do if there is no basic level of atomic
> support...

I just realized I may be feeding you an inconsistent
configuration, see the atomicity stuff in
libstdc++-v3/config/cpu/cris.  Is that just obsolete and unused
now or what do I need to add for that to work?

brgds, H-P

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-08  6:45               ` Hans-Peter Nilsson
@ 2011-11-08 13:43                 ` Andrew MacLeod
  2011-11-11 17:49                   ` Benjamin Kosnik
  0 siblings, 1 reply; 22+ messages in thread
From: Andrew MacLeod @ 2011-11-08 13:43 UTC (permalink / raw)
  To: Hans-Peter Nilsson; +Cc: joseph, gcc-patches, libstdc++, bkoz, rth

On 11/08/2011 12:05 AM, Hans-Peter Nilsson wrote:
>
>> So, what DO we do if there is no basic level of atomic
>> support...
> I just realized I may be feeding you an inconsistent
> configuration, see the atomicity stuff in
> libstdc++-v3/config/cpu/cris.  Is that just obsolete and unused
> now or what do I need to add for that to work?
>

You don't need to do anything there. I think that atomicity stuff will 
soon be obsolete, but bkoz will have to answer that question.

It looks to me like that was some gnu atomic extentions which predate 
atomic support in the standard.  In theory, that would all be able to go 
away or be integrated into the gcc machine description with the modern 
patterns, if its not already there.

I expect that for the next release we'll manage to get rid of all the 
little warts and uses of older mechanisms that are sprinkled around.

bkoz: As relates to the existing problem, how is the legacy support 
invoked in compatibility-atomic-c++0x.cc?  That has the old style 
implementation of atomic_flag with a lock, which would allow this target 
to compile...  which is another option perhaps.  or is that purely for 
pervious releases somehow?

Andrew

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-07 14:56       ` Andrew MacLeod
                           ` (2 preceding siblings ...)
  2011-11-07 16:32         ` Richard Henderson
@ 2011-11-08 20:22         ` Hans-Peter Nilsson
  3 siblings, 0 replies; 22+ messages in thread
From: Hans-Peter Nilsson @ 2011-11-08 20:22 UTC (permalink / raw)
  To: amacleod; +Cc: hp, hp, gcc-patches, libstdc++, bkoz, rth

> From: Andrew MacLeod <amacleod@redhat.com>
> Date: Mon, 7 Nov 2011 15:44:47 +0100

> >> On 11/06/2011 07:38 PM, Hans-Peter Nilsson wrote:
> >>> This (formally a change in the range 181027:181034) got me three
> >>> libstdc++ regressions for cris-elf,

> >> yes, I have a final pending patch which didn't make it to the branch
> >> before the merge.  It changes the behaviour of atomic_flag on targets
> >> with no compare_and_swap.  I *think* it will resolve your problem.
> >>
> >> I've attached the early version of the patch which you can try. Its
> >> missing a documentation change I was going to add tomorrow before
> >> submitting, but we can see if it resolves your problem.  Give it a shot
> >> and let me know.
> > Sorry, no it didn't help.  No additional regressions either
> > though, but the undef'd reference changed to two:

> I should also change it so that the compiler issues an error if 
> atomic_thread_fence doesn't resolve to a something since that implies 
> there is no __sync_sychronize() either, which is also minimally expected 
> at this point.  It should never become  an external reference.

JFTR, you already know this; I saw some commits go by that I
thought was addressing this, but didn't, and then I realized
it'd be better to track it using bugzilla, so I entered PR51038.

brgds, H-P

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-08 13:43                 ` Andrew MacLeod
@ 2011-11-11 17:49                   ` Benjamin Kosnik
  2011-11-11 17:56                     ` Andrew MacLeod
  2011-11-11 20:27                     ` Hans-Peter Nilsson
  0 siblings, 2 replies; 22+ messages in thread
From: Benjamin Kosnik @ 2011-11-11 17:49 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: Hans-Peter Nilsson, joseph, gcc-patches, libstdc++, rth


> > I just realized I may be feeding you an inconsistent
> > configuration, see the atomicity stuff in
> > libstdc++-v3/config/cpu/cris.  Is that just obsolete and unused
> > now or what do I need to add for that to work?
> >
> 
> You don't need to do anything there. I think that atomicity stuff
> will soon be obsolete, but bkoz will have to answer that question.
> It looks to me like that was some gnu atomic extentions which predate 
> atomic support in the standard.  In theory, that would all be able to
> go away or be integrated into the gcc machine description with the
> modern patterns, if its not already there.

That is very obsolete and should be removed as it's now just
causing confusion. That was pre-builtin days, let's call this
atomics-try-1. So, all:

config/cpu/*/atomicity.h
./i486/atomicity.h
./i386/atomicity.h
./sparc/atomicity.h
./sh/atomicity.h
./m68k/atomicity.h
./cris/atomicity.h
./hppa/atomicity.h
./generic/atomicity_mutex/atomicity.h
./generic/atomicity_builtins/atomicity.h

ATOMICITY_SRCDIR
ATOMIC_WORD_SRCDIR
ATOMIC_FLAGS

Should go. I'll look in to peeling off this cruft sharpish.
 
> bkoz: As relates to the existing problem, how is the legacy support 
> invoked in compatibility-atomic-c++0x.cc?  That has the old style 
> implementation of atomic_flag with a lock, which would allow this
> target to compile...  which is another option perhaps.  or is that
> purely for pervious releases somehow?

compatibility-atomic-c++0x.cc is the support for previous builtins
attempt, let's call this atomics-try-2. We need to keep these symbols
exported and doing the same thing done in previous releases. (Or else
abi-check will fail.)

If this system used to use a lock to work, then that is what it should
still do. The behavior shouldn't change.

 -benjamin

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-11 17:49                   ` Benjamin Kosnik
@ 2011-11-11 17:56                     ` Andrew MacLeod
  2011-11-11 21:07                       ` Hans-Peter Nilsson
  2011-11-11 23:34                       ` Torvald Riegel
  2011-11-11 20:27                     ` Hans-Peter Nilsson
  1 sibling, 2 replies; 22+ messages in thread
From: Andrew MacLeod @ 2011-11-11 17:56 UTC (permalink / raw)
  To: Benjamin Kosnik; +Cc: Hans-Peter Nilsson, joseph, gcc-patches, libstdc++, rth

On 11/11/2011 12:43 AM, Benjamin Kosnik wrote:
>
>> bkoz: As relates to the existing problem, how is the legacy support
>> invoked in compatibility-atomic-c++0x.cc?  That has the old style
>> implementation of atomic_flag with a lock, which would allow this
>> target to compile...  which is another option perhaps.  or is that
>> purely for pervious releases somehow?
> compatibility-atomic-c++0x.cc is the support for previous builtins
> attempt, let's call this atomics-try-2. We need to keep these symbols
> exported and doing the same thing done in previous releases. (Or else
> abi-check will fail.)
>
> If this system used to use a lock to work, then that is what it should
> still do. The behavior shouldn't change.
>
I think there is also an argument for single threaded-ness vs multi 
threaded.  If there is no atomic support and its single threaded, we 
don't really need the lock... and I'm not sure how you can detect the 
change in behaviour if test_and_set and clear just store 1 and 0 rather 
than create alock, then do the store of 1 or 0.

If the target is multithreaded, well, we'll have to go to a lock I 
guess...   Are there any multithreaded targets without atomic support?  
ie, is this one?

Andrew



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-11 17:49                   ` Benjamin Kosnik
  2011-11-11 17:56                     ` Andrew MacLeod
@ 2011-11-11 20:27                     ` Hans-Peter Nilsson
  1 sibling, 0 replies; 22+ messages in thread
From: Hans-Peter Nilsson @ 2011-11-11 20:27 UTC (permalink / raw)
  To: bkoz; +Cc: amacleod, hp, joseph, gcc-patches, libstdc++, rth

> From: Benjamin Kosnik <bkoz@redhat.com>
> Date: Fri, 11 Nov 2011 06:43:29 +0100

> So, all:
> 
> config/cpu/*/atomicity.h

And config/cpu/*/atomic_word.h presumably?

> Should go. I'll look in to peeling off this cruft sharpish.

brgds, H-P

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-11 17:56                     ` Andrew MacLeod
@ 2011-11-11 21:07                       ` Hans-Peter Nilsson
  2011-11-11 23:34                       ` Torvald Riegel
  1 sibling, 0 replies; 22+ messages in thread
From: Hans-Peter Nilsson @ 2011-11-11 21:07 UTC (permalink / raw)
  To: amacleod; +Cc: bkoz, hp, joseph, gcc-patches, libstdc++, rth

> From: Andrew MacLeod <amacleod@redhat.com>
> Date: Fri, 11 Nov 2011 18:45:11 +0100

> On 11/11/2011 12:43 AM, Benjamin Kosnik wrote:
> I think there is also an argument for single threaded-ness vs multi 
> threaded.  If there is no atomic support and its single threaded, we 
> don't really need the lock... and I'm not sure how you can detect the 
> change in behaviour if test_and_set and clear just store 1 and 0 rather 
> than create alock, then do the store of 1 or 0.
> 
> If the target is multithreaded, well, we'll have to go to a lock I 
> guess...   Are there any multithreaded targets without atomic support?  
> ie, is this one?

No, cris-elf is not multithreaded target.

(FWIW, cris-*-linux* and crisv32-*-linux* are, but the lack of
update to the atomicity support for them is a port bug.)

brgds, H-P

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: cxx-mem-model merge [6 of 9] - libstdc++-v3
  2011-11-11 17:56                     ` Andrew MacLeod
  2011-11-11 21:07                       ` Hans-Peter Nilsson
@ 2011-11-11 23:34                       ` Torvald Riegel
  1 sibling, 0 replies; 22+ messages in thread
From: Torvald Riegel @ 2011-11-11 23:34 UTC (permalink / raw)
  To: Andrew MacLeod
  Cc: Benjamin Kosnik, Hans-Peter Nilsson, joseph, gcc-patches, libstdc++, rth

On Fri, 2011-11-11 at 12:45 -0500, Andrew MacLeod wrote:
> On 11/11/2011 12:43 AM, Benjamin Kosnik wrote:
> >
> >> bkoz: As relates to the existing problem, how is the legacy support
> >> invoked in compatibility-atomic-c++0x.cc?  That has the old style
> >> implementation of atomic_flag with a lock, which would allow this
> >> target to compile...  which is another option perhaps.  or is that
> >> purely for pervious releases somehow?
> > compatibility-atomic-c++0x.cc is the support for previous builtins
> > attempt, let's call this atomics-try-2. We need to keep these symbols
> > exported and doing the same thing done in previous releases. (Or else
> > abi-check will fail.)
> >
> > If this system used to use a lock to work, then that is what it should
> > still do. The behavior shouldn't change.
> >
> I think there is also an argument for single threaded-ness vs multi 
> threaded.  If there is no atomic support and its single threaded, we 
> don't really need the lock... and I'm not sure how you can detect the 
> change in behaviour if test_and_set and clear just store 1 and 0 rather 
> than create alock, then do the store of 1 or 0.

Also, if you're replacing it with atomic ops you can't see different
behavior because, well, they are atomic.  However, this requires that
_nobody_ tries to synchronize using this lock anymore (only observing
the lock is fine, but you must never modify it).  Likewise on a
single-threaded target.

Torvald

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2011-11-11 23:14 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-03 23:52 cxx-mem-model merge [6 of 9] - libstdc++-v3 Andrew MacLeod
2011-11-04 18:17 ` Jeff Law
2011-11-04 18:53   ` Andrew MacLeod
2011-11-07  0:54 ` Hans-Peter Nilsson
2011-11-07  4:48   ` Andrew MacLeod
2011-11-07 11:36     ` Hans-Peter Nilsson
2011-11-07 14:41       ` Andrew MacLeod
2011-11-07 14:56       ` Andrew MacLeod
2011-11-07 15:38         ` Hans-Peter Nilsson
2011-11-07 16:28         ` Joseph S. Myers
2011-11-07 17:24           ` Andrew MacLeod
2011-11-07 17:43           ` Hans-Peter Nilsson
2011-11-07 18:27             ` Andrew MacLeod
2011-11-08  6:45               ` Hans-Peter Nilsson
2011-11-08 13:43                 ` Andrew MacLeod
2011-11-11 17:49                   ` Benjamin Kosnik
2011-11-11 17:56                     ` Andrew MacLeod
2011-11-11 21:07                       ` Hans-Peter Nilsson
2011-11-11 23:34                       ` Torvald Riegel
2011-11-11 20:27                     ` Hans-Peter Nilsson
2011-11-07 16:32         ` Richard Henderson
2011-11-08 20:22         ` Hans-Peter Nilsson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).