rmaprath created this revision.
rmaprath added reviewers: mclow.lists, EricWF, bcraig.
rmaprath added a subscriber: cfe-commits.
This is the replacement for D20328.

Rather than using opaque pointer types to delegate the internal representations 
of mutex / condvar / thread types, in this patch we expect the `libc++` vendor 
to explicitly define the implementation types upfront (at library compile 
time). The API is still left open for platform vendors to implement, it's only 
the types that need to be agreed upon.

http://reviews.llvm.org/D21968

Files:
  CMakeLists.txt
  include/__config
  include/__config_site.in
  include/__external_threading
  include/__threading_support
  lib/CMakeLists.txt
  test/CMakeLists.txt
  test/libcxx/test/config.py
  
test/libcxx/thread/thread.condition/thread.condition.condvar/native_handle.pass.cpp
  
test/libcxx/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/native_handle.pass.cpp
  
test/libcxx/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.recursive/native_handle.pass.cpp
  
test/libcxx/thread/thread.threads/thread.thread.class/thread.thread.member/native_handle.pass.cpp
  test/libcxx/thread/thread.threads/thread.thread.class/types.pass.cpp
  test/lit.site.cfg.in
  test/support/external_threads.cpp

Index: test/support/external_threads.cpp
===================================================================
--- /dev/null
+++ test/support/external_threads.cpp
@@ -0,0 +1,172 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SUPPORT_EXTERNAL_THREADS
+#define SUPPORT_EXTERNAL_THREADS
+
+#include <__threading_support>
+#include <pthread.h>
+#include <stdlib.h>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+//-- Mutex --//
+
+int __libcpp_recursive_mutex_init(__libcpp_mutex_t* __m)
+{
+    // Initialize the allocated pthread_mutex_t object as a recursive mutex
+    pthread_mutexattr_t attr;
+    int __ec = pthread_mutexattr_init(&attr);
+    if (__ec)
+      goto fail;
+
+    __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+    if (__ec)
+    {
+        pthread_mutexattr_destroy(&attr);
+        goto fail;
+    }
+
+    __ec = pthread_mutex_init(__m, &attr);
+    if (__ec)
+    {
+        pthread_mutexattr_destroy(&attr);
+        goto fail;
+    }
+
+    __ec = pthread_mutexattr_destroy(&attr);
+    if (__ec)
+    {
+        pthread_mutex_destroy(__m);
+        goto fail;
+    }
+
+    return 0;
+
+fail:
+    return __ec;
+}
+
+int __libcpp_mutex_lock(__libcpp_mutex_t* __m)
+{
+    return pthread_mutex_lock(__m);
+}
+
+int __libcpp_mutex_trylock(__libcpp_mutex_t* __m)
+{
+    return pthread_mutex_trylock(__m);
+}
+
+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, timespec* __ts)
+{
+    return pthread_cond_timedwait(__cv, __m, __ts);
+}
+
+int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv)
+{
+    return pthread_cond_destroy(__cv);
+}
+
+//-- Thread --//
+
+bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) {
+    return pthread_equal(t1, t2) != 0;
+}
+
+bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) {
+    return t1 < t2;
+}
+
+int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg)
+{
+    return pthread_create(__t, 0, __func, __arg);
+}
+
+__libcpp_thread_id __libcpp_thread_get_current_id()
+{
+    return static_cast<__libcpp_thread_id>(pthread_self());
+}
+
+__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t)
+{
+    return *__t;
+}
+
+int __libcpp_thread_join(__libcpp_thread_t* __t)
+{
+    // Must return non-zero if the internal state has already been invalidated
+    // This can happen for example, if std::thread::join() has been called
+    // before.
+    if (*__t == 0)
+        return -1;
+
+    return pthread_join(*__t, 0);
+}
+
+int __libcpp_thread_detach(__libcpp_thread_t* __t)
+{
+    // Must return non-zero if the internal state has already been invalidated
+    // This can happen for example, if std::thread::detach() has been called
+    // before.
+    if (*__t == 0)
+        return -1;
+
+    return pthread_detach(*__t);
+}
+
+void __libcpp_thread_yield()
+{
+    sched_yield();
+}
+
+//-- TLS --//
+
+int __libcpp_tl_create(__libcpp_tl_key* __key, void (*__at_exit)(void*))
+{
+    return pthread_key_create(__key, __at_exit);
+}
+
+void* __libcpp_tl_get(__libcpp_tl_key __key)
+{
+    return pthread_getspecific(__key);
+}
+
+void __libcpp_tl_set(__libcpp_tl_key __key, void* __p)
+{
+    pthread_setspecific(__key, __p);
+}
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // SUPPORT_EXTERNAL_THREADS
Index: test/lit.site.cfg.in
===================================================================
--- test/lit.site.cfg.in
+++ test/lit.site.cfg.in
@@ -24,6 +24,7 @@
 config.llvm_unwinder            = "@LIBCXXABI_USE_LLVM_UNWINDER@"
 config.use_libatomic            = "@LIBCXX_HAS_ATOMIC_LIB@"
 config.libcxxabi_shared         = "@LIBCXXABI_ENABLE_SHARED@"
