From 87361f3098d399531bc329b2ad71f6a530742567 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Sun, 18 Jan 2015 14:25:22 +0000 Subject: [PATCH] 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 --- libstdc++-v3/ChangeLog | 6 ++ libstdc++-v3/include/bits/atomic_futex.h | 91 ++++++++++++------------ 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 e0bfa814bd3..178da523b96 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,9 @@ +2015-01-18 Jonathan Wakely + + * 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 PR libstdc++/64638 diff --git a/libstdc++-v3/include/bits/atomic_futex.h b/libstdc++-v3/include/bits/atomic_futex.h index 2673604e995..51b9c7e5737 100644 --- a/libstdc++-v3/include/bits/atomic_futex.h +++ b/libstdc++-v3/include/bits/atomic_futex.h @@ -35,7 +35,7 @@ #include #include #include -#if !defined(_GLIBCXX_HAVE_LINUX_FUTEX) +#if ! (defined(_GLIBCXX_HAVE_LINUX_FUTEX) && ATOMIC_INT_LOCK_FREE > 1) #include #include #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 - 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 _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 - _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 - _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 @@ -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 - 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 - _GLIBCXX_ALWAYS_INLINE bool - _M_load_when_equal_for(unsigned __val, memory_order __mo, - const chrono::duration<_Rep, _Period>& __rtime) - { - unique_lock __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 __lock(_M_mutex); + return _M_condvar.wait_for(__lock, __rtime, + [&] { return _M_data == __val;}); + } template - _GLIBCXX_ALWAYS_INLINE bool - _M_load_when_equal_until(unsigned __val, memory_order __mo, - const chrono::time_point<_Clock, _Duration>& __atime) - { - unique_lock __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 __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 ad766c83229..f24b44e5a8f 100644 --- a/libstdc++-v3/src/c++11/futex.cc +++ b/libstdc++-v3/src/c++11/futex.cc @@ -23,7 +23,7 @@ // . #include -#if defined(_GLIBCXX_HAVE_LINUX_FUTEX) +#if defined(_GLIBCXX_HAVE_LINUX_FUTEX) && ATOMIC_INT_LOCK_FREE > 1 #include #include #include -- 2.30.2