[libcxx-commits] [libcxx] [libcxxabi] [libc++] Split the monolithic __threading_support header (PR #79654)

via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jan 26 14:03:53 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxxabi

@llvm/pr-subscribers-libcxx

Author: Louis Dionne (ldionne)

<details>
<summary>Changes</summary>

The <__threading_support> header is a huge beast and it's really difficult to navigate. I find myself struggling to find what I want every time I have to open it, and I've been considering splitting it up for years for that reason.

This patch aims not to contain any functional change. The various implementations of the threading base are simply moved to separate headers and then the individual headers are simplified in mechanical ways. For example, we used to have redundant declarations of all the functions at the top of `__threading_support`, and those are removed since they are not needed anymore. The various #ifdefs are also simplified and removed when they become unnecessary.

Finally, this patch adds documentation for the API we expect from any threading implementation.

---

Patch is 56.60 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/79654.diff


34 Files Affected:

- (modified) libcxx/docs/DesignDocs/ThreadingSupportAPI.rst (+9-5) 
- (modified) libcxx/include/CMakeLists.txt (+5-1) 
- (modified) libcxx/include/__atomic/atomic_flag.h (+1-1) 
- (modified) libcxx/include/__atomic/atomic_sync.h (+1-1) 
- (modified) libcxx/include/__condition_variable/condition_variable.h (+1-1) 
- (modified) libcxx/include/__mutex/mutex.h (+1-1) 
- (modified) libcxx/include/__thread/formatter.h (+1-1) 
- (modified) libcxx/include/__thread/id.h (+1-1) 
- (modified) libcxx/include/__thread/jthread.h (+1-1) 
- (added) libcxx/include/__thread/support.h (+118) 
- (added) libcxx/include/__thread/support/c11.h (+190) 
- (added) libcxx/include/__thread/support/external.h (+21) 
- (added) libcxx/include/__thread/support/pthread.h (+219) 
- (added) libcxx/include/__thread/support/windows.h (+133) 
- (modified) libcxx/include/__thread/this_thread.h (+1-1) 
- (modified) libcxx/include/__thread/thread.h (+1-1) 
- (modified) libcxx/include/__thread/timed_backoff_policy.h (+1-1) 
- (removed) libcxx/include/__threading_support (-456) 
- (modified) libcxx/include/libcxx.imp (+20) 
- (modified) libcxx/include/module.modulemap.in (+8-4) 
- (modified) libcxx/include/mutex (+1-1) 
- (modified) libcxx/include/semaphore (+1-1) 
- (modified) libcxx/include/thread (+1-1) 
- (modified) libcxx/src/call_once.cpp (+1-1) 
- (modified) libcxx/src/condition_variable_destructor.cpp (+1-1) 
- (modified) libcxx/src/mutex_destructor.cpp (+1-1) 
- (modified) libcxx/src/support/win32/thread_win32.cpp (+1-1) 
- (modified) libcxx/utils/generate_iwyu_mapping.py (+1-1) 
- (modified) libcxx/utils/libcxx/test/modules.py (-1) 
- (modified) libcxxabi/src/cxa_exception_storage.cpp (+1-1) 
- (modified) libcxxabi/src/cxa_guard_impl.h (+1-1) 
- (modified) libcxxabi/src/cxa_thread_atexit.cpp (+1-1) 
- (modified) libcxxabi/src/fallback_malloc.cpp (+1-1) 
- (modified) libcxxabi/test/test_fallback_malloc.pass.cpp (+1-1) 


``````````diff
diff --git a/libcxx/docs/DesignDocs/ThreadingSupportAPI.rst b/libcxx/docs/DesignDocs/ThreadingSupportAPI.rst
index 752a9d4d770a1c..e7f3de54e6782a 100644
--- a/libcxx/docs/DesignDocs/ThreadingSupportAPI.rst
+++ b/libcxx/docs/DesignDocs/ThreadingSupportAPI.rst
@@ -14,9 +14,9 @@ These different models provide entirely different interfaces from each
 other. To address this libc++ wraps the underlying threading API in a new and
 consistent API, which it uses internally to implement threading primitives.
 
-The ``<__threading_support>`` header is where libc++ defines its internal
-threading interface. It contains forward declarations of the internal threading
-interface as well as definitions for the interface.
+The ``<__thread/support.h>`` header is where libc++ defines its internal
+threading interface. It documents the functions and declarations required
+to fullfil the internal threading interface.
 
 External Threading API and the ``<__external_threading>`` header
 ================================================================
@@ -25,10 +25,10 @@ In order to support vendors with custom threading API's libc++ allows the
 entire internal threading interface to be provided by an external,
 vendor provided, header.
 
-When ``_LIBCPP_HAS_THREAD_API_EXTERNAL`` is defined the ``<__threading_support>``
+When ``_LIBCPP_HAS_THREAD_API_EXTERNAL`` is defined the ``<__thread/support.h>``
 header simply forwards to the ``<__external_threading>`` header (which must exist).
 It is expected that the ``<__external_threading>`` header provide the exact
-interface normally provided by ``<__threading_support>``.
+interface normally provided by ``<__thread/support.h>``.
 
 External Threading Library
 ==========================
@@ -58,6 +58,10 @@ Threading Configuration Macros
   This macro is defined when libc++ should use POSIX threads to implement the
   internal threading API.
 
+**_LIBCPP_HAS_THREAD_API_C11**
+  This macro is defined when libc++ should use C11 threads to implement the
+  internal threading API.
+
 **_LIBCPP_HAS_THREAD_API_WIN32**
   This macro is defined when libc++ should use Win32 threads to implement the
   internal threading API.
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index ed721d467e94f4..0bb23710cae849 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -688,10 +688,14 @@ set(files
   __thread/id.h
   __thread/jthread.h
   __thread/poll_with_backoff.h
+  __thread/support.h
+  __thread/support/c11.h
+  __thread/support/external.h
+  __thread/support/pthread.h
+  __thread/support/windows.h
   __thread/this_thread.h
   __thread/thread.h
   __thread/timed_backoff_policy.h
-  __threading_support
   __tree
   __tuple/make_tuple_types.h
   __tuple/pair_like.h
diff --git a/libcxx/include/__atomic/atomic_flag.h b/libcxx/include/__atomic/atomic_flag.h
index d76e5e45c01a02..a45a7183547726 100644
--- a/libcxx/include/__atomic/atomic_flag.h
+++ b/libcxx/include/__atomic/atomic_flag.h
@@ -15,7 +15,7 @@
 #include <__atomic/memory_order.h>
 #include <__chrono/duration.h>
 #include <__config>
-#include <__threading_support>
+#include <__thread/support.h>
 #include <cstdint>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
diff --git a/libcxx/include/__atomic/atomic_sync.h b/libcxx/include/__atomic/atomic_sync.h
index 3d20d6a8ce2514..93527958b2e1ce 100644
--- a/libcxx/include/__atomic/atomic_sync.h
+++ b/libcxx/include/__atomic/atomic_sync.h
@@ -17,7 +17,7 @@
 #include <__config>
 #include <__memory/addressof.h>
 #include <__thread/poll_with_backoff.h>
-#include <__threading_support>
+#include <__thread/support.h>
 #include <__type_traits/decay.h>
 #include <cstring>
 
diff --git a/libcxx/include/__condition_variable/condition_variable.h b/libcxx/include/__condition_variable/condition_variable.h
index 4d8e590e29db7f..2b1a817e2dfee6 100644
--- a/libcxx/include/__condition_variable/condition_variable.h
+++ b/libcxx/include/__condition_variable/condition_variable.h
@@ -16,7 +16,7 @@
 #include <__mutex/mutex.h>
 #include <__mutex/unique_lock.h>
 #include <__system_error/system_error.h>
-#include <__threading_support>
+#include <__thread/support.h>
 #include <__type_traits/enable_if.h>
 #include <__type_traits/is_floating_point.h>
 #include <__utility/move.h>
diff --git a/libcxx/include/__mutex/mutex.h b/libcxx/include/__mutex/mutex.h
index 4423abf62b8b78..ddc85cf5a00d51 100644
--- a/libcxx/include/__mutex/mutex.h
+++ b/libcxx/include/__mutex/mutex.h
@@ -10,7 +10,7 @@
 #define _LIBCPP___MUTEX_MUTEX_H
 
 #include <__config>
-#include <__threading_support>
+#include <__thread/support.h>
 #include <__type_traits/is_nothrow_default_constructible.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
diff --git a/libcxx/include/__thread/formatter.h b/libcxx/include/__thread/formatter.h
index 0454864ce93990..9b54036dcab36b 100644
--- a/libcxx/include/__thread/formatter.h
+++ b/libcxx/include/__thread/formatter.h
@@ -43,7 +43,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter<__thread_id, _CharT> {
 
   template <class _FormatContext>
   _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(__thread_id __id, _FormatContext& __ctx) const {
-    // In __threading_support __libcpp_thread_id is either a
+    // 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
diff --git a/libcxx/include/__thread/id.h b/libcxx/include/__thread/id.h
index 83b1d8eceede3b..d5aef3f860ce27 100644
--- a/libcxx/include/__thread/id.h
+++ b/libcxx/include/__thread/id.h
@@ -14,7 +14,7 @@
 #include <__config>
 #include <__fwd/hash.h>
 #include <__fwd/ostream.h>
-#include <__threading_support>
+#include <__thread/support.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
diff --git a/libcxx/include/__thread/jthread.h b/libcxx/include/__thread/jthread.h
index 2fbc8a36755e96..253e3a935d9b73 100644
--- a/libcxx/include/__thread/jthread.h
+++ b/libcxx/include/__thread/jthread.h
@@ -15,8 +15,8 @@
 #include <__functional/invoke.h>
 #include <__stop_token/stop_source.h>
 #include <__stop_token/stop_token.h>
+#include <__thread/support.h>
 #include <__thread/thread.h>
-#include <__threading_support>
 #include <__type_traits/decay.h>
 #include <__type_traits/is_constructible.h>
 #include <__type_traits/is_same.h>
diff --git a/libcxx/include/__thread/support.h b/libcxx/include/__thread/support.h
new file mode 100644
index 00000000000000..b05ee892c5f0f6
--- /dev/null
+++ b/libcxx/include/__thread/support.h
@@ -0,0 +1,118 @@
+// -*- 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:
+//
+
+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*);
+int __libcpp_condvar_wait(__libcpp_condvar_t*, __libcpp_mutex_t*);
+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*);
+
+*/
+
+#if !defined(_LIBCPP_HAS_NO_THREADS)
+
+#  if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
+#    include <__thread/support/external.h>
+#  elif defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
+#    include <__thread/support/pthread.h>
+#  elif defined(_LIBCPP_HAS_THREAD_API_C11)
+#    include <__thread/support/c11.h>
+#  elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
+#    include <__thread/support/windows.h>
+#  else
+#    error "No threading API was selected"
+#  endif
+
+#endif // !_LIBCPP_HAS_NO_THREADS
+
+#endif // _LIBCPP___THREAD_SUPPORT_H
diff --git a/libcxx/include/__thread/support/c11.h b/libcxx/include/__thread/support/c11.h
new file mode 100644
index 00000000000000..44515454d69581
--- /dev/null
+++ b/libcxx/include/__thread/support/c11.h
@@ -0,0 +1,190 @@
+// -*- 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 <threads.h>
+
+#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
+#  pragma GCC system_header
+#endif
+
+typedef ::timespec __libcpp_timespec_t;
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+//
+// 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;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
+__libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m) {
+  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool
+__libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m) {
+  return mtx_trylock(__m) == thrd_success;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 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;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_lock(__libcpp_mutex_t* __m) {
+  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m) {
+  return mtx_trylock(__m) == thrd_success;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 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;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
+__libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) {
+  return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 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/libcxx/include/__thread/support/external.h b/libcxx/include/__thread/support/external.h
new file mode 100644
index 00000000000000..d5e212491cfdbd
--- /dev/null
+++ b/libcxx/include/__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/libcxx/include/__thread/support/pthread.h b/libcxx/include/__thread/support/pthread.h
new file mode 100644
index 00000000000000..c129234433ac57
--- /dev/null
+++ b/libcxx/include/__thread/support/pthread.h
@@ -0,0 +1,219 @@
+// -*- 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 <__availability>
+#include <__chrono/convert_to_timespec.h>
+#include <__chrono/duration.h>
+#include <__config>
+#include <__fwd/hash.h>
+#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.
+#include <math.h>
+
+#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
+#  pragma GCC system_header
+#endif
+
+typedef ::timespec __libcpp_timespec_t;
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+//
+// 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;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSI...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/79654


More information about the libcxx-commits mailing list