+config.libcxx_external_thread_api  = "@LIBCXX_HAS_EXTERNAL_THREAD_API@"
 
 # Let the main config do the real work.
 lit_config.load_config(config, "@LIBCXX_SOURCE_DIR@/test/lit.cfg")
Index: test/libcxx/thread/thread.threads/thread.thread.class/types.pass.cpp
===================================================================
--- test/libcxx/thread/thread.threads/thread.thread.class/types.pass.cpp
+++ test/libcxx/thread/thread.threads/thread.thread.class/types.pass.cpp
@@ -7,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// UNSUPPORTED: libcpp-has-no-threads
+// UNSUPPORTED: libcpp-has-no-threads, libcpp-has-thread-api-external
 
 // <thread>
 
Index: test/libcxx/thread/thread.threads/thread.thread.class/thread.thread.member/native_handle.pass.cpp
===================================================================
--- test/libcxx/thread/thread.threads/thread.thread.class/thread.thread.member/native_handle.pass.cpp
+++ test/libcxx/thread/thread.threads/thread.thread.class/thread.thread.member/native_handle.pass.cpp
@@ -7,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// UNSUPPORTED: libcpp-has-no-threads
+// UNSUPPORTED: libcpp-has-no-threads, libcpp-has-thread-api-external
 
 // <thread>
 
Index: test/libcxx/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.recursive/native_handle.pass.cpp
===================================================================
--- test/libcxx/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.recursive/native_handle.pass.cpp
+++ test/libcxx/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.recursive/native_handle.pass.cpp
@@ -7,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// UNSUPPORTED: libcpp-has-no-threads
+// UNSUPPORTED: libcpp-has-no-threads, libcpp-has-thread-api-external
 
 // <mutex>
 
Index: test/libcxx/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/native_handle.pass.cpp
===================================================================
--- test/libcxx/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/native_handle.pass.cpp
+++ test/libcxx/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/native_handle.pass.cpp
@@ -7,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// UNSUPPORTED: libcpp-has-no-threads
+// UNSUPPORTED: libcpp-has-no-threads, libcpp-has-thread-api-external
 
 // <mutex>
 
Index: test/libcxx/thread/thread.condition/thread.condition.condvar/native_handle.pass.cpp
===================================================================
--- test/libcxx/thread/thread.condition/thread.condition.condvar/native_handle.pass.cpp
+++ test/libcxx/thread/thread.condition/thread.condition.condvar/native_handle.pass.cpp
@@ -7,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// UNSUPPORTED: libcpp-has-no-threads
+// UNSUPPORTED: libcpp-has-no-threads, libcpp-has-thread-api-external
 
 // <condition_variable>
 
Index: test/libcxx/test/config.py
===================================================================
--- test/libcxx/test/config.py
+++ test/libcxx/test/config.py
@@ -505,6 +505,10 @@
                 self.cxx.link_flags += [abs_path]
             else:
                 self.cxx.link_flags += ['-lc++']
