----- Original Message ----- > On 07/26/2013 08:42 PM, Nathan Froyd wrote: > > Sure, I can do that. For maximum effectiveness, it'd be good to have it > > check the specializations for atomic<>, too. Is there something in the > > libstdc++ testsuite for iterating template instantiations over a list of > > types, or do I have to roll the list myself? > testsuite/29_atomics already uses testsuite_common_types.h
New patch, this time with tests. Let me know if test placement, etc. need adjusting. Tested on x86_64-unknown-linux-gnu. OK for commit to trunk and active branches? -Nathan * include/std/atomic (compare_exchange_weak, compare_exchange_strong): Add call to __cmpexch_failure_order. * testsuite/util/testsuite_common_types.h (compare_exchange_order_lowering): New generator. * testsuite/29_atomics/atomic/requirements/compare_exchange_lowering.cc: New test. diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index ac2cb45..3b79d91 100644 diff --git a/libstdc++-v3/include/std/atomic b/libstdc++-v3/include/std/atomic index 813f574..2d66729 100644 --- a/libstdc++-v3/include/std/atomic +++ b/libstdc++-v3/include/std/atomic @@ -252,12 +252,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION bool compare_exchange_weak(_Tp& __e, _Tp __i, memory_order __m = memory_order_seq_cst) noexcept - { return compare_exchange_weak(__e, __i, __m, __m); } + { return compare_exchange_weak(__e, __i, __m, + __cmpexch_failure_order(__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); } + { return compare_exchange_weak(__e, __i, __m, + __cmpexch_failure_order(__m)); } bool compare_exchange_strong(_Tp& __e, _Tp __i, memory_order __s, @@ -276,12 +278,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION bool compare_exchange_strong(_Tp& __e, _Tp __i, memory_order __m = memory_order_seq_cst) noexcept - { return compare_exchange_strong(__e, __i, __m, __m); } + { return compare_exchange_strong(__e, __i, __m, + __cmpexch_failure_order(__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); } + { return compare_exchange_strong(__e, __i, __m, + __cmpexch_failure_order(__m)); } }; diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/requirements/compare_exchange_lowering.cc b/libstdc++-v3/testsuite/29_atomics/atomic/requirements/compare_exchange_lowering.cc new file mode 100644 index 0000000..75e7406 --- /dev/null +++ b/libstdc++-v3/testsuite/29_atomics/atomic/requirements/compare_exchange_lowering.cc @@ -0,0 +1,65 @@ +// { dg-options "-std=gnu++0x" } +// { dg-do compile } + +// Copyright (C) 2008-2013 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. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <atomic> +#include <testsuite_common_types.h> + +#define TEST_ALL_ORDERS() \ + do { \ + ORDER_TEST(std::memory_order_relaxed); \ + ORDER_TEST(std::memory_order_consume); \ + ORDER_TEST(std::memory_order_acquire); \ + ORDER_TEST(std::memory_order_release); \ + ORDER_TEST(std::memory_order_acq_rel); \ + ORDER_TEST(std::memory_order_seq_cst); \ + } while(0) + +void test01() +{ +#define ORDER_TEST(ORDER) \ + do { \ + __gnu_test::compare_exchange_order_lowering<ORDER> test; \ + __gnu_cxx::typelist::apply_generator(test, \ + __gnu_test::integral_types::type()); \ + } while (0); + TEST_ALL_ORDERS(); +#undef ORDER_TEST + + enum e { a, b, c }; +#define ORDER_TEST(ORDER) \ + do { \ + std::atomic<e> x(a); \ + e expected = a; \ + x.compare_exchange_strong(expected, b, ORDER); \ + x.compare_exchange_weak(expected, c, ORDER); \ + } while (0); + TEST_ALL_ORDERS(); +#undef ORDER_TEST + +#define ORDER_TEST(ORDER) \ + do { \ + std::atomic<void*> x(nullptr); \ + void* expected = nullptr; \ + x.compare_exchange_strong(expected, nullptr, ORDER); \ + x.compare_exchange_weak(expected, nullptr, ORDER); \ + } while (0); + TEST_ALL_ORDERS(); +#undef ORDER_TEST +} diff --git a/libstdc++-v3/testsuite/util/testsuite_common_types.h b/libstdc++-v3/testsuite/util/testsuite_common_types.h index 54d6a75..e7f081b 100644 --- a/libstdc++-v3/testsuite/util/testsuite_common_types.h +++ b/libstdc++-v3/testsuite/util/testsuite_common_types.h @@ -872,5 +872,22 @@ namespace __gnu_test = &_Concept::__constraint; } }; + +#if __cplusplus >= 201103L + // Generator to test lowering requirements for compare-and-exchange. + template<std::memory_order order> + struct compare_exchange_order_lowering + { + template<typename _Tp> + void + operator()() + { + std::atomic<_Tp> x; + _Tp __expected = 0; + x.compare_exchange_strong(__expected, 1, order); + x.compare_exchange_weak(__expected, 1, order); + } + }; +#endif } // namespace __gnu_test #endif