summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libcxx/include/memory12
-rw-r--r--libcxx/include/mutex4
-rw-r--r--libcxx/src/mutex.cpp5
3 files changed, 15 insertions, 6 deletions
diff --git a/libcxx/include/memory b/libcxx/include/memory
index 31f58b7c0a4..8cb094e6b6a 100644
--- a/libcxx/include/memory
+++ b/libcxx/include/memory
@@ -663,6 +663,18 @@ _ValueType __libcpp_relaxed_load(_ValueType const* __value) {
#endif
}
+template <class _ValueType>
+inline _LIBCPP_ALWAYS_INLINE
+_ValueType __libcpp_acquire_load(_ValueType const* __value) {
+#if !defined(_LIBCPP_HAS_NO_THREADS) && \
+ defined(__ATOMIC_ACQUIRE) && \
+ (__has_builtin(__atomic_load_n) || _GNUC_VER >= 407)
+ return __atomic_load_n(__value, __ATOMIC_ACQUIRE);
+#else
+ return *__value;
+#endif
+}
+
// addressof moved to <__functional_base>
template <class _Tp> class allocator;
diff --git a/libcxx/include/mutex b/libcxx/include/mutex
index c047cf943e8..79befbeb56f 100644
--- a/libcxx/include/mutex
+++ b/libcxx/include/mutex
@@ -574,7 +574,7 @@ inline _LIBCPP_INLINE_VISIBILITY
void
call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args)
{
- if (__libcpp_relaxed_load(&__flag.__state_) != ~0ul)
+ if (__libcpp_acquire_load(&__flag.__state_) != ~0ul)
{
typedef tuple<_Callable&&, _Args&&...> _Gp;
_Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...);
@@ -590,7 +590,7 @@ inline _LIBCPP_INLINE_VISIBILITY
void
call_once(once_flag& __flag, _Callable& __func)
{
- if (__libcpp_relaxed_load(&__flag.__state_) != ~0ul)
+ if (__libcpp_acquire_load(&__flag.__state_) != ~0ul)
{
__call_once_param<_Callable> __p(__func);
__call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>);
diff --git a/libcxx/src/mutex.cpp b/libcxx/src/mutex.cpp
index 9f808ca5076..7226abc6a51 100644
--- a/libcxx/src/mutex.cpp
+++ b/libcxx/src/mutex.cpp
@@ -199,9 +199,6 @@ static __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER;
static __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER;
#endif
-/// NOTE: Changes to flag are done via relaxed atomic stores
-/// even though the accesses are protected by a mutex because threads
-/// just entering 'call_once` concurrently read from flag.
void
__call_once(volatile unsigned long& flag, void* arg, void(*func)(void*))
{
@@ -238,7 +235,7 @@ __call_once(volatile unsigned long& flag, void* arg, void(*func)(void*))
__libcpp_mutex_unlock(&mut);
func(arg);
__libcpp_mutex_lock(&mut);
- __libcpp_relaxed_store(&flag, ~0ul);
+ __libcpp_atomic_store(&flag, ~0ul, _AO_Release);
__libcpp_mutex_unlock(&mut);
__libcpp_condvar_broadcast(&cv);
#ifndef _LIBCPP_NO_EXCEPTIONS
OpenPOWER on IntegriCloud