c11.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // -*- C++ -*-
  2. //===----------------------------------------------------------------------===//
  3. //
  4. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  5. // See https://llvm.org/LICENSE.txt for license information.
  6. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #ifndef _LIBCPP___THREAD_SUPPORT_C11_H
  10. #define _LIBCPP___THREAD_SUPPORT_C11_H
  11. #include <__chrono/convert_to_timespec.h>
  12. #include <__chrono/duration.h>
  13. #include <__config>
  14. #include <ctime>
  15. #include <errno.h>
  16. #include <threads.h>
  17. #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
  18. # pragma GCC system_header
  19. #endif
  20. _LIBCPP_BEGIN_NAMESPACE_STD
  21. using __libcpp_timespec_t = ::timespec;
  22. //
  23. // Mutex
  24. //
  25. typedef mtx_t __libcpp_mutex_t;
  26. // mtx_t is a struct so using {} for initialization is valid.
  27. #define _LIBCPP_MUTEX_INITIALIZER \
  28. {}
  29. typedef mtx_t __libcpp_recursive_mutex_t;
  30. inline _LIBCPP_HIDE_FROM_ABI int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t* __m) {
  31. return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL;
  32. }
  33. inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
  34. __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m) {
  35. return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
  36. }
  37. inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool
  38. __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m) {
  39. return mtx_trylock(__m) == thrd_success;
  40. }
  41. inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
  42. __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t* __m) {
  43. return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
  44. }
  45. inline _LIBCPP_HIDE_FROM_ABI int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t* __m) {
  46. mtx_destroy(__m);
  47. return 0;
  48. }
  49. inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_lock(__libcpp_mutex_t* __m) {
  50. return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
  51. }
  52. inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m) {
  53. return mtx_trylock(__m) == thrd_success;
  54. }
  55. inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_unlock(__libcpp_mutex_t* __m) {
  56. return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
  57. }
  58. inline _LIBCPP_HIDE_FROM_ABI int __libcpp_mutex_destroy(__libcpp_mutex_t* __m) {
  59. mtx_destroy(__m);
  60. return 0;
  61. }
  62. //
  63. // Condition Variable
  64. //
  65. typedef cnd_t __libcpp_condvar_t;
  66. // cnd_t is a struct so using {} for initialization is valid.
  67. #define _LIBCPP_CONDVAR_INITIALIZER \
  68. {}
  69. inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_signal(__libcpp_condvar_t* __cv) {
  70. return cnd_signal(__cv) == thrd_success ? 0 : EINVAL;
  71. }
  72. inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv) {
  73. return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL;
  74. }
  75. inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
  76. __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) {
  77. return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL;
  78. }
  79. inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
  80. __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, timespec* __ts) {
  81. int __ec = cnd_timedwait(__cv, __m, __ts);
  82. return __ec == thrd_timedout ? ETIMEDOUT : __ec;
  83. }
  84. inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv) {
  85. cnd_destroy(__cv);
  86. return 0;
  87. }
  88. //
  89. // Execute once
  90. //
  91. typedef ::once_flag __libcpp_exec_once_flag;
  92. #define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT
  93. inline _LIBCPP_HIDE_FROM_ABI int __libcpp_execute_once(__libcpp_exec_once_flag* flag, void (*init_routine)(void)) {
  94. ::call_once(flag, init_routine);
  95. return 0;
  96. }
  97. //
  98. // Thread id
  99. //
  100. typedef thrd_t __libcpp_thread_id;
  101. // Returns non-zero if the thread ids are equal, otherwise 0
  102. inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) {
  103. return thrd_equal(t1, t2) != 0;
  104. }
  105. // Returns non-zero if t1 < t2, otherwise 0
  106. inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) {
  107. return t1 < t2;
  108. }
  109. //
  110. // Thread
  111. //
  112. #define _LIBCPP_NULL_THREAD 0U
  113. typedef thrd_t __libcpp_thread_t;
  114. inline _LIBCPP_HIDE_FROM_ABI __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t) { return *__t; }
  115. inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_isnull(const __libcpp_thread_t* __t) {
  116. return __libcpp_thread_get_id(__t) == 0;
  117. }
  118. inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg) {
  119. int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg);
  120. return __ec == thrd_nomem ? ENOMEM : __ec;
  121. }
  122. inline _LIBCPP_HIDE_FROM_ABI __libcpp_thread_id __libcpp_thread_get_current_id() { return thrd_current(); }
  123. inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_join(__libcpp_thread_t* __t) {
  124. return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL;
  125. }
  126. inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_detach(__libcpp_thread_t* __t) {
  127. return thrd_detach(*__t) == thrd_success ? 0 : EINVAL;
  128. }
  129. inline _LIBCPP_HIDE_FROM_ABI void __libcpp_thread_yield() { thrd_yield(); }
  130. inline _LIBCPP_HIDE_FROM_ABI void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) {
  131. __libcpp_timespec_t __ts = std::__convert_to_timespec<__libcpp_timespec_t>(__ns);
  132. thrd_sleep(&__ts, nullptr);
  133. }
  134. //
  135. // Thread local storage
  136. //
  137. #define _LIBCPP_TLS_DESTRUCTOR_CC /* nothing */
  138. typedef tss_t __libcpp_tls_key;
  139. inline _LIBCPP_HIDE_FROM_ABI int __libcpp_tls_create(__libcpp_tls_key* __key, void (*__at_exit)(void*)) {
  140. return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL;
  141. }
  142. inline _LIBCPP_HIDE_FROM_ABI void* __libcpp_tls_get(__libcpp_tls_key __key) { return tss_get(__key); }
  143. inline _LIBCPP_HIDE_FROM_ABI int __libcpp_tls_set(__libcpp_tls_key __key, void* __p) {
  144. return tss_set(__key, __p) == thrd_success ? 0 : EINVAL;
  145. }
  146. _LIBCPP_END_NAMESPACE_STD
  147. #endif // _LIBCPP___THREAD_SUPPORT_C11_H