From cf7d4f543c73c2707e0c53bae1e7b8419e12b871 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Sun, 5 Nov 2023 19:08:24 -0500 Subject: [libc++] Handle threads-related .cpp files like we do all other source files (#71100) Source files in libc++ are added to the CMake targets only if they are required by the configuration. We do this pretty consistently for all configurations like no-filesystem, no-random-device, etc. but we didn't do it for no-threads. This patch makes this consistent for no-threads, which is helpful in reducing the amount of work required to port libc++ to some platforms without threads. Indeed, with the previous approach, several threads-related source files would end up including headers that might fail to compile properly on some platforms. This issue is sidestepped entirely by making the approach for no-threads consistent with the other configurations. --- libcxx/src/CMakeLists.txt | 24 ++++++---- libcxx/src/atomic.cpp | 5 -- libcxx/src/barrier.cpp | 6 --- libcxx/src/call_once.cpp | 72 ++++++++++++++++++++++++++++ libcxx/src/condition_variable.cpp | 6 --- libcxx/src/condition_variable_destructor.cpp | 6 +-- libcxx/src/future.cpp | 6 --- libcxx/src/mutex.cpp | 62 +----------------------- libcxx/src/mutex_destructor.cpp | 8 ++-- libcxx/src/shared_mutex.cpp | 16 ++----- libcxx/src/thread.cpp | 6 --- 11 files changed, 99 insertions(+), 118 deletions(-) create mode 100644 libcxx/src/call_once.cpp (limited to 'libcxx/src') diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt index e57fbf1..156dbe8 100644 --- a/libcxx/src/CMakeLists.txt +++ b/libcxx/src/CMakeLists.txt @@ -4,13 +4,10 @@ set(LIBCXX_LIB_CMAKEFILES_DIR "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTOR set(LIBCXX_SOURCES algorithm.cpp any.cpp - atomic.cpp - barrier.cpp bind.cpp + call_once.cpp charconv.cpp chrono.cpp - condition_variable.cpp - condition_variable_destructor.cpp error_category.cpp exception.cpp filesystem/filesystem_clock.cpp @@ -18,7 +15,6 @@ set(LIBCXX_SOURCES filesystem/path_parser.h filesystem/path.cpp functional.cpp - future.cpp hash.cpp include/apple_availability.h include/atomic_support.h @@ -37,8 +33,6 @@ set(LIBCXX_SOURCES legacy_pointer_safety.cpp memory.cpp memory_resource.cpp - mutex.cpp - mutex_destructor.cpp new_handler.cpp new_helpers.cpp optional.cpp @@ -47,7 +41,6 @@ set(LIBCXX_SOURCES ryu/d2fixed.cpp ryu/d2s.cpp ryu/f2s.cpp - shared_mutex.cpp stdexcept.cpp string.cpp support/runtime/exception_fallback.ipp @@ -62,7 +55,6 @@ set(LIBCXX_SOURCES support/runtime/stdexcept_default.ipp support/runtime/stdexcept_vcruntime.ipp system_error.cpp - thread.cpp typeinfo.cpp valarray.cpp variant.cpp @@ -70,6 +62,20 @@ set(LIBCXX_SOURCES verbose_abort.cpp ) +if (LIBCXX_ENABLE_THREADS) + list(APPEND LIBCXX_SOURCES + atomic.cpp + barrier.cpp + condition_variable_destructor.cpp + condition_variable.cpp + future.cpp + mutex_destructor.cpp + mutex.cpp + shared_mutex.cpp + thread.cpp + ) +endif() + if (LIBCXX_ENABLE_RANDOM_DEVICE) list(APPEND LIBCXX_SOURCES random.cpp diff --git a/libcxx/src/atomic.cpp b/libcxx/src/atomic.cpp index fc90a1f..133774b 100644 --- a/libcxx/src/atomic.cpp +++ b/libcxx/src/atomic.cpp @@ -6,9 +6,6 @@ // //===----------------------------------------------------------------------===// -#include <__config> -#ifndef _LIBCPP_HAS_NO_THREADS - #include <__thread/timed_backoff_policy.h> #include #include @@ -219,5 +216,3 @@ void __libcpp_atomic_wait(__cxx_atomic_contention_t const volatile* __location, } _LIBCPP_END_NAMESPACE_STD - -#endif //_LIBCPP_HAS_NO_THREADS diff --git a/libcxx/src/barrier.cpp b/libcxx/src/barrier.cpp index 8ce2c04..3242e08 100644 --- a/libcxx/src/barrier.cpp +++ b/libcxx/src/barrier.cpp @@ -6,10 +6,6 @@ // //===----------------------------------------------------------------------===// -#include <__config> - -#ifndef _LIBCPP_HAS_NO_THREADS - #include #include @@ -93,5 +89,3 @@ void __destroy_barrier_algorithm_base(__barrier_algorithm_base* __barrier) #endif // !defined(_LIBCPP_HAS_NO_TREE_BARRIER) _LIBCPP_END_NAMESPACE_STD - -#endif //_LIBCPP_HAS_NO_THREADS diff --git a/libcxx/src/call_once.cpp b/libcxx/src/call_once.cpp new file mode 100644 index 0000000..352cdcc --- /dev/null +++ b/libcxx/src/call_once.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include <__mutex/once_flag.h> +#include <__utility/exception_guard.h> + +#ifndef _LIBCPP_HAS_NO_THREADS +# include <__threading_support> +#endif + +#include "include/atomic_support.h" + +_LIBCPP_BEGIN_NAMESPACE_STD + +// If dispatch_once_f ever handles C++ exceptions, and if one can get to it +// without illegal macros (unexpected macros not beginning with _UpperCase or +// __lowercase), and if it stops spinning waiting threads, then call_once should +// call into dispatch_once_f instead of here. Relevant radar this code needs to +// keep in sync with: 7741191. + +#ifndef _LIBCPP_HAS_NO_THREADS +static constinit __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER; +static constinit __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER; +#endif + +void __call_once(volatile once_flag::_State_type& flag, void* arg, + void (*func)(void*)) +{ +#if defined(_LIBCPP_HAS_NO_THREADS) + + if (flag == once_flag::_Unset) { + auto guard = std::__make_exception_guard([&flag] { flag = once_flag::_Unset; }); + flag = once_flag::_Pending; + func(arg); + flag = once_flag::_Complete; + guard.__complete(); + } + +#else // !_LIBCPP_HAS_NO_THREADS + + __libcpp_mutex_lock(&mut); + while (flag == once_flag::_Pending) + __libcpp_condvar_wait(&cv, &mut); + if (flag == once_flag::_Unset) { + auto guard = std::__make_exception_guard([&flag] { + __libcpp_mutex_lock(&mut); + __libcpp_relaxed_store(&flag, once_flag::_Unset); + __libcpp_mutex_unlock(&mut); + __libcpp_condvar_broadcast(&cv); + }); + + __libcpp_relaxed_store(&flag, once_flag::_Pending); + __libcpp_mutex_unlock(&mut); + func(arg); + __libcpp_mutex_lock(&mut); + __libcpp_atomic_store(&flag, once_flag::_Complete, _AO_Release); + __libcpp_mutex_unlock(&mut); + __libcpp_condvar_broadcast(&cv); + guard.__complete(); + } else { + __libcpp_mutex_unlock(&mut); + } + +#endif // !_LIBCPP_HAS_NO_THREADS +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/condition_variable.cpp b/libcxx/src/condition_variable.cpp index 87ce1d8..33e1956 100644 --- a/libcxx/src/condition_variable.cpp +++ b/libcxx/src/condition_variable.cpp @@ -6,10 +6,6 @@ // //===----------------------------------------------------------------------===// -#include <__config> - -#ifndef _LIBCPP_HAS_NO_THREADS - #include #include @@ -92,5 +88,3 @@ notify_all_at_thread_exit(condition_variable& cond, unique_lock lk) _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS - -#endif // !_LIBCPP_HAS_NO_THREADS diff --git a/libcxx/src/condition_variable_destructor.cpp b/libcxx/src/condition_variable_destructor.cpp index 333face..36113ab 100644 --- a/libcxx/src/condition_variable_destructor.cpp +++ b/libcxx/src/condition_variable_destructor.cpp @@ -14,10 +14,8 @@ #include <__config> #include <__threading_support> -#if !defined(_LIBCPP_HAS_NO_THREADS) -# if _LIBCPP_ABI_VERSION == 1 || !defined(_LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION) -# define NEEDS_CONDVAR_DESTRUCTOR -# endif +#if _LIBCPP_ABI_VERSION == 1 || !defined(_LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION) +# define NEEDS_CONDVAR_DESTRUCTOR #endif _LIBCPP_BEGIN_NAMESPACE_STD diff --git a/libcxx/src/future.cpp b/libcxx/src/future.cpp index 3383b50..0e3f7b1 100644 --- a/libcxx/src/future.cpp +++ b/libcxx/src/future.cpp @@ -6,10 +6,6 @@ // //===----------------------------------------------------------------------===// -#include <__config> - -#ifndef _LIBCPP_HAS_NO_THREADS - #include #include @@ -268,5 +264,3 @@ shared_future::operator=(const shared_future& __rhs) } _LIBCPP_END_NAMESPACE_STD - -#endif // !_LIBCPP_HAS_NO_THREADS diff --git a/libcxx/src/mutex.cpp b/libcxx/src/mutex.cpp index b165b1b..fe7a970 100644 --- a/libcxx/src/mutex.cpp +++ b/libcxx/src/mutex.cpp @@ -14,10 +14,8 @@ #include "include/atomic_support.h" -#ifndef _LIBCPP_HAS_NO_THREADS -# if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) -# pragma comment(lib, "pthread") -# endif +#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) +# pragma comment(lib, "pthread") #endif _LIBCPP_PUSH_MACROS @@ -25,8 +23,6 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#ifndef _LIBCPP_HAS_NO_THREADS - // ~mutex is defined elsewhere void @@ -189,60 +185,6 @@ recursive_timed_mutex::unlock() noexcept } } -#endif // !_LIBCPP_HAS_NO_THREADS - -// If dispatch_once_f ever handles C++ exceptions, and if one can get to it -// without illegal macros (unexpected macros not beginning with _UpperCase or -// __lowercase), and if it stops spinning waiting threads, then call_once should -// call into dispatch_once_f instead of here. Relevant radar this code needs to -// keep in sync with: 7741191. - -#ifndef _LIBCPP_HAS_NO_THREADS -static constinit __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER; -static constinit __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER; -#endif - -void __call_once(volatile once_flag::_State_type& flag, void* arg, - void (*func)(void*)) -{ -#if defined(_LIBCPP_HAS_NO_THREADS) - - if (flag == once_flag::_Unset) { - auto guard = std::__make_exception_guard([&flag] { flag = once_flag::_Unset; }); - flag = once_flag::_Pending; - func(arg); - flag = once_flag::_Complete; - guard.__complete(); - } - -#else // !_LIBCPP_HAS_NO_THREADS - - __libcpp_mutex_lock(&mut); - while (flag == once_flag::_Pending) - __libcpp_condvar_wait(&cv, &mut); - if (flag == once_flag::_Unset) { - auto guard = std::__make_exception_guard([&flag] { - __libcpp_mutex_lock(&mut); - __libcpp_relaxed_store(&flag, once_flag::_Unset); - __libcpp_mutex_unlock(&mut); - __libcpp_condvar_broadcast(&cv); - }); - - __libcpp_relaxed_store(&flag, once_flag::_Pending); - __libcpp_mutex_unlock(&mut); - func(arg); - __libcpp_mutex_lock(&mut); - __libcpp_atomic_store(&flag, once_flag::_Complete, _AO_Release); - __libcpp_mutex_unlock(&mut); - __libcpp_condvar_broadcast(&cv); - guard.__complete(); - } else { - __libcpp_mutex_unlock(&mut); - } - -#endif // !_LIBCPP_HAS_NO_THREADS -} - _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS diff --git a/libcxx/src/mutex_destructor.cpp b/libcxx/src/mutex_destructor.cpp index d366a4e..6096e42 100644 --- a/libcxx/src/mutex_destructor.cpp +++ b/libcxx/src/mutex_destructor.cpp @@ -19,10 +19,8 @@ #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 +#if _LIBCPP_ABI_VERSION == 1 || !defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION) +# define NEEDS_MUTEX_DESTRUCTOR #endif _LIBCPP_BEGIN_NAMESPACE_STD @@ -45,6 +43,6 @@ mutex::~mutex() noexcept { __libcpp_mutex_destroy(&__m_); } +#endif // !NEEDS_MUTEX_DESTRUCTOR -#endif // !_LIBCPP_HAS_NO_THREADS _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/shared_mutex.cpp b/libcxx/src/shared_mutex.cpp index 49a51e0..1a346dd 100644 --- a/libcxx/src/shared_mutex.cpp +++ b/libcxx/src/shared_mutex.cpp @@ -6,15 +6,11 @@ // //===----------------------------------------------------------------------===// -#include <__config> - -#ifndef _LIBCPP_HAS_NO_THREADS - -# include -# include -# if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) -# pragma comment(lib, "pthread") -# endif +#include +#include +#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) +# pragma comment(lib, "pthread") +#endif _LIBCPP_BEGIN_NAMESPACE_STD @@ -95,5 +91,3 @@ bool shared_timed_mutex::try_lock_shared() { return __base_.try_lock_shared(); } void shared_timed_mutex::unlock_shared() { return __base_.unlock_shared(); } _LIBCPP_END_NAMESPACE_STD - -#endif // !_LIBCPP_HAS_NO_THREADS diff --git a/libcxx/src/thread.cpp b/libcxx/src/thread.cpp index 184b5ae..289c457 100644 --- a/libcxx/src/thread.cpp +++ b/libcxx/src/thread.cpp @@ -6,10 +6,6 @@ // //===----------------------------------------------------------------------===// -#include <__config> - -#ifndef _LIBCPP_HAS_NO_THREADS - #include <__thread/poll_with_backoff.h> #include <__thread/timed_backoff_policy.h> #include @@ -215,5 +211,3 @@ __thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s) } _LIBCPP_END_NAMESPACE_STD - -#endif // !_LIBCPP_HAS_NO_THREADS -- cgit v1.1