+        # This needs to come after -lc++ as we want its unresolved thread-api symbols
+        # to be picked up from this one.
+        if self.get_lit_bool('libcxx_external_thread_api', default=False):
+            self.cxx.link_flags += ['-lc++external_threading_support']
 
     def configure_link_flags_abi_library(self):
         cxx_abi = self.get_lit_conf('cxx_abi', 'libcxxabi')
Index: test/CMakeLists.txt
===================================================================
--- test/CMakeLists.txt
+++ test/CMakeLists.txt
@@ -19,6 +19,7 @@
 pythonize_bool(LIBCXXABI_ENABLE_SHARED)
 pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER)
 pythonize_bool(LIBCXX_HAS_ATOMIC_LIB)
+pythonize_bool(LIBCXX_HAS_EXTERNAL_THREAD_API)
 
 # The tests shouldn't link to any ABI library when it has been linked into
 # libc++ statically or via a linker script.
@@ -49,10 +50,14 @@
   set(experimental_dep cxx_experimental)
 endif()
 
+if (LIBCXX_HAS_EXTERNAL_THREAD_API)
+  set(external_threading_support_dep cxx_external_threading_support)
+endif()
+
 add_lit_testsuite(check-libcxx
   "Running libcxx tests"
   ${CMAKE_CURRENT_BINARY_DIR}
-  DEPENDS cxx ${experimental_dep})
+  DEPENDS cxx ${experimental_dep} ${external_threading_support_dep})
 
 if (LIBCXX_GENERATE_COVERAGE)
   include(CodeCoverage)
Index: lib/CMakeLists.txt
===================================================================
--- lib/CMakeLists.txt
+++ lib/CMakeLists.txt
@@ -172,6 +172,18 @@
   )
 endif()
 
+if (LIBCXX_HAS_EXTERNAL_THREAD_API)
+  file(GLOB LIBCXX_EXTERNAL_THREADING_SUPPORT_SOURCES ../test/support/external_threads.cpp)
+  add_library(cxx_external_threading_support STATIC ${LIBCXX_EXTERNAL_THREADING_SUPPORT_SOURCES})
+  target_link_libraries(cxx_external_threading_support cxx)
+
+  set_target_properties(cxx_external_threading_support
+    PROPERTIES
+      COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}"
+      OUTPUT_NAME   "c++external_threading_support"
+  )
+endif()
+
 # Generate a linker script inplace of a libc++.so symlink. Rerun this command
 # after cxx builds.
 if (LIBCXX_ENABLE_ABI_LINKER_SCRIPT)
Index: include/__threading_support
===================================================================
--- include/__threading_support
+++ include/__threading_support
@@ -24,10 +24,10 @@
 #include <sched.h>
 #endif
 
-_LIBCPP_BEGIN_NAMESPACE_STD
-
 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
 
+_LIBCPP_BEGIN_NAMESPACE_STD
+
 // Mutex
 #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
 typedef pthread_mutex_t __libcpp_mutex_t;
@@ -194,12 +194,17 @@
     pthread_setspecific(__key, __p);
 }
 
-#else // !_LIBCPP_HAS_THREAD_API_PTHREAD
+_LIBCPP_END_NAMESPACE_STD
+
+#elif defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
+#  if !defined(__has_include) || __has_include(<__external_threading>)
+     /* For compiling libc++ against an external thread API. */
+#    include<__external_threading>
+#  endif
+#else
   #error "No thread API selected."
 #endif
 
-_LIBCPP_END_NAMESPACE_STD
-
 #endif // _LIBCPP_HAS_NO_THREADS
 
 #endif // _LIBCPP_THREADING_SUPPORT
