rmaprath created this revision.
rmaprath added reviewers: EricWF, mclow.lists, theraven, jroelofs.
rmaprath added a subscriber: cfe-commits.
Herald added a subscriber: aemerson.

This patch builds on D19412.

The motivation here is to allow toolchain vendors to build a version of 
`libcxx` with all the underlying os threading mechanics differed to runtime - 
sacrificing some performance for flexibility.

This API (`_LIBCPP_THREAD_API_EXTERNAL`) currently only works when `libcxx` is 
build as a static library. This is because the shared library builds pass `-z 
defs` linker flag, which disallows undefined symbols in the library. I'm not 
familiar with shared library limitations on specific platforms, but in theory, 
this could work on shared library builds as well.

Currently there are quite a lot of test failures because the testing 
infrastructure need to be updated to provide an implementation of this 
threading API (pthreads will do). Our plan is to hide this whole extension 
under some cmake variable at some point.

Before putting more effort into this, I thought of checking if the community if 
open to this kind of an API. Of course, we (ARM) will be committed to 
maintaining this API in the long run.

http://reviews.llvm.org/D19415

Files:
  include/__mutex_base
  include/__os_support
  include/thread
  src/algorithm.cpp
  src/condition_variable.cpp
  src/memory.cpp
  src/mutex.cpp
  src/thread.cpp

