diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index d0a494b467f0da2a4ec60fbe893b6b430f86b895..edb17eae0c0cc5564f1682dfb21be97accb57e2f 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,12 @@ +2013-07-29 Nathan Froyd <froydnj@gcc.gnu.org> + + * 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. + 2013-07-25 Paolo Carlini <paolo.carlini@oracle.com> * include/std/complex (pow(const complex<>&, int)): Enable in diff --git a/libstdc++-v3/include/std/atomic b/libstdc++-v3/include/std/atomic index 813f5741a1053a8cf06a03d19d94758a7f6d17b2..2d66729629e53fafc83f4e2ab512ef84bf28a5b9 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 0000000000000000000000000000000000000000..7e5d58f418ee2705713210cd76eaaf2496fd93ee --- /dev/null +++ b/libstdc++-v3/testsuite/29_atomics/atomic/requirements/compare_exchange_lowering.cc @@ -0,0 +1,65 @@ +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +// Copyright (C) 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 54d6a753e3672c25e9ec0be42b69c8497e3dd95f..12e3921aaf2b953c9c7f2e1d1e716226011579f5 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 _Torder> + struct compare_exchange_order_lowering + { + template<typename _Tp> + void + operator()() + { + std::atomic<_Tp> __x; + _Tp __expected = 0; + __x.compare_exchange_strong(__expected, 1, _Torder); + __x.compare_exchange_weak(__expected, 1, _Torder); + } + }; +#endif } // namespace __gnu_test #endif