Index: include/__external_threading
===================================================================
--- /dev/null
+++ include/__external_threading
@@ -0,0 +1,91 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_EXTERNAL_THREADING
+#define _LIBCPP_EXTERNAL_THREADING
+
+#include <__config>
+
+#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
+#pragma GCC system_header
+#endif
+
+#if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
+#  error "Only valid when _LIBCPP_HAS_THREAD_API_EXTERNAL is defined"
+#endif
+
+#include <time.h>
+
+#if !defined(_LIBCPP_MUTEX_T) || \
+    !defined(_LIBCPP_MUTEX_INITIALIZER) || \
+    !defined(_LIBCPP_CONDVAR_T) || \
+    !defined(_LIBCPP_CONDVAR_INITIALIZER) || \
+    !defined(_LIBCPP_THREAD_T) || \
+    !defined(_LIBCPP_TLSKEY_T)
+  // We could emit a warning here to indicate that we are defaulting to
+  // pthreads because these thread-support macros are not provided, but this
+  // causes many test failures (due to the unexpected warning). Instead,
+  // we expect people using LIBCXX_HAS_EXTERNAL_THREAD_API to know what
+  // they are doing and provide the right set of macros (and an appropriate
+  // thread implementation - substitute for test/support/external_threads.cpp).
+  #include <pthread.h>
+  #define _LIBCPP_MUTEX_T pthread_mutex_t
+  #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+  #define _LIBCPP_CONDVAR_T pthread_cond_t
+  #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
+  #define _LIBCPP_THREAD_T pthread_t
+  #define _LIBCPP_TLSKEY_T pthread_key_t
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// Mutex
+typedef _LIBCPP_MUTEX_T __libcpp_mutex_t;
+
+int __libcpp_recursive_mutex_init(__libcpp_mutex_t* __m);
+int __libcpp_mutex_lock(__libcpp_mutex_t* __m);
+int __libcpp_mutex_trylock(__libcpp_mutex_t* __m);
+int __libcpp_mutex_unlock(__libcpp_mutex_t* __m);
+int __libcpp_mutex_destroy(__libcpp_mutex_t* __m);
+
+// Condition variable
+typedef _LIBCPP_CONDVAR_T __libcpp_condvar_t;
+
+int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
+int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
+int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
+int __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, timespec* __ts);
+int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
+
+// Thread id
+typedef unsigned long __libcpp_thread_id;
+bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
+bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
+
+// Thread
+typedef _LIBCPP_THREAD_T __libcpp_thread_t;
+int __libcpp_thread_create(__libcpp_thread_t* __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* __t);
+int __libcpp_thread_join(__libcpp_thread_t* __t);
+int __libcpp_thread_detach(__libcpp_thread_t* __t);
+void __libcpp_thread_yield();
+void __libcpp_thread_finalize(__libcpp_thread_t* __t);
+
+// Thread local storage
+typedef _LIBCPP_TLSKEY_T __libcpp_tl_key;
+int __libcpp_tl_create(__libcpp_tl_key* __key, void (*__at_exit)(void*));
+void* __libcpp_tl_get(__libcpp_tl_key __key);
+void __libcpp_tl_set(__libcpp_tl_key __key, void* __p);
+void __libcpp_tl_finalize(__libcpp_tl_key __key);
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_EXTERNAL_THREADING
Index: include/__config_site.in
===================================================================
--- include/__config_site.in
+++ include/__config_site.in
@@ -20,5 +20,6 @@
 #cmakedefine _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
 #cmakedefine _LIBCPP_HAS_MUSL_LIBC
 #cmakedefine _LIBCPP_HAS_THREAD_API_PTHREAD
+#cmakedefine _LIBCPP_HAS_THREAD_API_EXTERNAL
 
 #endif // _LIBCPP_CONFIG_SITE
Index: include/__config
===================================================================
--- include/__config
+++ include/__config
@@ -814,7 +814,9 @@
 #endif
 
 // Thread API
-#if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
+#if !defined(_LIBCPP_HAS_NO_THREADS) && \
+    !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && \
+    !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
 # if defined(__FreeBSD__) || \
     defined(__NetBSD__) || \
     defined(__linux__) || \
@@ -832,6 +834,11 @@
          _LIBCPP_HAS_NO_THREADS is not defined.
 #endif
 
