[libcxx-commits] [libcxx] ab9aefe - [libcxx] Use C11 thread API on Fuchsia

Petr Hosek via libcxx-commits libcxx-commits at lists.llvm.org
Tue Jan 14 16:48:33 PST 2020


Author: Petr Hosek
Date: 2020-01-14T16:48:20-08:00
New Revision: ab9aefee9fa09957d1a3e76fcc47abda0d002255

URL: https://github.com/llvm/llvm-project/commit/ab9aefee9fa09957d1a3e76fcc47abda0d002255
DIFF: https://github.com/llvm/llvm-project/commit/ab9aefee9fa09957d1a3e76fcc47abda0d002255.diff

LOG: [libcxx] Use C11 thread API on Fuchsia

On Fuchsia, pthread API is emulated on top of C11 thread API. Using C11
thread API directly is more efficient.

While this implementation is only used by Fuchsia at the moment, it's
not Fuchsia specific, and could be used by other platforms that use C11
threads rather than pthreads in the future.

Differential Revision: https://reviews.llvm.org/D64378

Added: 
    

Modified: 
    libcxx/include/__config
    libcxx/include/__threading_support

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__config b/libcxx/include/__config
index 7394d443b729..ac4549802ef2 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -1111,7 +1111,6 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
     !defined(_LIBCPP_HAS_THREAD_API_WIN32) && \
     !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
 #  if defined(__FreeBSD__) || \
-      defined(__Fuchsia__) || \
       defined(__wasi__) || \
       defined(__NetBSD__) || \
       defined(__linux__) || \
@@ -1121,6 +1120,8 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
       defined(__sun__) || \
       (defined(__MINGW32__) && __has_include(<pthread.h>))
 #    define _LIBCPP_HAS_THREAD_API_PTHREAD
+#  elif defined(__Fuchsia__)
+#    define _LIBCPP_HAS_THREAD_API_C11
 #  elif defined(_LIBCPP_WIN32API)
 #    define _LIBCPP_HAS_THREAD_API_WIN32
 #  else
@@ -1172,6 +1173,7 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
 // TODO(EricWF): Enable this optimization on Bionic after speaking to their
 //               respective stakeholders.
 #if (defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && defined(__GLIBC__)) \
+  || (defined(_LIBCPP_HAS_THREAD_API_C11) && defined(__Fuchsia__)) \
   || defined(_LIBCPP_HAS_THREAD_API_WIN32)
 # define _LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION
 #endif
@@ -1184,7 +1186,8 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
 //
 // TODO(EricWF): This is potentially true for some pthread implementations
 // as well.
-#if defined(_LIBCPP_HAS_THREAD_API_WIN32)
+#if (defined(_LIBCPP_HAS_THREAD_API_C11) && defined(__Fuchsia__)) || \
+     defined(_LIBCPP_HAS_THREAD_API_WIN32)
 # define _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION
 #endif
 

diff  --git a/libcxx/include/__threading_support b/libcxx/include/__threading_support
index 50cec7e0c95a..026429f6a8ec 100644
--- a/libcxx/include/__threading_support
+++ b/libcxx/include/__threading_support
@@ -26,6 +26,8 @@
 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
 # include <pthread.h>
 # include <sched.h>
+#elif defined(_LIBCPP_HAS_THREAD_API_C11)
+# include <threads.h>
 #endif
 
 #if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
@@ -78,6 +80,35 @@ 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
@@ -212,8 +243,35 @@ int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
 #endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
 
 #if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
-     defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) && \
-    defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
+     defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL))
+
+namespace __thread_detail {
+
+inline __libcpp_timespec_t __convert_to_timespec(const chrono::nanoseconds& __ns)
+{
+  using namespace chrono;
+  seconds __s = duration_cast<seconds>(__ns);
+  __libcpp_timespec_t __ts;
+  typedef decltype(__ts.tv_sec) __ts_sec;
+  const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max();
+
+  if (__s.count() < __ts_sec_max)
+  {
+    __ts.tv_sec = static_cast<__ts_sec>(__s.count());
+    __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
+  }
+  else
+  {
+    __ts.tv_sec = __ts_sec_max;
+    __ts.tv_nsec = 999999999; // (10^9 - 1)
+  }
+
+  return __ts;
+}
+
+}
+
+#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
 
 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
 {
@@ -363,23 +421,7 @@ void __libcpp_thread_yield()
 
 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
 {
-   using namespace chrono;
-   seconds __s = duration_cast<seconds>(__ns);
-   __libcpp_timespec_t __ts;
-   typedef decltype(__ts.tv_sec) ts_sec;
-   _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits<ts_sec>::max();
-
-   if (__s.count() < __ts_sec_max)
-   {
-     __ts.tv_sec = static_cast<ts_sec>(__s.count());
-     __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
-   }
-   else
-   {
-     __ts.tv_sec = __ts_sec_max;
-     __ts.tv_nsec = 999999999; // (10^9 - 1)
-   }
-
+   __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
    while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
 }
 
@@ -399,6 +441,165 @@ 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_recursive) == thrd_success ? 0 : EINVAL;
+}
+
+int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
+{
+  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
+}
+
+bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
+{
+  return mtx_trylock(__m) == thrd_success;
+}
+
+int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
+{
+  return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
+}
+
+int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
+{
+  mtx_destroy(__m);
+  return 0;
+}
+
+int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
+{
+  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
+}
+
+bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
+{
+  return mtx_trylock(__m) == thrd_success;
+}
+
+int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
+{
+  return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
+}
+
+int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
+{
+  mtx_destroy(__m);
+  return 0;
+}
+
+// Condition Variable
+int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
+{
+  return cnd_signal(__cv) == thrd_success ? 0 : EINVAL;
+}
+
+int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
+{
+  return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL;
+}
+
+int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
+{
+  return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL;
+}
+
+int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
+                               timespec *__ts)
+{
+  int __ec = cnd_timedwait(__cv, __m, __ts);
+  return __ec == thrd_timedout ? ETIMEDOUT : __ec;
+}
+
+int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
+{
+  cnd_destroy(__cv);
+  return 0;
+}
+
+// Execute once
+int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
+                          void (*init_routine)(void)) {
+  ::call_once(flag, init_routine);
+  return 0;
+}
+
+// Thread id
+// Returns non-zero if the thread ids are equal, otherwise 0
+bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
+{
+  return thrd_equal(t1, t2) != 0;
+}
+
+// Returns non-zero if t1 < t2, otherwise 0
+bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
+{
+  return t1 < t2;
+}
+
+// Thread
+bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
+  return *__t == 0;
+}
+
+int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
+                           void *__arg)
+{
+  int __ec = thrd_create(__t, reinterpret_cast<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 = __thread_detail::__convert_to_timespec(__ns);
+  thrd_sleep(&__ts, nullptr);
+}
+
+// Thread local storage
+int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
+{
+  return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL;
+}
+
+void *__libcpp_tls_get(__libcpp_tls_key __key)
+{
+  return tss_get(__key);
+}
+
+int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
+{
+  return tss_set(__key, __p) == thrd_success ? 0 : EINVAL;
+}
+
+#endif
+
 #endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
 
 class _LIBCPP_TYPE_VIS thread;


        


More information about the libcxx-commits mailing list