diff options
-rw-r--r-- | libcxx/include/__config | 8 | ||||
-rw-r--r-- | libcxx/include/__mutex_base | 22 | ||||
-rw-r--r-- | libcxx/src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | libcxx/src/mutex.cpp | 5 | ||||
-rw-r--r-- | libcxx/src/mutex_destructor.cpp | 51 | ||||
-rw-r--r-- | libcxx/test/std/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/default.pass.cpp | 6 |
6 files changed, 73 insertions, 20 deletions
diff --git a/libcxx/include/__config b/libcxx/include/__config index 51ac16cc572..1ed51699932 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -1097,6 +1097,14 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container( _LIBCPP_HAS_NO_THREADS is defined. #endif +// The Apple, glibc, and Bionic implementation of pthreads implements +// pthread_mutex_destroy as nop for regular mutexes. +// TODO(EricWF): Enable this optimization on Apple and Bionic platforms after +// speaking to their respective stakeholders. +#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && defined(__GLIBC__) +# define _LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION +#endif + // Systems that use capability-based security (FreeBSD with Capsicum, // Nuxi CloudABI) may only provide local filesystem access (using *at()). // Functions like open(), rename(), unlink() and stat() should not be diff --git a/libcxx/include/__mutex_base b/libcxx/include/__mutex_base index 0c34a3bf709..61abae979ac 100644 --- a/libcxx/include/__mutex_base +++ b/libcxx/include/__mutex_base @@ -36,28 +36,24 @@ _LIBCPP_BEGIN_NAMESPACE_STD # endif #endif // _LIBCPP_THREAD_SAFETY_ANNOTATION + class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex { -#ifndef _LIBCPP_CXX03_LANG __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER; -#else - __libcpp_mutex_t __m_; -#endif public: _LIBCPP_INLINE_VISIBILITY -#ifndef _LIBCPP_CXX03_LANG - constexpr mutex() = default; + _LIBCPP_CONSTEXPR mutex() = default; + + mutex(const mutex&) = delete; + mutex& operator=(const mutex&) = delete; + +#if defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION) + ~mutex() = default; #else - mutex() _NOEXCEPT {__m_ = (__libcpp_mutex_t)_LIBCPP_MUTEX_INITIALIZER;} -#endif ~mutex() _NOEXCEPT; +#endif -private: - mutex(const mutex&);// = delete; - mutex& operator=(const mutex&);// = delete; - -public: void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true)); void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()); diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt index 2a8ff2c2d89..56d7b9888e3 100644 --- a/libcxx/src/CMakeLists.txt +++ b/libcxx/src/CMakeLists.txt @@ -22,6 +22,7 @@ set(LIBCXX_SOURCES locale.cpp memory.cpp mutex.cpp + mutex_destructor.cpp new.cpp optional.cpp random.cpp diff --git a/libcxx/src/mutex.cpp b/libcxx/src/mutex.cpp index 33a8197dadf..0d69d7cacfa 100644 --- a/libcxx/src/mutex.cpp +++ b/libcxx/src/mutex.cpp @@ -25,10 +25,7 @@ const defer_lock_t defer_lock = {}; const try_to_lock_t try_to_lock = {}; const adopt_lock_t adopt_lock = {}; -mutex::~mutex() _NOEXCEPT -{ - __libcpp_mutex_destroy(&__m_); -} +// ~mutex is defined elsewhere void mutex::lock() diff --git a/libcxx/src/mutex_destructor.cpp b/libcxx/src/mutex_destructor.cpp new file mode 100644 index 00000000000..3a6b6b55eeb --- /dev/null +++ b/libcxx/src/mutex_destructor.cpp @@ -0,0 +1,51 @@ +//===--------------------- mutex_destructor.cpp ---------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Define ~mutex. +// +// On some platforms ~mutex has been made trivial and the definition is only +// provided for ABI compatibility. +// +// In order to avoid ODR violations within libc++ itself, we need to ensure +// that *nothing* sees the non-trivial mutex declaration. For this reason +// we re-declare the entire class in this file instead of using +// _LIBCPP_BUILDING_LIBRARY to change the definition in the headers. + +#include "__config" +#include "__threading_support" + +#if !defined(_LIBCPP_HAS_NO_THREADS) +#if _LIBCPP_ABI_VERSION == 1 || !defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION) +#define NEEDS_MUTEX_DESTRUCTOR +#endif +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifdef NEEDS_MUTEX_DESTRUCTOR +class _LIBCPP_TYPE_VIS mutex +{ + __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER; + +public: + _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY + constexpr mutex() = default; + mutex(const mutex&) = delete; + mutex& operator=(const mutex&) = delete; + ~mutex() noexcept; +}; + + +mutex::~mutex() _NOEXCEPT +{ + __libcpp_mutex_destroy(&__m_); +} + +#endif // !_LIBCPP_HAS_NO_THREADS +_LIBCPP_END_NAMESPACE_STD + diff --git a/libcxx/test/std/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/default.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/default.pass.cpp index e2fd416b6e4..f754e7b7031 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/default.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/default.pass.cpp @@ -21,8 +21,8 @@ int main(int, char**) { - static_assert(std::is_nothrow_default_constructible<std::mutex>::value, ""); - std::mutex m; - + static_assert(std::is_nothrow_default_constructible<std::mutex>::value, ""); + std::mutex m; + ((void)m); return 0; } |