+#if defined(_LIBCPP_HAS_NO_THREADS) && defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 
+#  error _LIBCPP_HAS_EXTERNAL_THREAD_API may not be defined when \
+         _LIBCPP_HAS_NO_THREADS is defined.
+#endif
+
 #if defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK) && !defined(_LIBCPP_HAS_NO_THREADS)
 #  error _LIBCPP_HAS_NO_MONOTONIC_CLOCK may only be defined when \
          _LIBCPP_HAS_NO_THREADS is defined.
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt
+++ CMakeLists.txt
@@ -128,7 +128,10 @@
   "Build libc++ with support for a monotonic clock.
    This option may only be set to OFF when LIBCXX_ENABLE_THREADS=OFF." ON)
 option(LIBCXX_HAS_MUSL_LIBC "Build libc++ with support for the Musl C library" OFF)
-option(LIBCXX_HAS_PTHREAD_API "Ignore auto-detection and force use of pthread API" OFF)
+option(LIBCXX_HAS_PTHREAD_THREAD_API "Ignore auto-detection and force use of pthread API" OFF)
+option(LIBCXX_HAS_EXTERNAL_THREAD_API
+  "Build libc++ with an externalized threading API.
+   This option may only be set to ON when LIBCXX_ENABLE_THREADS=ON." OFF)
 
 # Misc options ----------------------------------------------------------------
 # FIXME: Turn -pedantic back ON. It is currently off because it warns
@@ -173,15 +176,20 @@
     "LIBCXX_ENABLE_FILESYSTEM cannot be turned on when LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY=OFF")
 endif()
 
-# Ensure LIBCXX_ENABLE_MONOTONIC_CLOCK is set to ON only when
+# Ensure LIBCXX_ENABLE_MONOTONIC_CLOCK is always set to ON when
 # LIBCXX_ENABLE_THREADS is on.
 if(LIBCXX_ENABLE_THREADS AND NOT LIBCXX_ENABLE_MONOTONIC_CLOCK)
   message(FATAL_ERROR "LIBCXX_ENABLE_MONOTONIC_CLOCK can only be set to OFF"
                       " when LIBCXX_ENABLE_THREADS is also set to OFF.")
 endif()
 
-if(LIBCXX_HAS_PTHREAD_API AND NOT LIBCXX_ENABLE_THREADS)
-  message(FATAL_ERROR "LIBCXX_HAS_PTHREAD_API can only be set to ON"
+if(LIBCXX_HAS_PTHREAD_THREAD_API AND NOT LIBCXX_ENABLE_THREADS)
+  message(FATAL_ERROR "LIBCXX_HAS_PTHREAD_THREAD_API can only be set to ON"
+                      " when LIBCXX_ENABLE_THREADS is also set to ON.")
+endif()
+
+if(LIBCXX_HAS_EXTERNAL_THREAD_API AND NOT LIBCXX_ENABLE_THREADS)
+  message(FATAL_ERROR "LIBCXX_HAS_EXTERNAL_THREAD_API can only be set to ON"
                       " when LIBCXX_ENABLE_THREADS is also set to ON.")
 endif()
 
@@ -402,7 +410,8 @@
 config_define_if_not(LIBCXX_ENABLE_MONOTONIC_CLOCK _LIBCPP_HAS_NO_MONOTONIC_CLOCK)
 config_define_if_not(LIBCXX_ENABLE_THREAD_UNSAFE_C_FUNCTIONS _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS)
 
-config_define_if(LIBCXX_HAS_PTHREAD_API _LIBCPP_HAS_THREAD_API_PTHREAD)
+config_define_if(LIBCXX_HAS_PTHREAD_THREAD_API _LIBCPP_HAS_THREAD_API_PTHREAD)
+config_define_if(LIBCXX_HAS_EXTERNAL_THREAD_API _LIBCPP_HAS_THREAD_API_EXTERNAL)
 config_define_if(LIBCXX_HAS_MUSL_LIBC _LIBCPP_HAS_MUSL_LIBC)
 
 if (LIBCXX_NEEDS_SITE_CONFIG)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to