diff --git a/libcxx/include/__threading_support b/libcxx/include/__threading_support index f8add051f2ab..072c4c7bcc89 100644 --- a/libcxx/include/__threading_support +++ b/libcxx/include/__threading_support @@ -1,802 +1,802 @@ // -*- C++ -*- //===----------------------------------------------------------------------===// // // 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 // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_THREADING_SUPPORT #define _LIBCPP_THREADING_SUPPORT #include <__config> #include #include #include #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER #pragma GCC system_header #endif #if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) # include <__external_threading> #elif !defined(_LIBCPP_HAS_NO_THREADS) #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) # include # include # ifdef __APPLE__ # define _LIBCPP_NO_NATIVE_SEMAPHORES # endif # ifndef _LIBCPP_NO_NATIVE_SEMAPHORES # include # endif #elif defined(_LIBCPP_HAS_THREAD_API_C11) # include #endif #if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \ defined(_LIBCPP_HAS_THREAD_API_WIN32) #define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS #else #define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY #endif #if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis) #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) #else #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS #endif typedef ::timespec __libcpp_timespec_t; #endif // !defined(_LIBCPP_HAS_NO_THREADS) _LIBCPP_PUSH_MACROS #include <__undef_macros> _LIBCPP_BEGIN_NAMESPACE_STD #if !defined(_LIBCPP_HAS_NO_THREADS) #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) // Mutex typedef pthread_mutex_t __libcpp_mutex_t; #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER typedef pthread_mutex_t __libcpp_recursive_mutex_t; // Condition Variable typedef pthread_cond_t __libcpp_condvar_t; #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER #ifndef _LIBCPP_NO_NATIVE_SEMAPHORES // Semaphore typedef sem_t __libcpp_semaphore_t; # define _LIBCPP_SEMAPHORE_MAX SEM_VALUE_MAX #endif // Execute once typedef pthread_once_t __libcpp_exec_once_flag; #define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT // Thread id typedef pthread_t __libcpp_thread_id; // Thread #define _LIBCPP_NULL_THREAD 0U typedef pthread_t __libcpp_thread_t; // Thread Local Storage typedef pthread_key_t __libcpp_tls_key; #define _LIBCPP_TLS_DESTRUCTOR_CC #elif defined(_LIBCPP_HAS_THREAD_API_C11) // Mutex typedef mtx_t __libcpp_mutex_t; // mtx_t is a struct so using {} for initialization is valid. #define _LIBCPP_MUTEX_INITIALIZER {} typedef mtx_t __libcpp_recursive_mutex_t; // Condition Variable typedef cnd_t __libcpp_condvar_t; // cnd_t is a struct so using {} for initialization is valid. #define _LIBCPP_CONDVAR_INITIALIZER {} // Execute once typedef once_flag __libcpp_exec_once_flag; #define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT // Thread id typedef thrd_t __libcpp_thread_id; // Thread #define _LIBCPP_NULL_THREAD 0U typedef thrd_t __libcpp_thread_t; // Thread Local Storage typedef tss_t __libcpp_tls_key; #define _LIBCPP_TLS_DESTRUCTOR_CC #elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) // Mutex typedef void* __libcpp_mutex_t; #define _LIBCPP_MUTEX_INITIALIZER 0 #if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__) typedef void* __libcpp_recursive_mutex_t[6]; #elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) typedef void* __libcpp_recursive_mutex_t[5]; #else # error Unsupported architecture #endif // Condition Variable typedef void* __libcpp_condvar_t; #define _LIBCPP_CONDVAR_INITIALIZER 0 // Semaphore typedef void* __libcpp_semaphore_t; // Execute Once typedef void* __libcpp_exec_once_flag; #define _LIBCPP_EXEC_ONCE_INITIALIZER 0 // Thread ID typedef long __libcpp_thread_id; // Thread #define _LIBCPP_NULL_THREAD 0U typedef void* __libcpp_thread_t; // Thread Local Storage typedef long __libcpp_tls_key; #define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall #endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) #if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) // Mutex _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_lock(__libcpp_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_unlock(__libcpp_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_mutex_destroy(__libcpp_mutex_t *__m); // Condition variable _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_condvar_signal(__libcpp_condvar_t* __cv); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, __libcpp_timespec_t *__ts); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); #ifndef _LIBCPP_NO_NATIVE_SEMAPHORES // Semaphore _LIBCPP_THREAD_ABI_VISIBILITY bool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init); _LIBCPP_THREAD_ABI_VISIBILITY bool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem); _LIBCPP_THREAD_ABI_VISIBILITY bool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem); _LIBCPP_THREAD_ABI_VISIBILITY bool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem); _LIBCPP_THREAD_ABI_VISIBILITY bool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns); #endif // _LIBCPP_NO_NATIVE_SEMAPHORES // Execute once _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_execute_once(__libcpp_exec_once_flag *flag, void (*init_routine)()); // Thread id _LIBCPP_THREAD_ABI_VISIBILITY bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); _LIBCPP_THREAD_ABI_VISIBILITY bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); // Thread _LIBCPP_THREAD_ABI_VISIBILITY bool __libcpp_thread_isnull(const __libcpp_thread_t *__t); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), void *__arg); _LIBCPP_THREAD_ABI_VISIBILITY __libcpp_thread_id __libcpp_thread_get_current_id(); _LIBCPP_THREAD_ABI_VISIBILITY __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_thread_join(__libcpp_thread_t *__t); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_thread_detach(__libcpp_thread_t *__t); _LIBCPP_THREAD_ABI_VISIBILITY void __libcpp_thread_yield(); _LIBCPP_THREAD_ABI_VISIBILITY void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); // Thread local storage _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_tls_create(__libcpp_tls_key* __key, void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); _LIBCPP_THREAD_ABI_VISIBILITY void *__libcpp_tls_get(__libcpp_tls_key __key); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_tls_set(__libcpp_tls_key __key, void *__p); #endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) struct __libcpp_timed_backoff_policy { _LIBCPP_THREAD_ABI_VISIBILITY bool operator()(chrono::nanoseconds __elapsed) const; }; -inline _LIBCPP_THREAD_ABI_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY bool __libcpp_timed_backoff_policy::operator()(chrono::nanoseconds __elapsed) const { if(__elapsed > chrono::milliseconds(128)) __libcpp_thread_sleep_for(chrono::milliseconds(8)); else if(__elapsed > chrono::microseconds(64)) __libcpp_thread_sleep_for(__elapsed / 2); else if(__elapsed > chrono::microseconds(4)) __libcpp_thread_yield(); else ; // poll return false; } static _LIBCPP_CONSTEXPR const int __libcpp_polling_count = 64; template _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY bool __libcpp_thread_poll_with_backoff( _Fn && __f, _BFn && __bf, chrono::nanoseconds __max_elapsed = chrono::nanoseconds::zero()) { auto const __start = chrono::high_resolution_clock::now(); for(int __count = 0;;) { if(__f()) return true; // _Fn completion means success if(__count < __libcpp_polling_count) { __count += 1; continue; } chrono::nanoseconds const __elapsed = chrono::high_resolution_clock::now() - __start; if(__max_elapsed != chrono::nanoseconds::zero() && __max_elapsed < __elapsed) return false; // timeout failure if(__bf(__elapsed)) return false; // _BFn completion means failure } } #if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) namespace __thread_detail { inline __libcpp_timespec_t __convert_to_timespec(const chrono::nanoseconds& __ns) { using namespace chrono; seconds __s = duration_cast(__ns); __libcpp_timespec_t __ts; typedef decltype(__ts.tv_sec) __ts_sec; const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max(); if (__s.count() < __ts_sec_max) { __ts.tv_sec = static_cast<__ts_sec>(__s.count()); __ts.tv_nsec = static_cast((__ns - __s).count()); } else { __ts.tv_sec = __ts_sec_max; __ts.tv_nsec = 999999999; // (10^9 - 1) } return __ts; } } #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) { pthread_mutexattr_t attr; int __ec = pthread_mutexattr_init(&attr); if (__ec) return __ec; __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); if (__ec) { pthread_mutexattr_destroy(&attr); return __ec; } __ec = pthread_mutex_init(__m, &attr); if (__ec) { pthread_mutexattr_destroy(&attr); return __ec; } __ec = pthread_mutexattr_destroy(&attr); if (__ec) { pthread_mutex_destroy(__m); return __ec; } return 0; } int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) { return pthread_mutex_lock(__m); } bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) { return pthread_mutex_trylock(__m) == 0; } int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) { return pthread_mutex_unlock(__m); } int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) { return pthread_mutex_destroy(__m); } int __libcpp_mutex_lock(__libcpp_mutex_t *__m) { return pthread_mutex_lock(__m); } bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) { return pthread_mutex_trylock(__m) == 0; } int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) { return pthread_mutex_unlock(__m); } int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) { return pthread_mutex_destroy(__m); } // Condition Variable int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) { return pthread_cond_signal(__cv); } int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) { return pthread_cond_broadcast(__cv); } int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) { return pthread_cond_wait(__cv, __m); } int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, __libcpp_timespec_t *__ts) { return pthread_cond_timedwait(__cv, __m, __ts); } int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) { return pthread_cond_destroy(__cv); } #ifndef _LIBCPP_NO_NATIVE_SEMAPHORES // Semaphore bool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init) { return sem_init(__sem, 0, __init) == 0; } bool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem) { return sem_destroy(__sem) == 0; } bool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem) { return sem_post(__sem) == 0; } bool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem) { return sem_wait(__sem) == 0; } bool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns) { auto const __abs_time = chrono::system_clock::now().time_since_epoch() + __ns; __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__abs_time); return sem_timedwait(__sem, &__ts) == 0; } #endif //_LIBCPP_NO_NATIVE_SEMAPHORES // Execute once int __libcpp_execute_once(__libcpp_exec_once_flag *flag, void (*init_routine)()) { return pthread_once(flag, init_routine); } // Thread id // Returns non-zero if the thread ids are equal, otherwise 0 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) { return pthread_equal(t1, t2) != 0; } // Returns non-zero if t1 < t2, otherwise 0 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) { return t1 < t2; } // Thread bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { return *__t == 0; } int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), void *__arg) { return pthread_create(__t, 0, __func, __arg); } __libcpp_thread_id __libcpp_thread_get_current_id() { return pthread_self(); } __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) { return *__t; } int __libcpp_thread_join(__libcpp_thread_t *__t) { return pthread_join(*__t, 0); } int __libcpp_thread_detach(__libcpp_thread_t *__t) { return pthread_detach(*__t); } void __libcpp_thread_yield() { sched_yield(); } void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) { __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns); while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR); } // Thread local storage int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) { return pthread_key_create(__key, __at_exit); } void *__libcpp_tls_get(__libcpp_tls_key __key) { return pthread_getspecific(__key); } int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) { return pthread_setspecific(__key, __p); } #elif defined(_LIBCPP_HAS_THREAD_API_C11) int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) { return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL; } int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) { return mtx_lock(__m) == thrd_success ? 0 : EINVAL; } bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) { return mtx_trylock(__m) == thrd_success; } int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) { return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; } int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) { mtx_destroy(__m); return 0; } int __libcpp_mutex_lock(__libcpp_mutex_t *__m) { return mtx_lock(__m) == thrd_success ? 0 : EINVAL; } bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) { return mtx_trylock(__m) == thrd_success; } int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) { return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; } int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) { mtx_destroy(__m); return 0; } // Condition Variable int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) { return cnd_signal(__cv) == thrd_success ? 0 : EINVAL; } int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) { return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL; } int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) { return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL; } int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, timespec *__ts) { int __ec = cnd_timedwait(__cv, __m, __ts); return __ec == thrd_timedout ? ETIMEDOUT : __ec; } int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) { cnd_destroy(__cv); return 0; } // Execute once int __libcpp_execute_once(__libcpp_exec_once_flag *flag, void (*init_routine)(void)) { ::call_once(flag, init_routine); return 0; } // Thread id // Returns non-zero if the thread ids are equal, otherwise 0 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) { return thrd_equal(t1, t2) != 0; } // Returns non-zero if t1 < t2, otherwise 0 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) { return t1 < t2; } // Thread bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { return *__t == 0; } int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), void *__arg) { int __ec = thrd_create(__t, reinterpret_cast(__func), __arg); return __ec == thrd_nomem ? ENOMEM : __ec; } __libcpp_thread_id __libcpp_thread_get_current_id() { return thrd_current(); } __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) { return *__t; } int __libcpp_thread_join(__libcpp_thread_t *__t) { return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL; } int __libcpp_thread_detach(__libcpp_thread_t *__t) { return thrd_detach(*__t) == thrd_success ? 0 : EINVAL; } void __libcpp_thread_yield() { thrd_yield(); } void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) { __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns); thrd_sleep(&__ts, nullptr); } // Thread local storage int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) { return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL; } void *__libcpp_tls_get(__libcpp_tls_key __key) { return tss_get(__key); } int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) { return tss_set(__key, __p) == thrd_success ? 0 : EINVAL; } #endif #endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL class _LIBCPP_TYPE_VIS thread; class _LIBCPP_TYPE_VIS __thread_id; namespace this_thread { _LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; } // this_thread template<> struct hash<__thread_id>; class _LIBCPP_TEMPLATE_VIS __thread_id { // FIXME: pthread_t is a pointer on Darwin but a long on Linux. // NULL is the no-thread value on Darwin. Someone needs to check // on other platforms. We assume 0 works everywhere for now. __libcpp_thread_id __id_; public: _LIBCPP_INLINE_VISIBILITY __thread_id() _NOEXCEPT : __id_(0) {} friend _LIBCPP_INLINE_VISIBILITY bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT { // don't pass id==0 to underlying routines if (__x.__id_ == 0) return __y.__id_ == 0; if (__y.__id_ == 0) return false; return __libcpp_thread_id_equal(__x.__id_, __y.__id_); } friend _LIBCPP_INLINE_VISIBILITY bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT {return !(__x == __y);} friend _LIBCPP_INLINE_VISIBILITY bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT { // id==0 is always less than any other thread_id if (__x.__id_ == 0) return __y.__id_ != 0; if (__y.__id_ == 0) return false; return __libcpp_thread_id_less(__x.__id_, __y.__id_); } friend _LIBCPP_INLINE_VISIBILITY bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT {return !(__y < __x);} friend _LIBCPP_INLINE_VISIBILITY bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT {return __y < __x ;} friend _LIBCPP_INLINE_VISIBILITY bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT {return !(__x < __y);} _LIBCPP_INLINE_VISIBILITY void __reset() { __id_ = 0; } template friend _LIBCPP_INLINE_VISIBILITY basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id); private: _LIBCPP_INLINE_VISIBILITY __thread_id(__libcpp_thread_id __id) : __id_(__id) {} friend __thread_id this_thread::get_id() _NOEXCEPT; friend class _LIBCPP_TYPE_VIS thread; friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; }; namespace this_thread { inline _LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT { return __libcpp_thread_get_current_id(); } } // this_thread #endif // !_LIBCPP_HAS_NO_THREADS _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS #endif // _LIBCPP_THREADING_SUPPORT diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt index dcd53c8a302a..2001c09761d9 100644 --- a/libcxx/src/CMakeLists.txt +++ b/libcxx/src/CMakeLists.txt @@ -1,409 +1,406 @@ set(LIBCXX_LIB_CMAKEFILES_DIR "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}" PARENT_SCOPE) # Get sources set(LIBCXX_SOURCES algorithm.cpp any.cpp atomic.cpp barrier.cpp bind.cpp charconv.cpp chrono.cpp condition_variable.cpp condition_variable_destructor.cpp debug.cpp exception.cpp functional.cpp future.cpp hash.cpp include/apple_availability.h include/atomic_support.h include/config_elast.h include/refstring.h ios.cpp iostream.cpp locale.cpp memory.cpp mutex.cpp mutex_destructor.cpp new.cpp optional.cpp random.cpp random_shuffle.cpp regex.cpp shared_mutex.cpp stdexcept.cpp string.cpp strstream.cpp support/runtime/exception_fallback.ipp support/runtime/exception_glibcxx.ipp support/runtime/exception_libcxxabi.ipp support/runtime/exception_libcxxrt.ipp support/runtime/exception_msvc.ipp support/runtime/exception_pointer_cxxabi.ipp support/runtime/exception_pointer_glibcxx.ipp support/runtime/exception_pointer_msvc.ipp support/runtime/exception_pointer_unimplemented.ipp support/runtime/new_handler_fallback.ipp support/runtime/stdexcept_default.ipp support/runtime/stdexcept_vcruntime.ipp system_error.cpp thread.cpp typeinfo.cpp utility.cpp valarray.cpp variant.cpp vector.cpp ) if(WIN32) list(APPEND LIBCXX_SOURCES support/win32/locale_win32.cpp support/win32/support.cpp support/win32/thread_win32.cpp ) elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS") list(APPEND LIBCXX_SOURCES support/solaris/mbsnrtowcs.inc support/solaris/wcsnrtombs.inc support/solaris/xlocale.cpp ) endif() if (LIBCXX_ENABLE_FILESYSTEM) list(APPEND LIBCXX_SOURCES filesystem/filesystem_common.h filesystem/operations.cpp filesystem/directory_iterator.cpp ) # Filesystem uses __int128_t, which requires a definition of __muloi4 when # compiled with UBSAN. This definition is not provided by libgcc_s, but is # provided by compiler-rt. So we need to disable it to avoid having multiple # definitions. See filesystem/int128_builtins.cpp. if (NOT LIBCXX_USE_COMPILER_RT) list(APPEND LIBCXX_SOURCES filesystem/int128_builtins.cpp ) endif() endif() # Add all the headers to the project for IDEs. if (LIBCXX_CONFIGURE_IDE) file(GLOB_RECURSE LIBCXX_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/*) if(WIN32) file( GLOB LIBCXX_WIN32_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/support/win32/*.h) list(APPEND LIBCXX_HEADERS ${LIBCXX_WIN32_HEADERS}) endif() # Force them all into the headers dir on MSVC, otherwise they end up at # project scope because they don't have extensions. if (MSVC_IDE) source_group("Header Files" FILES ${LIBCXX_HEADERS}) endif() endif() if(NOT LIBCXX_INSTALL_LIBRARY) set(exclude_from_all EXCLUDE_FROM_ALL) endif() # If LIBCXX_CXX_ABI_LIBRARY_PATH is defined we want to add it to the search path. add_link_flags_if(LIBCXX_CXX_ABI_LIBRARY_PATH "${CMAKE_LIBRARY_PATH_FLAG}${LIBCXX_CXX_ABI_LIBRARY_PATH}") if (LIBCXX_GENERATE_COVERAGE AND NOT LIBCXX_COVERAGE_LIBRARY) find_compiler_rt_library(profile LIBCXX_COVERAGE_LIBRARY) endif() add_library_flags_if(LIBCXX_COVERAGE_LIBRARY "${LIBCXX_COVERAGE_LIBRARY}") if (APPLE AND LLVM_USE_SANITIZER) if (("${LLVM_USE_SANITIZER}" STREQUAL "Address") OR ("${LLVM_USE_SANITIZER}" STREQUAL "Address;Undefined") OR ("${LLVM_USE_SANITIZER}" STREQUAL "Undefined;Address")) set(LIBFILE "libclang_rt.asan_osx_dynamic.dylib") elseif("${LLVM_USE_SANITIZER}" STREQUAL "Undefined") set(LIBFILE "libclang_rt.ubsan_osx_dynamic.dylib") elseif("${LLVM_USE_SANITIZER}" STREQUAL "Thread") set(LIBFILE "libclang_rt.tsan_osx_dynamic.dylib") else() message(WARNING "LLVM_USE_SANITIZER=${LLVM_USE_SANITIZER} is not supported on OS X") endif() if (LIBFILE) find_compiler_rt_dir(LIBDIR) if (NOT IS_DIRECTORY "${LIBDIR}") message(FATAL_ERROR "Cannot find compiler-rt directory on OS X required for LLVM_USE_SANITIZER") endif() set(LIBCXX_SANITIZER_LIBRARY "${LIBDIR}/${LIBFILE}") set(LIBCXX_SANITIZER_LIBRARY "${LIBCXX_SANITIZER_LIBRARY}" PARENT_SCOPE) message(STATUS "Manually linking compiler-rt library: ${LIBCXX_SANITIZER_LIBRARY}") add_library_flags("${LIBCXX_SANITIZER_LIBRARY}") add_link_flags("-Wl,-rpath,${LIBDIR}") endif() endif() if (LIBCXX_ENABLE_PARALLEL_ALGORITHMS AND NOT TARGET pstl::ParallelSTL) message(FATAL_ERROR "Could not find ParallelSTL") endif() function(cxx_set_common_defines name) if(LIBCXX_CXX_ABI_HEADER_TARGET) add_dependencies(${name} ${LIBCXX_CXX_ABI_HEADER_TARGET}) endif() if (LIBCXX_ENABLE_PARALLEL_ALGORITHMS) target_link_libraries(${name} PUBLIC pstl::ParallelSTL) endif() endfunction() split_list(LIBCXX_COMPILE_FLAGS) split_list(LIBCXX_LINK_FLAGS) # Build the shared library. if (LIBCXX_ENABLE_SHARED) add_library(cxx_shared SHARED ${exclude_from_all} ${LIBCXX_SOURCES} ${LIBCXX_HEADERS}) if(COMMAND llvm_setup_rpath) llvm_setup_rpath(cxx_shared) endif() target_link_libraries(cxx_shared PUBLIC cxx-headers PRIVATE ${LIBCXX_LIBRARIES}) set_target_properties(cxx_shared PROPERTIES COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}" LINK_FLAGS "${LIBCXX_LINK_FLAGS}" OUTPUT_NAME "c++" VERSION "${LIBCXX_ABI_VERSION}.0" SOVERSION "${LIBCXX_ABI_VERSION}" DEFINE_SYMBOL "" ) cxx_add_common_build_flags(cxx_shared) cxx_set_common_defines(cxx_shared) # Link against LLVM libunwind if (LIBCXXABI_USE_LLVM_UNWINDER) if (NOT LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY AND (TARGET unwind_shared OR HAVE_LIBUNWIND)) target_link_libraries(cxx_shared PUBLIC unwind_shared) elseif (LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY AND (TARGET unwind_static OR HAVE_LIBUNWIND)) # libunwind is already included in libc++abi else() target_link_libraries(cxx_shared PUBLIC unwind) endif() endif() # Link against libc++abi if (LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY) if (APPLE) target_link_libraries(cxx_shared PRIVATE "-Wl,-force_load" "${LIBCXX_CXX_STATIC_ABI_LIBRARY}") else() target_link_libraries(cxx_shared PRIVATE "-Wl,--whole-archive,-Bstatic" "${LIBCXX_CXX_STATIC_ABI_LIBRARY}" "-Wl,-Bdynamic,--no-whole-archive") endif() else() target_link_libraries(cxx_shared PUBLIC "${LIBCXX_CXX_SHARED_ABI_LIBRARY}") endif() # Maybe re-export symbols from libc++abi if (APPLE AND (LIBCXX_CXX_ABI_LIBNAME STREQUAL "libcxxabi" OR LIBCXX_CXX_ABI_LIBNAME STREQUAL "default") AND NOT DEFINED LIBCXX_OSX_REEXPORT_LIBCXXABI_SYMBOLS) set(LIBCXX_OSX_REEXPORT_LIBCXXABI_SYMBOLS ON) endif() if (LIBCXX_OSX_REEXPORT_LIBCXXABI_SYMBOLS) target_link_libraries(cxx_shared PRIVATE "-Wl,-unexported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/libc++unexp.exp" "-Wl,-reexported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/libc++abi.v${LIBCXX_LIBCPPABI_VERSION}.exp" "-Wl,-force_symbols_not_weak_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/notweak.exp" "-Wl,-force_symbols_weak_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/weak.exp") if (LIBCXX_ENABLE_EXCEPTIONS) if ("${CMAKE_OSX_ARCHITECTURES}" MATCHES "^(armv6|armv7|armv7s)$") target_link_libraries(cxx_shared PRIVATE "-Wl,-reexported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/libc++abi-exceptions.sjlj.exp") else() target_link_libraries(cxx_shared PRIVATE "-Wl,-reexported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/libc++abi-exceptions.exp") endif() endif() if (NOT LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS) target_link_libraries(cxx_shared PRIVATE "-Wl,-reexported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/libc++abi-new-delete.exp") endif() endif() # Generate a linker script in place of a libc++.so symlink. if (LIBCXX_ENABLE_ABI_LINKER_SCRIPT) include(DefineLinkerScript) define_linker_script(cxx_shared) endif() list(APPEND LIBCXX_BUILD_TARGETS "cxx_shared") if(WIN32 AND NOT MINGW AND NOT "${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows") # Since we most likely do not have a mt.exe replacement, disable the # manifest bundling. This allows a normal cmake invocation to pass which # will attempt to use the manifest tool to generate the bundled manifest set_target_properties(cxx_shared PROPERTIES APPEND_STRING PROPERTY LINK_FLAGS " /MANIFEST:NO") endif() endif() # Build the static library. if (LIBCXX_ENABLE_STATIC) add_library(cxx_static STATIC ${exclude_from_all} ${LIBCXX_SOURCES} ${LIBCXX_HEADERS}) target_link_libraries(cxx_static PUBLIC cxx-headers PRIVATE ${LIBCXX_LIBRARIES}) set(CMAKE_STATIC_LIBRARY_PREFIX "lib") set_target_properties(cxx_static PROPERTIES COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}" LINK_FLAGS "${LIBCXX_LINK_FLAGS}" OUTPUT_NAME "c++" ) cxx_add_common_build_flags(cxx_static) cxx_set_common_defines(cxx_static) if (LIBCXX_HERMETIC_STATIC_LIBRARY) # If the hermetic library doesn't define the operator new/delete functions # then its code shouldn't declare them with hidden visibility. They might # actually be provided by a shared library at link time. if (LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS) append_flags_if_supported(CXX_STATIC_LIBRARY_FLAGS -fvisibility-global-new-delete-hidden) endif() target_compile_options(cxx_static PRIVATE ${CXX_STATIC_LIBRARY_FLAGS}) target_compile_definitions(cxx_static PRIVATE _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) endif() list(APPEND LIBCXX_BUILD_TARGETS "cxx_static") # Attempt to merge the libc++.a archive and the ABI library archive into one. if (LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY) set(MERGE_ARCHIVES_SEARCH_PATHS "") if (LIBCXX_CXX_ABI_LIBRARY_PATH) set(MERGE_ARCHIVES_SEARCH_PATHS "-L${LIBCXX_CXX_ABI_LIBRARY_PATH}") endif() if (TARGET "${LIBCXX_CXX_STATIC_ABI_LIBRARY}" OR HAVE_LIBCXXABI) set(MERGE_ARCHIVES_ABI_TARGET "$") else() set(MERGE_ARCHIVES_ABI_TARGET "${CMAKE_STATIC_LIBRARY_PREFIX}${LIBCXX_CXX_STATIC_ABI_LIBRARY}${CMAKE_STATIC_LIBRARY_SUFFIX}") endif() if (APPLE) set(MERGE_ARCHIVES_LIBTOOL "--use-libtool" "--libtool" "${CMAKE_LIBTOOL}") endif() add_custom_command(TARGET cxx_static POST_BUILD COMMAND ${Python3_EXECUTABLE} ${LIBCXX_SOURCE_DIR}/utils/merge_archives.py ARGS -o $ --ar "${CMAKE_AR}" ${MERGE_ARCHIVES_LIBTOOL} "$" "${MERGE_ARCHIVES_ABI_TARGET}" "${MERGE_ARCHIVES_SEARCH_PATHS}" WORKING_DIRECTORY ${LIBCXX_BUILD_DIR} ) endif() endif() # Add a meta-target for both libraries. add_custom_target(cxx DEPENDS ${LIBCXX_BUILD_TARGETS}) if (LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY) set(LIBCXX_EXPERIMENTAL_SOURCES experimental/memory_resource.cpp ) add_library(cxx_experimental STATIC ${LIBCXX_EXPERIMENTAL_SOURCES}) if (LIBCXX_ENABLE_SHARED) target_link_libraries(cxx_experimental PRIVATE cxx_shared) else() target_link_libraries(cxx_experimental PRIVATE cxx_static) endif() set_target_properties(cxx_experimental PROPERTIES COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}" OUTPUT_NAME "c++experimental" ) cxx_add_common_build_flags(cxx_experimental) endif() if (LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY) - set(LIBCXX_EXTERNAL_THREADING_SUPPORT_SOURCES - "${CMAKE_CURRENT_SOURCE_DIR}/../test/support/external_threads.cpp") + file(GLOB LIBCXX_EXTERNAL_THREADING_SUPPORT_SOURCES ../test/support/external_threads.cpp) if (LIBCXX_ENABLE_SHARED) add_library(cxx_external_threads SHARED ${LIBCXX_EXTERNAL_THREADING_SUPPORT_SOURCES}) else() add_library(cxx_external_threads STATIC ${LIBCXX_EXTERNAL_THREADING_SUPPORT_SOURCES}) endif() set_target_properties(cxx_external_threads PROPERTIES LINK_FLAGS "${LIBCXX_LINK_FLAGS}" COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}" OUTPUT_NAME "c++external_threads" ) - - target_link_libraries(cxx_external_threads PRIVATE cxx-headers) endif() if (LIBCXX_INSTALL_LIBRARY) if (LIBCXX_INSTALL_SHARED_LIBRARY) install(TARGETS cxx_shared ARCHIVE DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx LIBRARY DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx RUNTIME DESTINATION ${LIBCXX_INSTALL_PREFIX}bin COMPONENT cxx) endif() if (LIBCXX_INSTALL_STATIC_LIBRARY) install(TARGETS cxx_static ARCHIVE DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx LIBRARY DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx RUNTIME DESTINATION ${LIBCXX_INSTALL_PREFIX}bin COMPONENT cxx) endif() if(LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY) install(TARGETS cxx_experimental LIBRARY DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx ARCHIVE DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx RUNTIME DESTINATION ${LIBCXX_INSTALL_PREFIX}bin COMPONENT cxx) endif() # NOTE: This install command must go after the cxx install command otherwise # it will not be executed after the library symlinks are installed. if (LIBCXX_ENABLE_SHARED AND LIBCXX_ENABLE_ABI_LINKER_SCRIPT) # Replace the libc++ filename with $ # after we required CMake 3.0. install(FILES "${LIBCXX_LIBRARY_DIR}/libc++${CMAKE_SHARED_LIBRARY_SUFFIX}" DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT libcxx) endif() endif() if (NOT CMAKE_CONFIGURATION_TYPES AND (LIBCXX_INSTALL_LIBRARY OR LIBCXX_INSTALL_HEADERS)) if(LIBCXX_INSTALL_LIBRARY) set(lib_install_target cxx) endif() if (LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY) set(experimental_lib_install_target cxx_experimental) endif() if(LIBCXX_INSTALL_HEADERS) set(header_install_target install-cxx-headers) endif() if (LIBCXX_ENABLE_PARALLEL_ALGORITHMS) set(pstl_install_target install-pstl) endif() add_custom_target(install-cxx DEPENDS ${lib_install_target} ${experimental_lib_install_target} ${header_install_target} ${pstl_install_target} COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=cxx -P "${LIBCXX_BINARY_DIR}/cmake_install.cmake") add_custom_target(install-cxx-stripped DEPENDS ${lib_install_target} ${experimental_lib_install_target} ${header_install_target} ${pstl_install_target} COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=cxx -DCMAKE_INSTALL_DO_STRIP=1 -P "${LIBCXX_BINARY_DIR}/cmake_install.cmake") endif()