Index: src/thread.cpp
===================================================================
--- src/thread.cpp
+++ src/thread.cpp
@@ -50,6 +50,8 @@
 {
 #if defined(_LIBCPP_THREAD_API_PTHREAD)
     int ec = pthread_join(__t_, 0);
+#elif defined(_LIBCPP_THREAD_API_EXTERNAL)
+    int ec = __os_thread_join(__t_);
 #else
     #error "Not implemented for the selected thread API."
 #endif
@@ -70,6 +72,8 @@
     {
 #if defined(_LIBCPP_THREAD_API_PTHREAD)
         ec = pthread_detach(__t_);
+#elif defined(_LIBCPP_THREAD_API_EXTERNAL)
+        ec = __os_thread_detach(__t_);
 #else
         #error "Not implemented for the selected thread API."
 #endif
Index: src/mutex.cpp
===================================================================
--- src/mutex.cpp
+++ src/mutex.cpp
@@ -27,6 +27,8 @@
 {
 #if defined(_LIBCPP_THREAD_API_PTHREAD)
     pthread_mutex_destroy(&__m_);
+#elif defined(_LIBCPP_THREAD_API_EXTERNAL)
+    __os_mutex_destroy(__m_);
 #else
     #error "Not implemented for the selected thread API."
 #endif
@@ -37,6 +39,8 @@
 {
 #if defined(_LIBCPP_THREAD_API_PTHREAD)
     int ec = pthread_mutex_lock(&__m_);
+#elif defined(_LIBCPP_THREAD_API_EXTERNAL)
+    int ec = __os_mutex_lock(__m_);
 #else
     #error "Not implemented for the selected thread API."
 #endif
@@ -49,6 +53,8 @@
 {
 #if defined(_LIBCPP_THREAD_API_PTHREAD)
     return pthread_mutex_trylock(&__m_) == 0;
+#elif defined(_LIBCPP_THREAD_API_EXTERNAL)
+    return __os_mutex_trylock(__m_) == 0;
 #else
     #error "Not implemented for the selected thread API."
 #endif
@@ -59,6 +65,8 @@
 {
 #if defined(_LIBCPP_THREAD_API_PTHREAD)
     int ec = pthread_mutex_unlock(&__m_);
+#elif defined(_LIBCPP_THREAD_API_EXTERNAL)
+    int ec = __os_mutex_unlock(__m_);
 #else
     #error "Not implemented for the selected thread API."
 #endif
@@ -93,18 +101,24 @@
         pthread_mutex_destroy(&__m_);
         goto fail;
     }
-    return;
-fail:
-    __throw_system_error(ec, "recursive_mutex constructor failed");
+#elif defined(_LIBCPP_THREAD_API_EXTERNAL)
+    int ec = __os_mutex_init(&__m_, true);
+    if (ec)
+      goto fail;
 #else
     #error "Not implemented for the selected thread API."
 #endif
+    return;
+fail:
+    __throw_system_error(ec, "recursive_mutex constructor failed");
 }
 
 recursive_mutex::~recursive_mutex()
 {
 #if defined(_LIBCPP_THREAD_API_PTHREAD)
     int e = pthread_mutex_destroy(&__m_);
+#elif defined(_LIBCPP_THREAD_API_EXTERNAL)
+    int e = __os_mutex_destroy(__m_);
 #else
     #error "Not implemented for the selected thread API."
 #endif
@@ -117,6 +131,8 @@
 {
 #if defined(_LIBCPP_THREAD_API_PTHREAD)
     int ec = pthread_mutex_lock(&__m_);
+#elif defined(_LIBCPP_THREAD_API_EXTERNAL)
+    int ec = __os_mutex_lock(__m_);
 #else
     #error "Not implemented for the selected thread API."
 #endif
@@ -129,6 +145,8 @@
 {
 #if defined(_LIBCPP_THREAD_API_PTHREAD)
     int e = pthread_mutex_unlock(&__m_);
+#elif defined(_LIBCPP_THREAD_API_EXTERNAL)
+    int e = __os_mutex_unlock(__m_);
 #else
     #error "Not implemented for the selected thread API."
 #endif
@@ -141,6 +159,8 @@
 {
 #if defined(_LIBCPP_THREAD_API_PTHREAD)
     return pthread_mutex_trylock(&__m_) == 0;
+#elif defined(_LIBCPP_THREAD_API_EXTERNAL)
+    return __os_mutex_trylock(__m_) == 0;
 #else
     #error "Not implemented for the selected thread API."
 #endif
@@ -311,7 +331,9 @@
     }
     else
         pthread_mutex_unlock(&mut);
-#else // !_LIBCPP_THREAD_API_PTHREAD
+#elif defined(_LIBCPP_THREAD_API_EXTERNAL)
+     __os_call_once(flag, arg, func);
+#else
     #error "Not implemented for the selected thread API."
 #endif // _LIBCPP_THREAD_API_PTHREAD
 #endif // _LIBCPP_HAS_NO_THREADS
Index: src/memory.cpp
===================================================================
--- src/memory.cpp
+++ src/memory.cpp
@@ -127,6 +127,8 @@
 #if defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS)
 
 static const std::size_t __sp_mut_count = 16;
+
+#if !defined(_LIBCPP_THREAD_API_EXTERNAL)
 static __libcpp_os_support::__os_mutex mut_back_imp[__sp_mut_count] =
 {
     __OS_MUTEX_INITIALIZER, __OS_MUTEX_INITIALIZER, __OS_MUTEX_INITIALIZER, __OS_MUTEX_INITIALIZER,
@@ -136,6 +138,9 @@
 };
 
 static mutex* mut_back = reinterpret_cast<std::mutex*>(mut_back_imp);
+#else
+static mutex mut_back[__sp_mut_count];
+#endif
 
 _LIBCPP_CONSTEXPR __sp_mut::__sp_mut(void* p) _NOEXCEPT
    : __lx(p)
Index: src/condition_variable.cpp
===================================================================
--- src/condition_variable.cpp
+++ src/condition_variable.cpp
@@ -24,6 +24,8 @@
 {
 #if defined(_LIBCPP_THREAD_API_PTHREAD)
     pthread_cond_destroy(&__cv_);
+#elif defined(_LIBCPP_THREAD_API_EXTERNAL)
+    __os_condvar_destroy(__cv_);
 #else
     #error "Not implemented for the selected thread API."
 #endif
@@ -34,6 +36,8 @@
 {
 #if defined(_LIBCPP_THREAD_API_PTHREAD)
     pthread_cond_signal(&__cv_);
+#elif defined(_LIBCPP_THREAD_API_EXTERNAL)
+    __os_condvar_signal(__cv_);
 #else
     #error "Not implemented for the selected thread API."
 #endif
@@ -44,6 +48,8 @@
 {
 #if defined(_LIBCPP_THREAD_API_PTHREAD)
     pthread_cond_broadcast(&__cv_);
+#elif defined(_LIBCPP_THREAD_API_EXTERNAL)
+    __os_condvar_broadcast(__cv_);
 #else
     #error "Not implemented for the selected thread API."
 #endif
@@ -57,6 +63,8 @@
                                   "condition_variable::wait: mutex not locked");
 #if defined(_LIBCPP_THREAD_API_PTHREAD)
     int ec = pthread_cond_wait(&__cv_, lk.mutex()->native_handle());
+#elif defined(_LIBCPP_THREAD_API_EXTERNAL)
+    int ec = __os_condvar_wait(__cv_, lk.mutex()->native_handle());
 #else
     #error "Not implemented for the selected thread API."
 #endif
@@ -91,6 +99,8 @@
     }
 #if defined(_LIBCPP_THREAD_API_PTHREAD)
     int ec = pthread_cond_timedwait(&__cv_, lk.mutex()->native_handle(), &ts);
+#elif defined(_LIBCPP_THREAD_API_EXTERNAL)
+    int ec = __os_condvar_timedwait(__cv_, lk.mutex()->native_handle(), &ts);
 #else
     #error "Not implemented for the selected thread API."
 #endif
Index: src/algorithm.cpp
===================================================================
--- src/algorithm.cpp
+++ src/algorithm.cpp
@@ -48,18 +48,24 @@
 template unsigned __sort5<__less<long double>&, long double*>(long double*, long double*, long double*, long double*, long double*, __less<long double>&);
 
 #ifndef _LIBCPP_HAS_NO_THREADS
+# if defined(_LIBCPP_THREAD_API_PTHREAD)
 static __libcpp_os_support::__os_mutex __rs_mut = __OS_MUTEX_INITIALIZER;
+# else
+static mutex __rs_mut;
+# endif
 #endif
 unsigned __rs_default::__c_ = 0;
 
 __rs_default::__rs_default()
 {
 #ifndef _LIBCPP_HAS_NO_THREADS
-#if defined(_LIBCPP_THREAD_API_PTHREAD)
+# if defined(_LIBCPP_THREAD_API_PTHREAD)
     pthread_mutex_lock(&__rs_mut);
-#else
+# elif defined(_LIBCPP_THREAD_API_EXTERNAL)
+    __rs_mut.lock();
+# else
    #error "Not implemented for the selected thread API."
-#endif
+# endif
 #endif
     __c_ = 1;
 }
@@ -73,11 +79,13 @@
 {
 #ifndef _LIBCPP_HAS_NO_THREADS
     if (--__c_ == 0)
-#if defined(_LIBCPP_THREAD_API_PTHREAD)
+# if defined(_LIBCPP_THREAD_API_PTHREAD)
         pthread_mutex_unlock(&__rs_mut);
-#else
+# elif defined(_LIBCPP_THREAD_API_EXTERNAL)
+        __rs_mut.unlock();
+# else
    #error "Not implemented for the selected thread API."
-#endif
+# endif
 #else
     --__c_;
 #endif
Index: include/thread
===================================================================
--- include/thread
+++ include/thread
@@ -303,7 +303,11 @@
     typedef __thread_type native_handle_type;
 
     _LIBCPP_INLINE_VISIBILITY
+#if defined(_LIBCPP_THREAD_API_EXTERNAL)
+    thread() _NOEXCEPT : __t_(NULL) {}
+#else
     thread() _NOEXCEPT : __t_(__libcpp_os_support::__os_thread_init) {}
+#endif
 #ifndef _LIBCPP_HAS_NO_VARIADICS
     template <class _Fp, class ..._Args,
               class = typename enable_if
Index: include/__os_support
===================================================================
--- include/__os_support
+++ include/__os_support
@@ -13,7 +13,81 @@
 
 #ifndef _LIBCPP_HAS_NO_THREADS
 
-#if defined(_LIBCPP_THREAD_API_PTHREAD)
+#if defined(_LIBCPP_THREAD_API_EXTERNAL)
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace __libcpp_os_support
+{
+// Mutexes
+struct __mutex_t;
+typedef struct __mutex_t* __os_mutex;
+
+int __os_mutex_init(__os_mutex*, bool recursive = false);
+
+int __os_mutex_destroy(__os_mutex);
+
+int __os_mutex_lock(__os_mutex);
+
+int __os_mutex_trylock(__os_mutex);
+
+int __os_mutex_unlock(__os_mutex);
+
+void __os_call_once(volatile unsigned long& flag, void* arg, void(*func)(void*));
+
+// Condition variables
+struct __condvar_t;
+typedef struct __condvar_t* __os_cond_var;
+
+int __os_condvar_init(__os_cond_var*);
+
+int __os_condvar_destroy(__os_cond_var);
+
+int __os_condvar_signal(__os_cond_var);
+
+int __os_condvar_broadcast(__os_cond_var);
+
+int __os_condvar_wait(__os_cond_var, __os_mutex*);
+
+int __os_condvar_timedwait(__os_cond_var, __os_mutex*, timespec*);
+
+// Thread id
+typedef unsigned long __os_thread_id;
+
+int __os_thread_id_compare(__os_thread_id, __os_thread_id);
+
+// Thread
+struct __thread_t;
+typedef struct __thread_t* __os_thread;
+
+template<class _Func, class _Arg>
+int __os_thread_create(__os_thread* __t, _Func&& __f, _Arg&& __arg);
+
+__os_thread_id __os_thread_get_current_id();
+
+__os_thread_id __os_thread_get_id(__os_thread);
+
+int __os_thread_join(__os_thread);
+
+int __os_thread_detach(__os_thread);
+
+void __os_thread_yield();
+
+// Thread local storage
+typedef unsigned long __os_tl_key;
+
+template<class _Func>
+int __os_tl_create(__os_tl_key* __key, _Func&& __at_exit);
+
+void* __os_tl_get(__os_tl_key);
+
+void __os_tl_set(__os_tl_key __key, void* __p);
+
+} // __libcpp_os_support
+
+_LIBCPP_END_NAMESPACE_STD
+
+#elif defined(_LIBCPP_THREAD_API_PTHREAD)
 
 #include <pthread.h>
 #include <sched.h>
Index: include/__mutex_base
===================================================================
--- include/__mutex_base
+++ include/__mutex_base
@@ -39,7 +39,9 @@
 
 public:
     _LIBCPP_INLINE_VISIBILITY
-#ifndef _LIBCPP_HAS_NO_CONSTEXPR
+#if defined(_LIBCPP_THREAD_API_EXTERNAL)
+    mutex() _NOEXCEPT {__libcpp_os_support::__os_mutex_init(&__m_);}
+#elif !defined(_LIBCPP_HAS_NO_CONSTEXPR)
     constexpr mutex() _NOEXCEPT : __m_(__OS_MUTEX_INITIALIZER) {}
 #else
     mutex() _NOEXCEPT {__m_ = (__mutex_type)__OS_MUTEX_INITIALIZER;}
@@ -279,7 +281,9 @@
     __cond_var_type  __cv_;
 public:
     _LIBCPP_INLINE_VISIBILITY
-#ifndef _LIBCPP_HAS_NO_CONSTEXPR
+#if defined(_LIBCPP_THREAD_API_EXTERNAL)
+    condition_variable() {__libcpp_os_support::__os_condvar_init(&__cv_);}
+#elif !defined(_LIBCPP_HAS_NO_CONSTEXPR)
     constexpr condition_variable() : __cv_(__OS_COND_INITIALIZER) {}
 #else
     condition_variable() {__cv_ = (__os_cond_var)__OS_COND_INITIALIZER;}
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to