diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-07-11 22:48:30 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-07-11 22:48:30 +0800 |
| commit | 3ad39e9878310e5317ee73c9b353c1e2c1c5c4ee (patch) | |
| tree | 4bd5a49ef60ad1e371c0984cd46838368c5ef83a /third_party/libcxx/include/c++/v1/__thread | |
| parent | 48ef95c24e9ac3d11200b61af617a01b10b507d1 (diff) | |
| download | lume-3ad39e9878310e5317ee73c9b353c1e2c1c5c4ee.tar.gz lume-3ad39e9878310e5317ee73c9b353c1e2c1c5c4ee.tar.xz | |
lib: establish Zircon libc++ and KTL foundation
Diffstat (limited to 'third_party/libcxx/include/c++/v1/__thread')
12 files changed, 1502 insertions, 0 deletions
diff --git a/third_party/libcxx/include/c++/v1/__thread/formatter.h b/third_party/libcxx/include/c++/v1/__thread/formatter.h new file mode 100644 index 0000000..826607d --- /dev/null +++ b/third_party/libcxx/include/c++/v1/__thread/formatter.h @@ -0,0 +1,80 @@ +// -*- 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___THREAD_FORMATTER_H +#define _LIBCPP___THREAD_FORMATTER_H + +#include <__concepts/arithmetic.h> +#include <__config> +#include <__format/concepts.h> +#include <__format/format_parse_context.h> +#include <__format/formatter.h> +#include <__format/formatter_integral.h> +#include <__format/parser_std_format_spec.h> +#include <__thread/id.h> +#include <__type_traits/conditional.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/is_same.h> +#include <cstdint> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +# if _LIBCPP_HAS_THREADS + +template <__fmt_char_type _CharT> +struct formatter<__thread_id, _CharT> { +public: + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return __parser_.__parse(__ctx, __format_spec::__fields_fill_align_width); + } + + template <class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(__thread_id __id, _FormatContext& __ctx) const { + // In __thread/support/pthread.h, __libcpp_thread_id is either a + // unsigned long long or a pthread_t. + // + // The type of pthread_t is left unspecified in POSIX so it can be any + // type. The most logical types are an integral or pointer. + // On Linux systems pthread_t is an unsigned long long. + // On Apple systems pthread_t is a pointer type. + // + // Note the output should match what the stream operator does. Since + // the ostream operator has been shipped years before this formatter + // was added to the Standard, this formatter does what the stream + // operator does. This may require platform specific changes. + + using _Tp = decltype(__get_underlying_id(__id)); + using _Cp = conditional_t<integral<_Tp>, _Tp, conditional_t<is_pointer_v<_Tp>, uintptr_t, void>>; + static_assert(!is_same_v<_Cp, void>, "unsupported thread::id type, please file a bug report"); + + __format_spec::__parsed_specifications<_CharT> __specs = __parser_.__get_parsed_std_specifications(__ctx); + if constexpr (is_pointer_v<_Tp>) { + __specs.__std_.__alternate_form_ = true; + __specs.__std_.__type_ = __format_spec::__type::__hexadecimal_lower_case; + } + return __formatter::__format_integer(reinterpret_cast<_Cp>(__get_underlying_id(__id)), __ctx, __specs); + } + + __format_spec::__parser<_CharT> __parser_{.__alignment_ = __format_spec::__alignment::__right}; +}; + +# endif // _LIBCPP_HAS_THREADS + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +#endif // _LIBCPP___THREAD_FORMATTER_H diff --git a/third_party/libcxx/include/c++/v1/__thread/id.h b/third_party/libcxx/include/c++/v1/__thread/id.h new file mode 100644 index 0000000..14a51fc --- /dev/null +++ b/third_party/libcxx/include/c++/v1/__thread/id.h @@ -0,0 +1,121 @@ +// -*- 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___THREAD_ID_H +#define _LIBCPP___THREAD_ID_H + +#include <__compare/ordering.h> +#include <__config> +#include <__fwd/functional.h> +#include <__fwd/ostream.h> +#include <__thread/support.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_HAS_THREADS +class __thread_id; + +namespace this_thread { + +_LIBCPP_HIDE_FROM_ABI __thread_id get_id() _NOEXCEPT; + +} // namespace this_thread + +template <> +struct hash<__thread_id>; + +class __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_; + + static _LIBCPP_HIDE_FROM_ABI bool + __lt_impl(__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_); + } + +public: + _LIBCPP_HIDE_FROM_ABI __thread_id() _NOEXCEPT : __id_(0) {} + + _LIBCPP_HIDE_FROM_ABI void __reset() { __id_ = 0; } + + friend _LIBCPP_HIDE_FROM_ABI bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT; +# if _LIBCPP_STD_VER <= 17 + friend _LIBCPP_HIDE_FROM_ABI bool operator<(__thread_id __x, __thread_id __y) _NOEXCEPT; +# else // _LIBCPP_STD_VER <= 17 + friend _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(__thread_id __x, __thread_id __y) noexcept; +# endif // _LIBCPP_STD_VER <= 17 + + template <class _CharT, class _Traits> + friend _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& + operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id); + +private: + _LIBCPP_HIDE_FROM_ABI __thread_id(__libcpp_thread_id __id) : __id_(__id) {} + + _LIBCPP_HIDE_FROM_ABI friend __libcpp_thread_id __get_underlying_id(const __thread_id __id) { return __id.__id_; } + + friend __thread_id this_thread::get_id() _NOEXCEPT; + friend class _LIBCPP_EXPORTED_FROM_ABI thread; + friend struct hash<__thread_id>; +}; + +inline _LIBCPP_HIDE_FROM_ABI 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_); +} + +# if _LIBCPP_STD_VER <= 17 + +inline _LIBCPP_HIDE_FROM_ABI bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__x == __y); } + +inline _LIBCPP_HIDE_FROM_ABI bool operator<(__thread_id __x, __thread_id __y) _NOEXCEPT { + return __thread_id::__lt_impl(__x.__id_, __y.__id_); +} + +inline _LIBCPP_HIDE_FROM_ABI bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__y < __x); } +inline _LIBCPP_HIDE_FROM_ABI bool operator>(__thread_id __x, __thread_id __y) _NOEXCEPT { return __y < __x; } +inline _LIBCPP_HIDE_FROM_ABI bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__x < __y); } + +# else // _LIBCPP_STD_VER <= 17 + +inline _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(__thread_id __x, __thread_id __y) noexcept { + if (__x == __y) + return strong_ordering::equal; + if (__thread_id::__lt_impl(__x, __y)) + return strong_ordering::less; + return strong_ordering::greater; +} + +# endif // _LIBCPP_STD_VER <= 17 + +namespace this_thread { + +inline _LIBCPP_HIDE_FROM_ABI __thread_id get_id() _NOEXCEPT { return __libcpp_thread_get_current_id(); } + +} // namespace this_thread + +#endif // _LIBCPP_HAS_THREADS + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___THREAD_ID_H diff --git a/third_party/libcxx/include/c++/v1/__thread/jthread.h b/third_party/libcxx/include/c++/v1/__thread/jthread.h new file mode 100644 index 0000000..481ffe2 --- /dev/null +++ b/third_party/libcxx/include/c++/v1/__thread/jthread.h @@ -0,0 +1,136 @@ +// -*- 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___THREAD_JTHREAD_H +#define _LIBCPP___THREAD_JTHREAD_H + +#include <__config> +#include <__stop_token/stop_source.h> +#include <__stop_token/stop_token.h> +#include <__thread/id.h> +#include <__thread/support.h> +#include <__thread/thread.h> +#include <__type_traits/decay.h> +#include <__type_traits/invoke.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_same.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include <__utility/swap.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_THREADS + +_LIBCPP_BEGIN_NAMESPACE_STD + +class jthread { +public: + // types + using id = thread::id; + using native_handle_type = thread::native_handle_type; + + // [thread.jthread.cons], constructors, move, and assignment + _LIBCPP_HIDE_FROM_ABI jthread() noexcept : __stop_source_(std::nostopstate) {} + + template <class _Fun, class... _Args> + _LIBCPP_HIDE_FROM_ABI explicit jthread(_Fun&& __fun, _Args&&... __args) + requires(!std::is_same_v<remove_cvref_t<_Fun>, jthread>) + : __stop_source_(), + __thread_(__init_thread(__stop_source_, std::forward<_Fun>(__fun), std::forward<_Args>(__args)...)) { + static_assert(is_constructible_v<decay_t<_Fun>, _Fun>); + static_assert((is_constructible_v<decay_t<_Args>, _Args> && ...)); + static_assert(is_invocable_v<decay_t<_Fun>, decay_t<_Args>...> || + is_invocable_v<decay_t<_Fun>, stop_token, decay_t<_Args>...>); + } + + _LIBCPP_HIDE_FROM_ABI ~jthread() { + if (joinable()) { + request_stop(); + join(); + } + } + + jthread(const jthread&) = delete; + + _LIBCPP_HIDE_FROM_ABI jthread(jthread&&) noexcept = default; + + jthread& operator=(const jthread&) = delete; + + _LIBCPP_HIDE_FROM_ABI jthread& operator=(jthread&& __other) noexcept { + if (this != &__other) { + if (joinable()) { + request_stop(); + join(); + } + __stop_source_ = std::move(__other.__stop_source_); + __thread_ = std::move(__other.__thread_); + } + + return *this; + } + + // [thread.jthread.mem], members + _LIBCPP_HIDE_FROM_ABI void swap(jthread& __other) noexcept { + std::swap(__stop_source_, __other.__stop_source_); + std::swap(__thread_, __other.__thread_); + } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool joinable() const noexcept { return get_id() != id(); } + + _LIBCPP_HIDE_FROM_ABI void join() { __thread_.join(); } + + _LIBCPP_HIDE_FROM_ABI void detach() { __thread_.detach(); } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI id get_id() const noexcept { return __thread_.get_id(); } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return __thread_.native_handle(); } + + // [thread.jthread.stop], stop token handling + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI stop_source get_stop_source() noexcept { return __stop_source_; } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI stop_token get_stop_token() const noexcept { return __stop_source_.get_token(); } + + _LIBCPP_HIDE_FROM_ABI bool request_stop() noexcept { return __stop_source_.request_stop(); } + + // [thread.jthread.special], specialized algorithms + _LIBCPP_HIDE_FROM_ABI friend void swap(jthread& __lhs, jthread& __rhs) noexcept { __lhs.swap(__rhs); } + + // [thread.jthread.static], static members + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static unsigned int hardware_concurrency() noexcept { + return thread::hardware_concurrency(); + } + +private: + template <class _Fun, class... _Args> + _LIBCPP_HIDE_FROM_ABI static thread __init_thread(const stop_source& __ss, _Fun&& __fun, _Args&&... __args) { + if constexpr (is_invocable_v<decay_t<_Fun>, stop_token, decay_t<_Args>...>) { + return thread(std::forward<_Fun>(__fun), __ss.get_token(), std::forward<_Args>(__args)...); + } else { + return thread(std::forward<_Fun>(__fun), std::forward<_Args>(__args)...); + } + } + + stop_source __stop_source_; + thread __thread_; +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_THREADS + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___THREAD_JTHREAD_H diff --git a/third_party/libcxx/include/c++/v1/__thread/poll_with_backoff.h b/third_party/libcxx/include/c++/v1/__thread/poll_with_backoff.h new file mode 100644 index 0000000..e007e77 --- /dev/null +++ b/third_party/libcxx/include/c++/v1/__thread/poll_with_backoff.h @@ -0,0 +1,86 @@ +// -*- 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___THREAD_POLL_WITH_BACKOFF_H +#define _LIBCPP___THREAD_POLL_WITH_BACKOFF_H + +#include <__chrono/duration.h> +#include <__chrono/high_resolution_clock.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +static _LIBCPP_CONSTEXPR const int __libcpp_polling_count = 64; + +enum class __backoff_results : unsigned char { + __continue_poll = 1, + __poll_success = 2, + __timeout = 3, + __backoff_failure = 4, +}; + +enum class __poll_with_backoff_results : unsigned char { + __poll_success = static_cast<unsigned char>(__backoff_results::__poll_success), + __timeout = static_cast<unsigned char>(__backoff_results::__timeout), + __backoff_failure = static_cast<unsigned char>(__backoff_results::__backoff_failure), +}; + +// Polls a thread for a condition given by a predicate, and backs off based on a backoff policy +// before polling again. +// +// - __poll is the "test function" that should return true if polling succeeded, and false if it failed. +// +// - __backoff is the "backoff policy", which is called with the duration since we started polling. It should +// return __backoff_results::__continue_poll in order to resume polling, and other appropriate __backoff_results +// if polling should stop entirely for some reason. +// In general, backoff policies sleep for some time before returning control to the polling loop. +// +// - __max_elapsed is the maximum duration to try polling for. If the maximum duration is exceeded, +// the polling loop will return __poll_with_backoff_results::__timeout to report a timeout. + +template <class _Poll, class _Backoff> +_LIBCPP_HIDE_FROM_ABI __poll_with_backoff_results __libcpp_thread_poll_with_backoff( + _Poll&& __poll, _Backoff&& __backoff, chrono::nanoseconds __max_elapsed = chrono::nanoseconds::zero()) { + auto const __start = chrono::high_resolution_clock::now(); + for (int __count = 0;;) { + if (__poll()) + return __poll_with_backoff_results::__poll_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 __poll_with_backoff_results::__timeout; + if (auto __backoff_res = __backoff(__elapsed); __backoff_res == __backoff_results::__continue_poll) + continue; + else + return static_cast<__poll_with_backoff_results>(__backoff_res); + } +} + +// A trivial backoff policy that always immediately returns the control to +// the polling loop. +// +// This is not very well-behaved since it will cause the polling loop to spin, +// so this should most likely only be used on single-threaded systems where there +// are no other threads to compete with. +struct __spinning_backoff_policy { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __backoff_results operator()(chrono::nanoseconds const&) const { + return __backoff_results::__continue_poll; + } +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___THREAD_POLL_WITH_BACKOFF_H diff --git a/third_party/libcxx/include/c++/v1/__thread/support.h b/third_party/libcxx/include/c++/v1/__thread/support.h new file mode 100644 index 0000000..50a18da --- /dev/null +++ b/third_party/libcxx/include/c++/v1/__thread/support.h @@ -0,0 +1,123 @@ +// -*- 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___THREAD_SUPPORT_H +#define _LIBCPP___THREAD_SUPPORT_H + +#include <__config> + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +# pragma GCC system_header +#endif + +/* + +// +// The library supports multiple implementations of the basic threading functionality. +// The following functionality must be provided by any implementation: +// + +_LIBCPP_BEGIN_NAMESPACE_STD + +using __libcpp_timespec_t = ...; + +// +// Mutex +// +using __libcpp_mutex_t = ...; +#define _LIBCPP_MUTEX_INITIALIZER ... + +using __libcpp_recursive_mutex_t = ...; + +int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t*); +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t*); +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t*); +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t*); +int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t*); + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_lock(__libcpp_mutex_t*); +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_mutex_trylock(__libcpp_mutex_t*); +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_unlock(__libcpp_mutex_t*); +int __libcpp_mutex_destroy(__libcpp_mutex_t*); + +// +// Condition Variable +// +using __libcpp_condvar_t = ...; +#define _LIBCPP_CONDVAR_INITIALIZER ... + +int __libcpp_condvar_signal(__libcpp_condvar_t*); +int __libcpp_condvar_broadcast(__libcpp_condvar_t*); +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_condvar_wait(__libcpp_condvar_t*, __libcpp_mutex_t*); +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS +int __libcpp_condvar_timedwait(__libcpp_condvar_t*, __libcpp_mutex_t*, __libcpp_timespec_t*); +int __libcpp_condvar_destroy(__libcpp_condvar_t*); + +// +// Execute once +// +using __libcpp_exec_once_flag = ...; +#define _LIBCPP_EXEC_ONCE_INITIALIZER ... + +int __libcpp_execute_once(__libcpp_exec_once_flag*, void (*__init_routine)()); + +// +// Thread id +// +using __libcpp_thread_id = ...; + +bool __libcpp_thread_id_equal(__libcpp_thread_id, __libcpp_thread_id); +bool __libcpp_thread_id_less(__libcpp_thread_id, __libcpp_thread_id); + +// +// Thread +// +#define _LIBCPP_NULL_THREAD ... +using __libcpp_thread_t = ...; + +bool __libcpp_thread_isnull(const __libcpp_thread_t*); +int __libcpp_thread_create(__libcpp_thread_t*, void* (*__func)(void*), void* __arg); +__libcpp_thread_id __libcpp_thread_get_current_id(); +__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t*); +int __libcpp_thread_join(__libcpp_thread_t*); +int __libcpp_thread_detach(__libcpp_thread_t*); +void __libcpp_thread_yield(); +void __libcpp_thread_sleep_for(const chrono::nanoseconds&); + +// +// Thread local storage +// +#define _LIBCPP_TLS_DESTRUCTOR_CC ... +using __libcpp_tls_key = ...; + +int __libcpp_tls_create(__libcpp_tls_key*, void (*__at_exit)(void*)); +void* __libcpp_tls_get(__libcpp_tls_key); +int __libcpp_tls_set(__libcpp_tls_key, void*); + +_LIBCPP_END_NAMESPACE_STD + +*/ + +#if _LIBCPP_HAS_THREADS + +# if _LIBCPP_HAS_THREAD_API_EXTERNAL +# include <__thread/support/external.h> +# elif _LIBCPP_HAS_THREAD_API_PTHREAD +# include <__thread/support/pthread.h> +# elif _LIBCPP_HAS_THREAD_API_C11 +# include <__thread/support/c11.h> +# elif _LIBCPP_HAS_THREAD_API_WIN32 +# include <__thread/support/windows.h> +# else +# error "No threading API was selected" +# endif + +#endif // _LIBCPP_HAS_THREADS + +#endif // _LIBCPP___THREAD_SUPPORT_H diff --git a/third_party/libcxx/include/c++/v1/__thread/support/c11.h b/third_party/libcxx/include/c++/v1/__thread/support/c11.h new file mode 100644 index 0000000..463c849 --- /dev/null +++ b/third_party/libcxx/include/c++/v1/__thread/support/c11.h @@ -0,0 +1,191 @@ +// -*- 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___THREAD_SUPPORT_C11_H +#define _LIBCPP___THREAD_SUPPORT_C11_H + +#include <__chrono/convert_to_timespec.h> +#include <__chrono/duration.h> +#include <__config> +#include <ctime> +#include <errno.h> +#include <threads.h> + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +using __libcpp_timespec_t = ::timespec; + +// +// 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; + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t* __m) { + return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL; +} + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int +__libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m) { + return mtx_lock(__m) == thrd_success ? 0 : EINVAL; +} + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI bool +__libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m) { + return mtx_trylock(__m) == thrd_success; +} + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int +__libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t* __m) { + return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; +} + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t* __m) { + mtx_destroy(__m); + return 0; +} + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int __libcpp_mutex_lock(__libcpp_mutex_t* __m) { + return mtx_lock(__m) == thrd_success ? 0 : EINVAL; +} + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m) { + return mtx_trylock(__m) == thrd_success; +} + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int __libcpp_mutex_unlock(__libcpp_mutex_t* __m) { + return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; +} + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_mutex_destroy(__libcpp_mutex_t* __m) { + mtx_destroy(__m); + return 0; +} + +// +// Condition Variable +// +typedef cnd_t __libcpp_condvar_t; +// cnd_t is a struct so using {} for initialization is valid. +#define _LIBCPP_CONDVAR_INITIALIZER \ + {} + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_signal(__libcpp_condvar_t* __cv) { + return cnd_signal(__cv) == thrd_success ? 0 : EINVAL; +} + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv) { + return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL; +} + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int +__libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) { + return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL; +} + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI 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; +} + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv) { + cnd_destroy(__cv); + return 0; +} + +// +// Execute once +// +typedef ::once_flag __libcpp_exec_once_flag; +#define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_execute_once(__libcpp_exec_once_flag* flag, void (*init_routine)(void)) { + ::call_once(flag, init_routine); + return 0; +} + +// +// Thread id +// +typedef thrd_t __libcpp_thread_id; + +// Returns non-zero if the thread ids are equal, otherwise 0 +inline _LIBCPP_HIDE_FROM_ABI 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 +inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) { + return t1 < t2; +} + +// +// Thread +// +#define _LIBCPP_NULL_THREAD 0U + +typedef thrd_t __libcpp_thread_t; + +inline _LIBCPP_HIDE_FROM_ABI __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t) { return *__t; } + +inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_isnull(const __libcpp_thread_t* __t) { + return __libcpp_thread_get_id(__t) == 0; +} + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg) { + int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg); + return __ec == thrd_nomem ? ENOMEM : __ec; +} + +inline _LIBCPP_HIDE_FROM_ABI __libcpp_thread_id __libcpp_thread_get_current_id() { return thrd_current(); } + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_join(__libcpp_thread_t* __t) { + return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL; +} + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_detach(__libcpp_thread_t* __t) { + return thrd_detach(*__t) == thrd_success ? 0 : EINVAL; +} + +inline _LIBCPP_HIDE_FROM_ABI void __libcpp_thread_yield() { thrd_yield(); } + +inline _LIBCPP_HIDE_FROM_ABI void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) { + __libcpp_timespec_t __ts = std::__convert_to_timespec<__libcpp_timespec_t>(__ns); + thrd_sleep(&__ts, nullptr); +} + +// +// Thread local storage +// +#define _LIBCPP_TLS_DESTRUCTOR_CC /* nothing */ + +typedef tss_t __libcpp_tls_key; + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_tls_create(__libcpp_tls_key* __key, void (*__at_exit)(void*)) { + return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL; +} + +inline _LIBCPP_HIDE_FROM_ABI void* __libcpp_tls_get(__libcpp_tls_key __key) { return tss_get(__key); } + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_tls_set(__libcpp_tls_key __key, void* __p) { + return tss_set(__key, __p) == thrd_success ? 0 : EINVAL; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___THREAD_SUPPORT_C11_H diff --git a/third_party/libcxx/include/c++/v1/__thread/support/external.h b/third_party/libcxx/include/c++/v1/__thread/support/external.h new file mode 100644 index 0000000..d5e2124 --- /dev/null +++ b/third_party/libcxx/include/c++/v1/__thread/support/external.h @@ -0,0 +1,21 @@ +// -*- 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___THREAD_SUPPORT_EXTERNAL_H +#define _LIBCPP___THREAD_SUPPORT_EXTERNAL_H + +#include <__config> + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +# pragma GCC system_header +#endif + +#include <__external_threading> + +#endif // _LIBCPP___THREAD_SUPPORT_EXTERNAL_H diff --git a/third_party/libcxx/include/c++/v1/__thread/support/pthread.h b/third_party/libcxx/include/c++/v1/__thread/support/pthread.h new file mode 100644 index 0000000..4cf5c03 --- /dev/null +++ b/third_party/libcxx/include/c++/v1/__thread/support/pthread.h @@ -0,0 +1,221 @@ +// -*- 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___THREAD_SUPPORT_PTHREAD_H +#define _LIBCPP___THREAD_SUPPORT_PTHREAD_H + +#include <__chrono/convert_to_timespec.h> +#include <__chrono/duration.h> +#include <__config> +#include <ctime> +#include <errno.h> +#include <pthread.h> +#include <sched.h> + +#ifdef __MVS__ +# include <__support/ibm/nanosleep.h> +#endif + +// Some platforms require <bits/atomic_wide_counter.h> in order for +// PTHREAD_COND_INITIALIZER to be expanded. Normally that would come +// in via <pthread.h>, but it's a non-modular header on those platforms, +// so libc++'s <math.h> usually absorbs atomic_wide_counter.h into the +// module with <math.h> and makes atomic_wide_counter.h invisible. +// Include <math.h> here to work around that. +// This checks wheter a Clang module is built +#if __building_module(std) +# include <math.h> +#endif + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +using __libcpp_timespec_t _LIBCPP_NODEBUG = ::timespec; + +// +// Mutex +// +typedef pthread_mutex_t __libcpp_mutex_t; +#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER + +typedef pthread_mutex_t __libcpp_recursive_mutex_t; + +inline _LIBCPP_HIDE_FROM_ABI 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; +} + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int +__libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m) { + return pthread_mutex_lock(__m); +} + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI bool +__libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m) { + return pthread_mutex_trylock(__m) == 0; +} + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int +__libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t* __m) { + return pthread_mutex_unlock(__m); +} + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t* __m) { + return pthread_mutex_destroy(__m); +} + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int __libcpp_mutex_lock(__libcpp_mutex_t* __m) { + return pthread_mutex_lock(__m); +} + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m) { + return pthread_mutex_trylock(__m) == 0; +} + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int __libcpp_mutex_unlock(__libcpp_mutex_t* __m) { + return pthread_mutex_unlock(__m); +} + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_mutex_destroy(__libcpp_mutex_t* __m) { return pthread_mutex_destroy(__m); } + +// +// Condition Variable +// +typedef pthread_cond_t __libcpp_condvar_t; +#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_signal(__libcpp_condvar_t* __cv) { return pthread_cond_signal(__cv); } + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv) { + return pthread_cond_broadcast(__cv); +} + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int +__libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) { + return pthread_cond_wait(__cv, __m); +} + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int +__libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, __libcpp_timespec_t* __ts) { + return pthread_cond_timedwait(__cv, __m, __ts); +} + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv) { + return pthread_cond_destroy(__cv); +} + +// +// Execute once +// +typedef pthread_once_t __libcpp_exec_once_flag; +#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_execute_once(__libcpp_exec_once_flag* __flag, void (*__init_routine)()) { + return pthread_once(__flag, __init_routine); +} + +// +// Thread id +// +#if defined(__MVS__) +typedef unsigned long long __libcpp_thread_id; +#else +typedef pthread_t __libcpp_thread_id; +#endif + +// Returns non-zero if the thread ids are equal, otherwise 0 +inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2) { + return __t1 == __t2; +} + +// Returns non-zero if t1 < t2, otherwise 0 +inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2) { + return __t1 < __t2; +} + +// +// Thread +// +#define _LIBCPP_NULL_THREAD ((__libcpp_thread_t())) +typedef pthread_t __libcpp_thread_t; + +inline _LIBCPP_HIDE_FROM_ABI __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t) { +#if defined(__MVS__) + return __t->__; +#else + return *__t; +#endif +} + +inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_isnull(const __libcpp_thread_t* __t) { + return __libcpp_thread_get_id(__t) == 0; +} + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg) { + return pthread_create(__t, nullptr, __func, __arg); +} + +inline _LIBCPP_HIDE_FROM_ABI __libcpp_thread_id __libcpp_thread_get_current_id() { + const __libcpp_thread_t __current_thread = pthread_self(); + return __libcpp_thread_get_id(&__current_thread); +} + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_join(__libcpp_thread_t* __t) { return pthread_join(*__t, nullptr); } + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_detach(__libcpp_thread_t* __t) { return pthread_detach(*__t); } + +inline _LIBCPP_HIDE_FROM_ABI void __libcpp_thread_yield() { sched_yield(); } + +inline _LIBCPP_HIDE_FROM_ABI void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) { + __libcpp_timespec_t __ts = std::__convert_to_timespec<__libcpp_timespec_t>(__ns); + while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR) + ; +} + +// +// Thread local storage +// +#define _LIBCPP_TLS_DESTRUCTOR_CC /* nothing */ + +typedef pthread_key_t __libcpp_tls_key; + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_tls_create(__libcpp_tls_key* __key, void (*__at_exit)(void*)) { + return pthread_key_create(__key, __at_exit); +} + +inline _LIBCPP_HIDE_FROM_ABI void* __libcpp_tls_get(__libcpp_tls_key __key) { return pthread_getspecific(__key); } + +inline _LIBCPP_HIDE_FROM_ABI int __libcpp_tls_set(__libcpp_tls_key __key, void* __p) { + return pthread_setspecific(__key, __p); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___THREAD_SUPPORT_PTHREAD_H diff --git a/third_party/libcxx/include/c++/v1/__thread/support/windows.h b/third_party/libcxx/include/c++/v1/__thread/support/windows.h new file mode 100644 index 0000000..558b5c8 --- /dev/null +++ b/third_party/libcxx/include/c++/v1/__thread/support/windows.h @@ -0,0 +1,131 @@ +// -*- 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___THREAD_SUPPORT_WINDOWS_H +#define _LIBCPP___THREAD_SUPPORT_WINDOWS_H + +#include <__chrono/duration.h> +#include <__config> +#include <ctime> + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +using __libcpp_timespec_t = ::timespec; + +// +// Mutex +// +typedef void* __libcpp_mutex_t; +#define _LIBCPP_MUTEX_INITIALIZER 0 + +#if defined(_WIN64) +typedef void* __libcpp_recursive_mutex_t[5]; +#else +typedef void* __libcpp_recursive_mutex_t[6]; +#endif + +_LIBCPP_EXPORTED_FROM_ABI int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t* __m); + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_EXPORTED_FROM_ABI int +__libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m); + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_EXPORTED_FROM_ABI bool +__libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m); + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_EXPORTED_FROM_ABI int +__libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t* __m); + +_LIBCPP_EXPORTED_FROM_ABI int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t* __m); + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_EXPORTED_FROM_ABI int __libcpp_mutex_lock(__libcpp_mutex_t* __m); + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_EXPORTED_FROM_ABI bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m); + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_EXPORTED_FROM_ABI int __libcpp_mutex_unlock(__libcpp_mutex_t* __m); + +_LIBCPP_EXPORTED_FROM_ABI int __libcpp_mutex_destroy(__libcpp_mutex_t* __m); + +// +// Condition variable +// +typedef void* __libcpp_condvar_t; +#define _LIBCPP_CONDVAR_INITIALIZER 0 + +_LIBCPP_EXPORTED_FROM_ABI int __libcpp_condvar_signal(__libcpp_condvar_t* __cv); + +_LIBCPP_EXPORTED_FROM_ABI int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_EXPORTED_FROM_ABI int +__libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); + +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_EXPORTED_FROM_ABI int +__libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, __libcpp_timespec_t* __ts); + +_LIBCPP_EXPORTED_FROM_ABI int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); + +// +// Execute once +// +typedef void* __libcpp_exec_once_flag; +#define _LIBCPP_EXEC_ONCE_INITIALIZER 0 + +_LIBCPP_EXPORTED_FROM_ABI int __libcpp_execute_once(__libcpp_exec_once_flag* __flag, void (*__init_routine)()); + +// +// Thread id +// +typedef long __libcpp_thread_id; + +_LIBCPP_EXPORTED_FROM_ABI bool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2); + +_LIBCPP_EXPORTED_FROM_ABI bool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2); + +// +// Thread +// +#define _LIBCPP_NULL_THREAD 0U +typedef void* __libcpp_thread_t; + +_LIBCPP_EXPORTED_FROM_ABI bool __libcpp_thread_isnull(const __libcpp_thread_t* __t); + +_LIBCPP_EXPORTED_FROM_ABI int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg); + +_LIBCPP_EXPORTED_FROM_ABI __libcpp_thread_id __libcpp_thread_get_current_id(); + +_LIBCPP_EXPORTED_FROM_ABI __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t); + +_LIBCPP_EXPORTED_FROM_ABI int __libcpp_thread_join(__libcpp_thread_t* __t); + +_LIBCPP_EXPORTED_FROM_ABI int __libcpp_thread_detach(__libcpp_thread_t* __t); + +_LIBCPP_EXPORTED_FROM_ABI void __libcpp_thread_yield(); + +_LIBCPP_EXPORTED_FROM_ABI void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); + +// +// Thread local storage +// +typedef long __libcpp_tls_key; + +#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall + +_LIBCPP_EXPORTED_FROM_ABI int +__libcpp_tls_create(__libcpp_tls_key* __key, void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); + +_LIBCPP_EXPORTED_FROM_ABI void* __libcpp_tls_get(__libcpp_tls_key __key); + +_LIBCPP_EXPORTED_FROM_ABI int __libcpp_tls_set(__libcpp_tls_key __key, void* __p); + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___THREAD_SUPPORT_WINDOWS_H diff --git a/third_party/libcxx/include/c++/v1/__thread/this_thread.h b/third_party/libcxx/include/c++/v1/__thread/this_thread.h new file mode 100644 index 0000000..4df1377 --- /dev/null +++ b/third_party/libcxx/include/c++/v1/__thread/this_thread.h @@ -0,0 +1,79 @@ +// -*- 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___THREAD_THIS_THREAD_H +#define _LIBCPP___THREAD_THIS_THREAD_H + +#include <__chrono/duration.h> +#include <__chrono/steady_clock.h> +#include <__chrono/time_point.h> +#include <__condition_variable/condition_variable.h> +#include <__config> +#include <__mutex/mutex.h> +#include <__mutex/unique_lock.h> +#include <__thread/support.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace this_thread { + +#if _LIBCPP_HAS_THREADS + +_LIBCPP_EXPORTED_FROM_ABI void sleep_for(const chrono::nanoseconds& __ns); + +template <class _Rep, class _Period> +_LIBCPP_HIDE_FROM_ABI void sleep_for(const chrono::duration<_Rep, _Period>& __d) { + if (__d > chrono::duration<_Rep, _Period>::zero()) { + // The standard guarantees a 64bit signed integer resolution for nanoseconds, + // so use INT64_MAX / 1e9 as cut-off point. Use a constant to avoid <climits> + // and issues with long double folding on PowerPC with GCC. + _LIBCPP_CONSTEXPR chrono::duration<long double> __max = chrono::duration<long double>(9223372036.0L); + chrono::nanoseconds __ns; + if (__d < __max) { + __ns = chrono::duration_cast<chrono::nanoseconds>(__d); + if (__ns < __d) + ++__ns; + } else + __ns = chrono::nanoseconds::max(); + this_thread::sleep_for(__ns); + } +} + +template <class _Clock, class _Duration> +_LIBCPP_HIDE_FROM_ABI void sleep_until(const chrono::time_point<_Clock, _Duration>& __t) { + mutex __mut; + condition_variable __cv; + unique_lock<mutex> __lk(__mut); + while (_Clock::now() < __t) + __cv.wait_until(__lk, __t); +} + +template <class _Duration> +inline _LIBCPP_HIDE_FROM_ABI void sleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t) { + this_thread::sleep_for(__t - chrono::steady_clock::now()); +} + +inline _LIBCPP_HIDE_FROM_ABI void yield() _NOEXCEPT { __libcpp_thread_yield(); } + +#endif // _LIBCPP_HAS_THREADS + +} // namespace this_thread + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___THREAD_THIS_THREAD_H diff --git a/third_party/libcxx/include/c++/v1/__thread/thread.h b/third_party/libcxx/include/c++/v1/__thread/thread.h new file mode 100644 index 0000000..b2f51aa --- /dev/null +++ b/third_party/libcxx/include/c++/v1/__thread/thread.h @@ -0,0 +1,268 @@ +// -*- 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___THREAD_THREAD_H +#define _LIBCPP___THREAD_THREAD_H + +#include <__assert> +#include <__condition_variable/condition_variable.h> +#include <__config> +#include <__exception/terminate.h> +#include <__functional/hash.h> +#include <__functional/unary_function.h> +#include <__locale> +#include <__memory/addressof.h> +#include <__memory/unique_ptr.h> +#include <__mutex/mutex.h> +#include <__system_error/throw_system_error.h> +#include <__thread/id.h> +#include <__thread/support.h> +#include <__type_traits/decay.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/invoke.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_same.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/forward.h> +#include <tuple> + +#if _LIBCPP_HAS_LOCALIZATION +# include <sstream> +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_HAS_THREADS + +template <class _Tp> +class __thread_specific_ptr; +class _LIBCPP_EXPORTED_FROM_ABI __thread_struct; +class _LIBCPP_HIDDEN __thread_struct_imp; +class __assoc_sub_state; + +_LIBCPP_EXPORTED_FROM_ABI __thread_specific_ptr<__thread_struct>& __thread_local_data(); + +class _LIBCPP_EXPORTED_FROM_ABI __thread_struct { + __thread_struct_imp* __p_; + + __thread_struct(const __thread_struct&); + __thread_struct& operator=(const __thread_struct&); + +public: + __thread_struct(); + ~__thread_struct(); + + void notify_all_at_thread_exit(condition_variable*, mutex*); + void __make_ready_at_thread_exit(__assoc_sub_state*); +}; + +template <class _Tp> +class __thread_specific_ptr { + __libcpp_tls_key __key_; + + // Only __thread_local_data() may construct a __thread_specific_ptr + // and only with _Tp == __thread_struct. + static_assert(is_same<_Tp, __thread_struct>::value, ""); + __thread_specific_ptr(); + friend _LIBCPP_EXPORTED_FROM_ABI __thread_specific_ptr<__thread_struct>& __thread_local_data(); + + _LIBCPP_HIDDEN static void _LIBCPP_TLS_DESTRUCTOR_CC __at_thread_exit(void*); + +public: + typedef _Tp* pointer; + + __thread_specific_ptr(const __thread_specific_ptr&) = delete; + __thread_specific_ptr& operator=(const __thread_specific_ptr&) = delete; + ~__thread_specific_ptr(); + + _LIBCPP_HIDE_FROM_ABI pointer get() const { return static_cast<_Tp*>(__libcpp_tls_get(__key_)); } + _LIBCPP_HIDE_FROM_ABI pointer operator*() const { return *get(); } + _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return get(); } + void set_pointer(pointer __p); +}; + +template <class _Tp> +void _LIBCPP_TLS_DESTRUCTOR_CC __thread_specific_ptr<_Tp>::__at_thread_exit(void* __p) { + delete static_cast<pointer>(__p); +} + +template <class _Tp> +__thread_specific_ptr<_Tp>::__thread_specific_ptr() { + int __ec = __libcpp_tls_create(&__key_, &__thread_specific_ptr::__at_thread_exit); + if (__ec) + std::__throw_system_error(__ec, "__thread_specific_ptr construction failed"); +} + +template <class _Tp> +__thread_specific_ptr<_Tp>::~__thread_specific_ptr() { + // __thread_specific_ptr is only created with a static storage duration + // so this destructor is only invoked during program termination. Invoking + // pthread_key_delete(__key_) may prevent other threads from deleting their + // thread local data. For this reason we leak the key. +} + +template <class _Tp> +void __thread_specific_ptr<_Tp>::set_pointer(pointer __p) { + _LIBCPP_ASSERT_INTERNAL(get() == nullptr, "Attempting to overwrite thread local data"); + std::__libcpp_tls_set(__key_, __p); +} + +template <> +struct hash<__thread_id> : public __unary_function<__thread_id, size_t> { + _LIBCPP_HIDE_FROM_ABI size_t operator()(__thread_id __v) const _NOEXCEPT { + return hash<__libcpp_thread_id>()(__v.__id_); + } +}; + +# if _LIBCPP_HAS_LOCALIZATION +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) { + // [thread.thread.id]/9 + // Effects: Inserts the text representation for charT of id into out. + // + // [thread.thread.id]/2 + // The text representation for the character type charT of an + // object of type thread::id is an unspecified sequence of charT + // such that, for two objects of type thread::id x and y, if + // x == y is true, the thread::id objects have the same text + // representation, and if x != y is true, the thread::id objects + // have distinct text representations. + // + // Since various flags in the output stream can affect how the + // thread id is represented (e.g. numpunct or showbase), we + // use a temporary stream instead and just output the thread + // id representation as a string. + + basic_ostringstream<_CharT, _Traits> __sstr; + __sstr.imbue(locale::classic()); + __sstr << __id.__id_; + return __os << __sstr.str(); +} +# endif // _LIBCPP_HAS_LOCALIZATION + +# ifndef _LIBCPP_CXX03_LANG + +template <class _TSp, class _Fp, class... _Args, size_t... _Indices> +inline _LIBCPP_HIDE_FROM_ABI void __thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __index_sequence<_Indices...>) { + std::__invoke(std::move(std::get<_Indices + 1>(__t))...); +} + +template <class _Fp> +_LIBCPP_HIDE_FROM_ABI void* __thread_proxy(void* __vp) { + // _Fp = tuple< unique_ptr<__thread_struct>, Functor, Args...> + unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); + __thread_local_data().set_pointer(std::get<0>(*__p.get()).release()); + std::__thread_execute(*__p.get(), __make_index_sequence<tuple_size<_Fp>::value - 1>()); + return nullptr; +} + +# else // _LIBCPP_CXX03_LANG + +template <class _Fp> +struct __thread_invoke_pair { + // This type is used to pass memory for thread local storage and a functor + // to a newly created thread because std::pair doesn't work with + // std::unique_ptr in C++03. + _LIBCPP_HIDE_FROM_ABI __thread_invoke_pair(_Fp& __f) : __tsp_(new __thread_struct), __fn_(__f) {} + unique_ptr<__thread_struct> __tsp_; + _Fp __fn_; +}; + +template <class _Fp> +_LIBCPP_HIDE_FROM_ABI void* __thread_proxy_cxx03(void* __vp) { + unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); + __thread_local_data().set_pointer(__p->__tsp_.release()); + (__p->__fn_)(); + return nullptr; +} + +# endif // _LIBCPP_CXX03_LANG + +class _LIBCPP_EXPORTED_FROM_ABI thread { + __libcpp_thread_t __t_; + + thread(const thread&); + thread& operator=(const thread&); + +public: + typedef __thread_id id; + typedef __libcpp_thread_t native_handle_type; + + _LIBCPP_HIDE_FROM_ABI thread() _NOEXCEPT : __t_(_LIBCPP_NULL_THREAD) {} + +# ifndef _LIBCPP_CXX03_LANG + template <class _Fp, class... _Args, __enable_if_t<!is_same<__remove_cvref_t<_Fp>, thread>::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI explicit thread(_Fp&& __f, _Args&&... __args) { + static_assert(is_constructible<__decay_t<_Fp>, _Fp>::value, ""); + static_assert(_And<is_constructible<__decay_t<_Args>, _Args>...>::value, ""); + static_assert(__is_invocable_v<__decay_t<_Fp>, __decay_t<_Args>...>, ""); + + typedef unique_ptr<__thread_struct> _TSPtr; + _TSPtr __tsp(new __thread_struct); + typedef tuple<_TSPtr, __decay_t<_Fp>, __decay_t<_Args>...> _Gp; + unique_ptr<_Gp> __p(new _Gp(std::move(__tsp), std::forward<_Fp>(__f), std::forward<_Args>(__args)...)); + int __ec = std::__libcpp_thread_create(&__t_, std::addressof(__thread_proxy<_Gp>), __p.get()); + if (__ec == 0) + __p.release(); + else + __throw_system_error(__ec, "thread constructor failed"); + } +# else // _LIBCPP_CXX03_LANG + template <class _Fp> + _LIBCPP_HIDE_FROM_ABI explicit thread(_Fp __f) { + typedef __thread_invoke_pair<_Fp> _InvokePair; + typedef unique_ptr<_InvokePair> _PairPtr; + _PairPtr __pp(new _InvokePair(__f)); + int __ec = std::__libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get()); + if (__ec == 0) + __pp.release(); + else + __throw_system_error(__ec, "thread constructor failed"); + } +# endif + ~thread(); + + _LIBCPP_HIDE_FROM_ABI thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) { __t.__t_ = _LIBCPP_NULL_THREAD; } + + _LIBCPP_HIDE_FROM_ABI thread& operator=(thread&& __t) _NOEXCEPT { + if (!__libcpp_thread_isnull(&__t_)) + terminate(); + __t_ = __t.__t_; + __t.__t_ = _LIBCPP_NULL_THREAD; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI void swap(thread& __t) _NOEXCEPT { std::swap(__t_, __t.__t_); } + + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool joinable() const _NOEXCEPT { return !__libcpp_thread_isnull(&__t_); } + void join(); + void detach(); + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI id get_id() const _NOEXCEPT { return __libcpp_thread_get_id(&__t_); } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() _NOEXCEPT { return __t_; } + + [[__nodiscard__]] static unsigned hardware_concurrency() _NOEXCEPT; +}; + +inline _LIBCPP_HIDE_FROM_ABI void swap(thread& __x, thread& __y) _NOEXCEPT { __x.swap(__y); } + +#endif // _LIBCPP_HAS_THREADS + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___THREAD_THREAD_H diff --git a/third_party/libcxx/include/c++/v1/__thread/timed_backoff_policy.h b/third_party/libcxx/include/c++/v1/__thread/timed_backoff_policy.h new file mode 100644 index 0000000..01fe2dd --- /dev/null +++ b/third_party/libcxx/include/c++/v1/__thread/timed_backoff_policy.h @@ -0,0 +1,45 @@ +// -*- 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___THREAD_TIMED_BACKOFF_POLICY_H +#define _LIBCPP___THREAD_TIMED_BACKOFF_POLICY_H + +#include <__config> +#include <__thread/poll_with_backoff.h> + +#if _LIBCPP_HAS_THREADS + +# include <__chrono/duration.h> +# include <__thread/support.h> + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct __libcpp_timed_backoff_policy { + _LIBCPP_HIDE_FROM_ABI __backoff_results 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 __backoff_results::__continue_poll; + } +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_THREADS + +#endif // _LIBCPP___THREAD_TIMED_BACKOFF_POLICY_H |
