summaryrefslogtreecommitdiff
path: root/libcxx/include/__threading_support
diff options
context:
space:
mode:
Diffstat (limited to 'libcxx/include/__threading_support')
-rw-r--r--libcxx/include/__threading_support241
1 files changed, 221 insertions, 20 deletions
diff --git a/libcxx/include/__threading_support b/libcxx/include/__threading_support
index 0d1f1e681f50d..026429f6a8ec0 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) || \
@@ -79,6 +81,35 @@ typedef pthread_t __libcpp_thread_t;
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;
@@ -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;
@@ -453,7 +654,7 @@ public:
_LIBCPP_INLINE_VISIBILITY
void __reset() { __id_ = 0; }
-
+
template<class _CharT, class _Traits>
friend
_LIBCPP_INLINE_VISIBILITY