Index: libcxx/include/__config =================================================================== --- libcxx/include/__config +++ libcxx/include/__config @@ -1065,7 +1065,6 @@ !defined(_LIBCPP_HAS_THREAD_API_WIN32) && \ !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) # if defined(__FreeBSD__) || \ - defined(__Fuchsia__) || \ defined(__wasi__) || \ defined(__NetBSD__) || \ defined(__linux__) || \ @@ -1075,6 +1074,8 @@ defined(__sun__) || \ (defined(__MINGW32__) && __has_include()) # define _LIBCPP_HAS_THREAD_API_PTHREAD +# elif defined(__Fuchsia__) +# define _LIBCPP_HAS_THREAD_API_FUCHSIA # elif defined(_LIBCPP_WIN32API) # define _LIBCPP_HAS_THREAD_API_WIN32 # else @@ -1103,6 +1104,7 @@ // TODO(EricWF): Enable this optimization on Apple and Bionic platforms after // speaking to their respective stakeholders. #if (defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && defined(__GLIBC__)) \ + || defined(_LIBCPP_HAS_THREAD_API_FUCHSIA) \ || defined(_LIBCPP_HAS_THREAD_API_WIN32) # define _LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION #endif @@ -1110,7 +1112,8 @@ // Destroying a condvar is a nop on Windows. // 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_FUCHSIA) || \ + defined(_LIBCPP_HAS_THREAD_API_WIN32) # define _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION #endif Index: libcxx/include/__threading_support =================================================================== --- libcxx/include/__threading_support +++ libcxx/include/__threading_support @@ -27,6 +27,9 @@ #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) # include # include +#elif defined(_LIBCPP_HAS_THREAD_API_FUCHSIA) +# define _ALL_SOURCE 1 +# include #endif _LIBCPP_PUSH_MACROS @@ -74,6 +77,33 @@ // Thread Local Storage typedef pthread_key_t __libcpp_tls_key; +#define _LIBCPP_TLS_DESTRUCTOR_CC +#elif defined(_LIBCPP_HAS_THREAD_API_FUCHSIA) +// Mutex +typedef mtx_t __libcpp_mutex_t; +#define _LIBCPP_MUTEX_INITIALIZER MTX_INIT + +typedef mtx_t __libcpp_recursive_mutex_t; + +// Condition Variable +typedef cnd_t __libcpp_condvar_t; +#define _LIBCPP_CONDVAR_INITIALIZER CND_INIT + +// 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 #else // Mutex @@ -204,9 +234,10 @@ _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_tls_set(__libcpp_tls_key __key, void *__p); -#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ - defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) && \ - defined(_LIBCPP_HAS_THREAD_API_PTHREAD) +#if !defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ + defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) + +#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) { @@ -392,6 +423,179 @@ return pthread_setspecific(__key, __p); } +#elif defined(_LIBCPP_HAS_THREAD_API_FUCHSIA) + +int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) +{ + return mtx_init(__m, mtx_recursive); +} + +int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) +{ + return mtx_lock(__m); +} + +bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) +{ + return mtx_trylock(__m); +} + +int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) +{ + return mtx_unlock(__m); +} + +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); +} + +bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) +{ + return mtx_trylock(__m); +} + +int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) +{ + return mtx_unlock(__m); +} + +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); +} + +int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) +{ + return cnd_broadcast(__cv); +} + +int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) +{ + return cnd_wait(__cv, __m); +} + +int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, + timespec *__ts) +{ + return cnd_timedwait(__cv, __m, __ts); +} + +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) +{ + return thrd_create(__t, reinterpret_cast(__func), __arg); +} + +__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); +} + +int __libcpp_thread_detach(__libcpp_thread_t *__t) +{ + return thrd_detach(*__t); +} + +void __libcpp_thread_yield() +{ + thrd_yield(); +} + +void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) +{ + using namespace chrono; + seconds __s = duration_cast(__ns); + timespec __ts; + typedef decltype(__ts.tv_sec) ts_sec; + _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits::max(); + + if (__s.count() < __ts_sec_max) + { + __ts.tv_sec = static_cast(__s.count()); + __ts.tv_nsec = static_cast((__ns - __s).count()); + } + else + { + __ts.tv_sec = __ts_sec_max; + __ts.tv_nsec = 999999999; // (10^9 - 1) + } + + 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); +} + +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); +} + +#endif + #endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL _LIBCPP_END_NAMESPACE_STD