diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2015-01-18 14:25:22 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2015-01-18 14:25:22 +0000 |
commit | 87361f3098d399531bc329b2ad71f6a530742567 (patch) | |
tree | 5d05b401b06caecf052d80d415985a05f47ea18a | |
parent | e207c522623c3d3620416b5332b8a6d8644a1f06 (diff) | |
download | gcc-87361f3098d399531bc329b2ad71f6a530742567.zip gcc-87361f3098d399531bc329b2ad71f6a530742567.tar.gz gcc-87361f3098d399531bc329b2ad71f6a530742567.tar.bz2 |
atomic_futex.h: Use mutex and condition_variable when atomic int is not lock-free.
* include/bits/atomic_futex.h: Use mutex and condition_variable when
atomic int is not lock-free. Make member variables private.
* src/c++11/futex.cc: Likewise.
From-SVN: r219815
-rw-r--r-- | libstdc++-v3/ChangeLog | 6 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/atomic_futex.h | 91 | ||||
-rw-r--r-- | libstdc++-v3/src/c++11/futex.cc | 2 |
3 files changed, 52 insertions, 47 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index e0bfa81..178da52 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,9 @@ +2015-01-18 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/atomic_futex.h: Use mutex and condition_variable when + atomic int is not lock-free. Make member variables private. + * src/c++11/futex.cc: Likewise. + 2015-01-17 Jonathan Wakely <jwakely@redhat.com> PR libstdc++/64638 diff --git a/libstdc++-v3/include/bits/atomic_futex.h b/libstdc++-v3/include/bits/atomic_futex.h index 2673604..51b9c7e 100644 --- a/libstdc++-v3/include/bits/atomic_futex.h +++ b/libstdc++-v3/include/bits/atomic_futex.h @@ -35,7 +35,7 @@ #include <bits/c++config.h> #include <atomic> #include <chrono> -#if !defined(_GLIBCXX_HAVE_LINUX_FUTEX) +#if ! (defined(_GLIBCXX_HAVE_LINUX_FUTEX) && ATOMIC_INT_LOCK_FREE > 1) #include <mutex> #include <condition_variable> #endif @@ -49,7 +49,7 @@ namespace std _GLIBCXX_VISIBILITY(default) _GLIBCXX_BEGIN_NAMESPACE_VERSION #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) -#if defined(_GLIBCXX_HAVE_LINUX_FUTEX) +#if defined(_GLIBCXX_HAVE_LINUX_FUTEX) && ATOMIC_INT_LOCK_FREE > 1 struct __atomic_futex_unsigned_base { // Returns false iff a timeout occurred. @@ -62,16 +62,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; template <unsigned _Waiter_bit = 0x80000000> - struct __atomic_futex_unsigned : __atomic_futex_unsigned_base + class __atomic_futex_unsigned : __atomic_futex_unsigned_base { typedef chrono::system_clock __clock_t; - // XXX We expect this to be lock-free, and having the payload at offset 0. -#if ATOMIC_INT_LOCK_FREE < 2 -# error We require lock-free atomic operations on int -#endif + // This must be lock-free and at offset 0. atomic<unsigned> _M_data; + public: + explicit __atomic_futex_unsigned(unsigned __data) : _M_data(__data) { } @@ -82,7 +81,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } private: - // If a timeout occurs, returns a current value after the timeout; // otherwise, returns the operand's value if equal is true or a different // value if equal is false. @@ -165,26 +163,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Returns false iff a timeout occurred. template<typename _Rep, typename _Period> - _GLIBCXX_ALWAYS_INLINE bool - _M_load_when_equal_for(unsigned __val, memory_order __mo, - const chrono::duration<_Rep, _Period>& __rtime) - { - return _M_load_when_equal_until(__val, __mo, __clock_t::now() + __rtime); - } + _GLIBCXX_ALWAYS_INLINE bool + _M_load_when_equal_for(unsigned __val, memory_order __mo, + const chrono::duration<_Rep, _Period>& __rtime) + { + return _M_load_when_equal_until(__val, __mo, + __clock_t::now() + __rtime); + } // Returns false iff a timeout occurred. template<typename _Clock, typename _Duration> - _GLIBCXX_ALWAYS_INLINE bool - _M_load_when_equal_until(unsigned __val, memory_order __mo, - const chrono::time_point<_Clock, _Duration>& __atime) - { - // DR 887 - Sync unknown clock to known clock. - const typename _Clock::time_point __c_entry = _Clock::now(); - const __clock_t::time_point __s_entry = __clock_t::now(); - const auto __delta = __atime - __c_entry; - const auto __s_atime = __s_entry + __delta; - return _M_load_when_equal_until(__val, __mo, __s_atime); - } + _GLIBCXX_ALWAYS_INLINE bool + _M_load_when_equal_until(unsigned __val, memory_order __mo, + const chrono::time_point<_Clock, _Duration>& __atime) + { + // DR 887 - Sync unknown clock to known clock. + const typename _Clock::time_point __c_entry = _Clock::now(); + const __clock_t::time_point __s_entry = __clock_t::now(); + const auto __delta = __atime - __c_entry; + const auto __s_atime = __s_entry + __delta; + return _M_load_when_equal_until(__val, __mo, __s_atime); + } // Returns false iff a timeout occurred. template<typename _Duration> @@ -207,16 +206,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (_M_data.exchange(__val, __mo) & _Waiter_bit) _M_futex_notify_all(__futex); } - }; -#else // !_GLIBCXX_HAVE_LINUX_FUTEX +#else // ! (_GLIBCXX_HAVE_LINUX_FUTEX && ATOMIC_INT_LOCK_FREE > 1) // If futexes are not available, use a mutex and a condvar to wait. // Because we access the data only within critical sections, all accesses // are sequentially consistent; thus, we satisfy any provided memory_order. template <unsigned _Waiter_bit = 0x80000000> - struct __atomic_futex_unsigned + class __atomic_futex_unsigned { typedef chrono::system_clock __clock_t; @@ -224,6 +222,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION mutex _M_mutex; condition_variable _M_condvar; + public: + explicit __atomic_futex_unsigned(unsigned __data) : _M_data(__data) { } @@ -252,24 +252,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _Rep, typename _Period> - _GLIBCXX_ALWAYS_INLINE bool - _M_load_when_equal_for(unsigned __val, memory_order __mo, - const chrono::duration<_Rep, _Period>& __rtime) - { - unique_lock<mutex> __lock(_M_mutex); - return _M_condvar.wait_for(__lock, __rtime, - [&] { return _M_data == __val;}); - } + _GLIBCXX_ALWAYS_INLINE bool + _M_load_when_equal_for(unsigned __val, memory_order __mo, + const chrono::duration<_Rep, _Period>& __rtime) + { + unique_lock<mutex> __lock(_M_mutex); + return _M_condvar.wait_for(__lock, __rtime, + [&] { return _M_data == __val;}); + } template<typename _Clock, typename _Duration> - _GLIBCXX_ALWAYS_INLINE bool - _M_load_when_equal_until(unsigned __val, memory_order __mo, - const chrono::time_point<_Clock, _Duration>& __atime) - { - unique_lock<mutex> __lock(_M_mutex); - return _M_condvar.wait_until(__lock, __atime, - [&] { return _M_data == __val;}); - } + _GLIBCXX_ALWAYS_INLINE bool + _M_load_when_equal_until(unsigned __val, memory_order __mo, + const chrono::time_point<_Clock, _Duration>& __atime) + { + unique_lock<mutex> __lock(_M_mutex); + return _M_condvar.wait_until(__lock, __atime, + [&] { return _M_data == __val;}); + } _GLIBCXX_ALWAYS_INLINE void _M_store_notify_all(unsigned __val, memory_order __mo) @@ -278,10 +278,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_data = __val; _M_condvar.notify_all(); } - }; -#endif // _GLIBCXX_HAVE_LINUX_FUTEX +#endif // _GLIBCXX_HAVE_LINUX_FUTEX && ATOMIC_INT_LOCK_FREE > 1 #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1 _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/src/c++11/futex.cc b/libstdc++-v3/src/c++11/futex.cc index ad766c8..f24b44e 100644 --- a/libstdc++-v3/src/c++11/futex.cc +++ b/libstdc++-v3/src/c++11/futex.cc @@ -23,7 +23,7 @@ // <http://www.gnu.org/licenses/>. #include <bits/c++config.h> -#if defined(_GLIBCXX_HAVE_LINUX_FUTEX) +#if defined(_GLIBCXX_HAVE_LINUX_FUTEX) && ATOMIC_INT_LOCK_FREE > 1 #include <bits/atomic_futex.h> #include <chrono> #include <climits> |