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

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Mon Jan 29 11:31:38 PST 2024


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

>From 7c2838a311244743aeff7603e4fd8c07ea2e0ea2 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Fri, 26 Jan 2024 16:00:28 -0500
Subject: [PATCH 1/4] [libc++] Split the monolithic __threading_support header

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.
---
 .../docs/DesignDocs/ThreadingSupportAPI.rst   |  14 +-
 libcxx/include/CMakeLists.txt                 |   6 +-
 libcxx/include/__atomic/atomic_flag.h         |   2 +-
 libcxx/include/__atomic/atomic_sync.h         |   2 +-
 .../__condition_variable/condition_variable.h |   2 +-
 libcxx/include/__mutex/mutex.h                |   2 +-
 libcxx/include/__thread/formatter.h           |   2 +-
 libcxx/include/__thread/id.h                  |   2 +-
 libcxx/include/__thread/jthread.h             |   2 +-
 libcxx/include/__thread/support.h             | 118 +++++
 libcxx/include/__thread/support/c11.h         | 190 ++++++++
 libcxx/include/__thread/support/external.h    |  21 +
 libcxx/include/__thread/support/pthread.h     | 219 +++++++++
 libcxx/include/__thread/support/windows.h     | 133 +++++
 libcxx/include/__thread/this_thread.h         |   2 +-
 libcxx/include/__thread/thread.h              |   2 +-
 .../include/__thread/timed_backoff_policy.h   |   2 +-
 libcxx/include/__threading_support            | 456 ------------------
 libcxx/include/libcxx.imp                     |  20 +
 libcxx/include/module.modulemap.in            |  12 +-
 libcxx/include/mutex                          |   2 +-
 libcxx/include/semaphore                      |   2 +-
 libcxx/include/thread                         |   2 +-
 libcxx/src/call_once.cpp                      |   2 +-
 libcxx/src/condition_variable_destructor.cpp  |   2 +-
 libcxx/src/mutex_destructor.cpp               |   2 +-
 libcxx/src/support/win32/thread_win32.cpp     |   2 +-
 libcxx/utils/generate_iwyu_mapping.py         |   2 +-
 libcxx/utils/libcxx/test/modules.py           |   1 -
 libcxxabi/src/cxa_exception_storage.cpp       |   2 +-
 libcxxabi/src/cxa_guard_impl.h                |   2 +-
 libcxxabi/src/cxa_thread_atexit.cpp           |   2 +-
 libcxxabi/src/fallback_malloc.cpp             |   2 +-
 libcxxabi/test/test_fallback_malloc.pass.cpp  |   2 +-
 34 files changed, 746 insertions(+), 490 deletions(-)
 create mode 100644 libcxx/include/__thread/support.h
 create mode 100644 libcxx/include/__thread/support/c11.h
 create mode 100644 libcxx/include/__thread/support/external.h
 create mode 100644 libcxx/include/__thread/support/pthread.h
 create mode 100644 libcxx/include/__thread/support/windows.h
 delete mode 100644 libcxx/include/__threading_support

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_ANALYSIS int
+__libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m) {
+  return pthread_mutex_lock(__m);
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool
+__libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m) {
+  return pthread_mutex_trylock(__m) == 0;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 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);
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_lock(__libcpp_mutex_t* __m) {
+  return pthread_mutex_lock(__m);
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m) {
+  return pthread_mutex_trylock(__m) == 0;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 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);
+}
+
+inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) {
+  return pthread_cond_wait(__cv, __m);
+}
+
+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/libcxx/include/__thread/support/windows.h b/libcxx/include/__thread/support/windows.h
new file mode 100644
index 00000000000000..16d1f3ba5a3cc2
--- /dev/null
+++ b/libcxx/include/__thread/support/windows.h
@@ -0,0 +1,133 @@
+// -*- 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
+
+typedef ::timespec __libcpp_timespec_t;
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+//
+// 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
+
+_LIBCPP_EXPORTED_FROM_ABI int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t* __m);
+
+_LIBCPP_EXPORTED_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
+__libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m);
+
+_LIBCPP_EXPORTED_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool
+__libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m);
+
+_LIBCPP_EXPORTED_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 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_EXPORTED_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_lock(__libcpp_mutex_t* __m);
+
+_LIBCPP_EXPORTED_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m);
+
+_LIBCPP_EXPORTED_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 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_EXPORTED_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
+__libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
+
+_LIBCPP_EXPORTED_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 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/libcxx/include/__thread/this_thread.h b/libcxx/include/__thread/this_thread.h
index 6fb42533aab7c1..de7eea282c8749 100644
--- a/libcxx/include/__thread/this_thread.h
+++ b/libcxx/include/__thread/this_thread.h
@@ -16,7 +16,7 @@
 #include <__config>
 #include <__mutex/mutex.h>
 #include <__mutex/unique_lock.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/thread.h b/libcxx/include/__thread/thread.h
index 0ecaac1b011bee..28c2e21601ae29 100644
--- a/libcxx/include/__thread/thread.h
+++ b/libcxx/include/__thread/thread.h
@@ -19,7 +19,7 @@
 #include <__mutex/mutex.h>
 #include <__system_error/system_error.h>
 #include <__thread/id.h>
-#include <__threading_support>
+#include <__thread/support.h>
 #include <__utility/forward.h>
 #include <tuple>
 
diff --git a/libcxx/include/__thread/timed_backoff_policy.h b/libcxx/include/__thread/timed_backoff_policy.h
index 525f52b34914e2..838c918a57ef0d 100644
--- a/libcxx/include/__thread/timed_backoff_policy.h
+++ b/libcxx/include/__thread/timed_backoff_policy.h
@@ -15,7 +15,7 @@
 #ifndef _LIBCPP_HAS_NO_THREADS
 
 #  include <__chrono/duration.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/__threading_support b/libcxx/include/__threading_support
deleted file mode 100644
index ea6db4a3d59c1c..00000000000000
--- a/libcxx/include/__threading_support
+++ /dev/null
@@ -1,456 +0,0 @@
-// -*- 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 <__availability>
-#include <__chrono/convert_to_timespec.h>
-#include <__chrono/duration.h>
-#include <__config>
-#include <__fwd/hash.h>
-#include <ctime>
-#include <errno.h>
-
-#ifdef __MVS__
-#  include <__support/ibm/nanosleep.h>
-#endif
-
-#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)
-// 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>
-
-#    include <pthread.h>
-#    include <sched.h>
-#  elif defined(_LIBCPP_HAS_THREAD_API_C11)
-#    include <threads.h>
-#  endif
-
-#  if defined(_LIBCPP_HAS_THREAD_API_WIN32)
-#    define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_EXPORTED_FROM_ABI
-#  else
-#    define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_HIDE_FROM_ABI
-#  endif
-
-typedef ::timespec __libcpp_timespec_t;
-#endif // !defined(_LIBCPP_HAS_NO_THREADS)
-
-_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
-
-// Execute once
-typedef pthread_once_t __libcpp_exec_once_flag;
-#    define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
-
-// Thread id
-#    if defined(__MVS__)
-typedef unsigned long long __libcpp_thread_id;
-#    else
-typedef pthread_t __libcpp_thread_id;
-#    endif
-
-// Thread
-#    define _LIBCPP_NULL_THREAD ((__libcpp_thread_t()))
-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
-
-// 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);
-
-// 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)
-
-#  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_recursive_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); }
-
-// 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 __t1 == __t2; }
-
-// 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 __libcpp_thread_get_id(__t) == 0; }
-
-int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg) {
-  return pthread_create(__t, nullptr, __func, __arg);
-}
-
-__libcpp_thread_id __libcpp_thread_get_current_id() {
-  const __libcpp_thread_t __current_thread = pthread_self();
-  return __libcpp_thread_get_id(&__current_thread);
-}
-
-__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t) {
-#    if defined(__MVS__)
-  return __t->__;
-#    else
-  return *__t;
-#    endif
-}
-
-int __libcpp_thread_join(__libcpp_thread_t* __t) { return pthread_join(*__t, nullptr); }
-
-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 = std::__convert_to_timespec<__libcpp_timespec_t>(__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_recursive_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 __libcpp_thread_get_id(__t) == 0; }
-
-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;
-}
-
-__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 = std::__convert_to_timespec<__libcpp_timespec_t>(__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_NO_THREADS
-
-_LIBCPP_END_NAMESPACE_STD
-
-#endif // _LIBCPP___THREADING_SUPPORT
diff --git a/libcxx/include/libcxx.imp b/libcxx/include/libcxx.imp
index 45fa4a9541917f..13c0dfeb2bc98f 100644
--- a/libcxx/include/libcxx.imp
+++ b/libcxx/include/libcxx.imp
@@ -662,6 +662,26 @@
   { include: [ "<__thread/id.h>", "private", "<thread>", "public" ] },
   { include: [ "<__thread/jthread.h>", "private", "<thread>", "public" ] },
   { include: [ "<__thread/poll_with_backoff.h>", "private", "<thread>", "public" ] },
+  { include: [ "<__thread/support.h>", "private", "<atomic>", "public" ] },
+  { include: [ "<__thread/support.h>", "private", "<mutex>", "public" ] },
+  { include: [ "<__thread/support.h>", "private", "<semaphore>", "public" ] },
+  { include: [ "<__thread/support.h>", "private", "<thread>", "public" ] },
+  { include: [ "<__thread/support/c11.h>", "private", "<atomic>", "public" ] },
+  { include: [ "<__thread/support/c11.h>", "private", "<mutex>", "public" ] },
+  { include: [ "<__thread/support/c11.h>", "private", "<semaphore>", "public" ] },
+  { include: [ "<__thread/support/c11.h>", "private", "<thread>", "public" ] },
+  { include: [ "<__thread/support/external.h>", "private", "<atomic>", "public" ] },
+  { include: [ "<__thread/support/external.h>", "private", "<mutex>", "public" ] },
+  { include: [ "<__thread/support/external.h>", "private", "<semaphore>", "public" ] },
+  { include: [ "<__thread/support/external.h>", "private", "<thread>", "public" ] },
+  { include: [ "<__thread/support/pthread.h>", "private", "<atomic>", "public" ] },
+  { include: [ "<__thread/support/pthread.h>", "private", "<mutex>", "public" ] },
+  { include: [ "<__thread/support/pthread.h>", "private", "<semaphore>", "public" ] },
+  { include: [ "<__thread/support/pthread.h>", "private", "<thread>", "public" ] },
+  { include: [ "<__thread/support/windows.h>", "private", "<atomic>", "public" ] },
+  { include: [ "<__thread/support/windows.h>", "private", "<mutex>", "public" ] },
+  { include: [ "<__thread/support/windows.h>", "private", "<semaphore>", "public" ] },
+  { include: [ "<__thread/support/windows.h>", "private", "<thread>", "public" ] },
   { include: [ "<__thread/this_thread.h>", "private", "<thread>", "public" ] },
   { include: [ "<__thread/thread.h>", "private", "<thread>", "public" ] },
   { include: [ "<__thread/timed_backoff_policy.h>", "private", "<thread>", "public" ] },
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 194a74a1e07b14..207b44b6444bf6 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -614,10 +614,6 @@ module std_private_std_mbstate_t     [system] {
   header "__std_mbstate_t.h"
   export *
 }
-module std_private_threading_support [system] {
-  header "__threading_support"
-  export *
-}
 module std_private_tree              [system] {
   header "__tree"
   export *
@@ -1773,6 +1769,14 @@ module std_private_thread_jthread              [system] {
   export *
 }
 module std_private_thread_poll_with_backoff    [system] { header "__thread/poll_with_backoff.h" }
+module std_private_thread_support              [system] {
+  header "__thread/support.h"
+  export *
+}
+module std_private_thread_support_c11          [system] { textual header "__thread/support/c11.h" }
+module std_private_thread_support_external     [system] { textual header "__thread/support/external.h" }
+module std_private_thread_support_pthread      [system] { textual header "__thread/support/pthread.h" }
+module std_private_thread_support_windows      [system] { textual header "__thread/support/windows.h" }
 module std_private_thread_this_thread          [system] { header "__thread/this_thread.h" }
 module std_private_thread_thread               [system] {
   header "__thread/thread.h"
diff --git a/libcxx/include/mutex b/libcxx/include/mutex
index a16ef589c6970b..e67135fc0ec04e 100644
--- a/libcxx/include/mutex
+++ b/libcxx/include/mutex
@@ -198,7 +198,7 @@ template<class Callable, class ...Args>
 #include <__mutex/tag_types.h>
 #include <__mutex/unique_lock.h>
 #include <__thread/id.h>
-#include <__threading_support>
+#include <__thread/support.h>
 #include <__utility/forward.h>
 #include <cstddef>
 #include <limits>
diff --git a/libcxx/include/semaphore b/libcxx/include/semaphore
index ac3d2d7fe02e88..649705f45b049c 100644
--- a/libcxx/include/semaphore
+++ b/libcxx/include/semaphore
@@ -58,8 +58,8 @@ using binary_semaphore = counting_semaphore<1>;
 #include <__availability>
 #include <__chrono/time_point.h>
 #include <__thread/poll_with_backoff.h>
+#include <__thread/support.h>
 #include <__thread/timed_backoff_policy.h>
-#include <__threading_support>
 #include <cstddef>
 #include <limits>
 #include <version>
diff --git a/libcxx/include/thread b/libcxx/include/thread
index 84c80d04cf03c9..29c7e86785cde4 100644
--- a/libcxx/include/thread
+++ b/libcxx/include/thread
@@ -96,9 +96,9 @@ void sleep_for(const chrono::duration<Rep, Period>& rel_time);
 #include <__availability>
 #include <__thread/formatter.h>
 #include <__thread/jthread.h>
+#include <__thread/support.h>
 #include <__thread/this_thread.h>
 #include <__thread/thread.h>
-#include <__threading_support>
 #include <version>
 
 // standard-mandated includes
diff --git a/libcxx/src/call_once.cpp b/libcxx/src/call_once.cpp
index b596518a65401a..5744347f84b20c 100644
--- a/libcxx/src/call_once.cpp
+++ b/libcxx/src/call_once.cpp
@@ -10,7 +10,7 @@
 #include <__utility/exception_guard.h>
 
 #ifndef _LIBCPP_HAS_NO_THREADS
-#  include <__threading_support>
+#  include <__thread/support.h>
 #endif
 
 #include "include/atomic_support.h"
diff --git a/libcxx/src/condition_variable_destructor.cpp b/libcxx/src/condition_variable_destructor.cpp
index 8b62d4184018e7..59811ed7ff3564 100644
--- a/libcxx/src/condition_variable_destructor.cpp
+++ b/libcxx/src/condition_variable_destructor.cpp
@@ -12,7 +12,7 @@
 // definition is only provided for ABI compatibility.
 
 #include <__config>
-#include <__threading_support>
+#include <__thread/support.h>
 
 #if _LIBCPP_ABI_VERSION == 1 || !defined(_LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION)
 #  define NEEDS_CONDVAR_DESTRUCTOR
diff --git a/libcxx/src/mutex_destructor.cpp b/libcxx/src/mutex_destructor.cpp
index d5ac257f94d531..a6ceaaaf23ffed 100644
--- a/libcxx/src/mutex_destructor.cpp
+++ b/libcxx/src/mutex_destructor.cpp
@@ -17,7 +17,7 @@
 // _LIBCPP_BUILDING_LIBRARY to change the definition in the headers.
 
 #include <__config>
-#include <__threading_support>
+#include <__thread/support.h>
 
 #if _LIBCPP_ABI_VERSION == 1 || !defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION)
 #  define NEEDS_MUTEX_DESTRUCTOR
diff --git a/libcxx/src/support/win32/thread_win32.cpp b/libcxx/src/support/win32/thread_win32.cpp
index 8736a532073b4b..a2585c0b89f287 100644
--- a/libcxx/src/support/win32/thread_win32.cpp
+++ b/libcxx/src/support/win32/thread_win32.cpp
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include <__threading_support>
+#include <__thread/support/windows.h>
 #include <chrono>
 
 #define NOMINMAX
diff --git a/libcxx/utils/generate_iwyu_mapping.py b/libcxx/utils/generate_iwyu_mapping.py
index fd669172e29ab5..0a650250e747f6 100644
--- a/libcxx/utils/generate_iwyu_mapping.py
+++ b/libcxx/utils/generate_iwyu_mapping.py
@@ -30,7 +30,7 @@ def IWYU_mapping(header: str) -> typing.Optional[typing.List[str]]:
         return ["map", "set", "unordered_map", "unordered_set"]
     elif header == "__split_buffer":
         return ["deque", "vector"]
-    elif header == "__threading_support":
+    elif re.match("(__thread/support[.]h)|(__thread/support/.+)", header):
         return ["atomic", "mutex", "semaphore", "thread"]
     elif header == "__tree":
         return ["map", "set"]
diff --git a/libcxx/utils/libcxx/test/modules.py b/libcxx/utils/libcxx/test/modules.py
index 3e9fcae4c5389a..3f3c7999a1a21d 100644
--- a/libcxx/utils/libcxx/test/modules.py
+++ b/libcxx/utils/libcxx/test/modules.py
@@ -93,7 +93,6 @@
 ExtraHeader = dict()
 # locale has a file and not a subdirectory
 ExtraHeader["locale"] = "v1/__locale$"
-ExtraHeader["thread"] = "v1/__threading_support$"
 ExtraHeader["ranges"] = "v1/__fwd/subrange.h$"
 
 # The extra header is needed since two headers are required to provide the
diff --git a/libcxxabi/src/cxa_exception_storage.cpp b/libcxxabi/src/cxa_exception_storage.cpp
index 3a3233a1b92722..2479f550e09eff 100644
--- a/libcxxabi/src/cxa_exception_storage.cpp
+++ b/libcxxabi/src/cxa_exception_storage.cpp
@@ -12,7 +12,7 @@
 
 #include "cxa_exception.h"
 
-#include <__threading_support>
+#include <__thread/support.h>
 
 #if defined(_LIBCXXABI_HAS_NO_THREADS)
 
diff --git a/libcxxabi/src/cxa_guard_impl.h b/libcxxabi/src/cxa_guard_impl.h
index e00d54b3a7318a..7b140d3c360454 100644
--- a/libcxxabi/src/cxa_guard_impl.h
+++ b/libcxxabi/src/cxa_guard_impl.h
@@ -55,7 +55,7 @@
 #  endif
 #endif
 
-#include <__threading_support>
+#include <__thread/support.h>
 #include <cstdint>
 #include <cstring>
 #include <limits.h>
diff --git a/libcxxabi/src/cxa_thread_atexit.cpp b/libcxxabi/src/cxa_thread_atexit.cpp
index 665f9e55694abf..c6bd0aa323f2e1 100644
--- a/libcxxabi/src/cxa_thread_atexit.cpp
+++ b/libcxxabi/src/cxa_thread_atexit.cpp
@@ -8,7 +8,7 @@
 
 #include "abort_message.h"
 #include "cxxabi.h"
-#include <__threading_support>
+#include <__thread/support.h>
 #ifndef _LIBCXXABI_HAS_NO_THREADS
 #if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB)
 #pragma comment(lib, "pthread")
diff --git a/libcxxabi/src/fallback_malloc.cpp b/libcxxabi/src/fallback_malloc.cpp
index fa802b2d81a745..76bd2e9bcd9f74 100644
--- a/libcxxabi/src/fallback_malloc.cpp
+++ b/libcxxabi/src/fallback_malloc.cpp
@@ -9,7 +9,7 @@
 #include "fallback_malloc.h"
 #include "abort_message.h"
 
-#include <__threading_support>
+#include <__thread/support.h>
 #ifndef _LIBCXXABI_HAS_NO_THREADS
 #if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB)
 #pragma comment(lib, "pthread")
diff --git a/libcxxabi/test/test_fallback_malloc.pass.cpp b/libcxxabi/test/test_fallback_malloc.pass.cpp
index 265a7a309e0a98..c8a6a0797510d7 100644
--- a/libcxxabi/test/test_fallback_malloc.pass.cpp
+++ b/libcxxabi/test/test_fallback_malloc.pass.cpp
@@ -11,7 +11,7 @@
 #include <cassert>
 #include <inttypes.h>
 
-#include <__threading_support>
+#include <__thread/support.h>
 
 // UNSUPPORTED: c++03
 // UNSUPPORTED: modules-build && no-threads

>From 591510e74e048513dae3429b1754ba9801de9594 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Mon, 29 Jan 2024 14:22:48 -0500
Subject: [PATCH 2/4] Add missing include

---
 libcxx/include/__condition_variable/condition_variable.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libcxx/include/__condition_variable/condition_variable.h b/libcxx/include/__condition_variable/condition_variable.h
index 2b1a817e2dfee6..de35aaca1070eb 100644
--- a/libcxx/include/__condition_variable/condition_variable.h
+++ b/libcxx/include/__condition_variable/condition_variable.h
@@ -9,6 +9,7 @@
 #ifndef _LIBCPP___CONDITION_VARIABLE_CONDITION_VARIABLE_H
 #define _LIBCPP___CONDITION_VARIABLE_CONDITION_VARIABLE_H
 
+#include <__chrono/duration.h>
 #include <__chrono/steady_clock.h>
 #include <__chrono/system_clock.h>
 #include <__chrono/time_point.h>

>From eff1c10eaad2f49db0df225c664a29bbb99292cb Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Mon, 29 Jan 2024 14:26:57 -0500
Subject: [PATCH 3/4] Add missing thread safety analysis disablement on pthread
 condvar functions

---
 libcxx/include/__thread/support.h         | 4 ++--
 libcxx/include/__thread/support/pthread.h | 5 +++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/libcxx/include/__thread/support.h b/libcxx/include/__thread/support.h
index b05ee892c5f0f6..619ce389600db2 100644
--- a/libcxx/include/__thread/support.h
+++ b/libcxx/include/__thread/support.h
@@ -52,8 +52,8 @@ using __libcpp_condvar_t = ...;
 
 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*);
+_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*);
 
 //
diff --git a/libcxx/include/__thread/support/pthread.h b/libcxx/include/__thread/support/pthread.h
index c129234433ac57..6ea2a38f6b6b3c 100644
--- a/libcxx/include/__thread/support/pthread.h
+++ b/libcxx/include/__thread/support/pthread.h
@@ -116,11 +116,12 @@ inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_broadcast(__libcpp_condvar_t*
   return pthread_cond_broadcast(__cv);
 }
 
-inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) {
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
+__libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) {
   return pthread_cond_wait(__cv, __m);
 }
 
-inline _LIBCPP_HIDE_FROM_ABI int
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
 __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, __libcpp_timespec_t* __ts) {
   return pthread_cond_timedwait(__cv, __m, __ts);
 }

>From 31ff51cc897c126b085127b9486e096b9eb8f96b Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Mon, 29 Jan 2024 14:31:26 -0500
Subject: [PATCH 4/4] Fix formatting

---
 libcxx/include/__thread/support.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/__thread/support.h b/libcxx/include/__thread/support.h
index 619ce389600db2..33f343a876dac5 100644
--- a/libcxx/include/__thread/support.h
+++ b/libcxx/include/__thread/support.h
@@ -53,7 +53,8 @@ using __libcpp_condvar_t = ...;
 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*);
+_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*);
 
 //



More information about the libcxx-commits mailing list