[LoongArch] Fix incorrect pattern [X]VBITSELI_B instructions
[llvm-project.git] / libcxx / include / __threading_support
blobea6db4a3d59c1c8b8f3647ee33dfa270f4e4566f
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 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___THREADING_SUPPORT
11 #define _LIBCPP___THREADING_SUPPORT
13 #include <__availability>
14 #include <__chrono/convert_to_timespec.h>
15 #include <__chrono/duration.h>
16 #include <__config>
17 #include <__fwd/hash.h>
18 #include <ctime>
19 #include <errno.h>
21 #ifdef __MVS__
22 #  include <__support/ibm/nanosleep.h>
23 #endif
25 #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
26 #  pragma GCC system_header
27 #endif
29 #if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
30 #  include <__external_threading>
31 #elif !defined(_LIBCPP_HAS_NO_THREADS)
33 #  if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
34 // Some platforms require <bits/atomic_wide_counter.h> in order for
35 // PTHREAD_COND_INITIALIZER to be expanded. Normally that would come
36 // in via <pthread.h>, but it's a non-modular header on those platforms,
37 // so libc++'s <math.h> usually absorbs atomic_wide_counter.h into the
38 // module with <math.h> and makes atomic_wide_counter.h invisible.
39 // Include <math.h> here to work around that.
40 #    include <math.h>
42 #    include <pthread.h>
43 #    include <sched.h>
44 #  elif defined(_LIBCPP_HAS_THREAD_API_C11)
45 #    include <threads.h>
46 #  endif
48 #  if defined(_LIBCPP_HAS_THREAD_API_WIN32)
49 #    define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_EXPORTED_FROM_ABI
50 #  else
51 #    define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_HIDE_FROM_ABI
52 #  endif
54 typedef ::timespec __libcpp_timespec_t;
55 #endif // !defined(_LIBCPP_HAS_NO_THREADS)
57 _LIBCPP_BEGIN_NAMESPACE_STD
59 #if !defined(_LIBCPP_HAS_NO_THREADS)
61 #  if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
62 // Mutex
63 typedef pthread_mutex_t __libcpp_mutex_t;
64 #    define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
66 typedef pthread_mutex_t __libcpp_recursive_mutex_t;
68 // Condition Variable
69 typedef pthread_cond_t __libcpp_condvar_t;
70 #    define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
72 // Execute once
73 typedef pthread_once_t __libcpp_exec_once_flag;
74 #    define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
76 // Thread id
77 #    if defined(__MVS__)
78 typedef unsigned long long __libcpp_thread_id;
79 #    else
80 typedef pthread_t __libcpp_thread_id;
81 #    endif
83 // Thread
84 #    define _LIBCPP_NULL_THREAD ((__libcpp_thread_t()))
85 typedef pthread_t __libcpp_thread_t;
87 // Thread Local Storage
88 typedef pthread_key_t __libcpp_tls_key;
90 #    define _LIBCPP_TLS_DESTRUCTOR_CC
91 #  elif defined(_LIBCPP_HAS_THREAD_API_C11)
92 // Mutex
93 typedef mtx_t __libcpp_mutex_t;
94 // mtx_t is a struct so using {} for initialization is valid.
95 #    define _LIBCPP_MUTEX_INITIALIZER                                                                                  \
96       {}
98 typedef mtx_t __libcpp_recursive_mutex_t;
100 // Condition Variable
101 typedef cnd_t __libcpp_condvar_t;
102 // cnd_t is a struct so using {} for initialization is valid.
103 #    define _LIBCPP_CONDVAR_INITIALIZER                                                                                \
104       {}
106 // Execute once
107 typedef ::once_flag __libcpp_exec_once_flag;
108 #    define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT
110 // Thread id
111 typedef thrd_t __libcpp_thread_id;
113 // Thread
114 #    define _LIBCPP_NULL_THREAD 0U
116 typedef thrd_t __libcpp_thread_t;
118 // Thread Local Storage
119 typedef tss_t __libcpp_tls_key;
121 #    define _LIBCPP_TLS_DESTRUCTOR_CC
122 #  elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
123 // Mutex
124 typedef void* __libcpp_mutex_t;
125 #    define _LIBCPP_MUTEX_INITIALIZER 0
127 #    if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__)
128 typedef void* __libcpp_recursive_mutex_t[6];
129 #    elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__)
130 typedef void* __libcpp_recursive_mutex_t[5];
131 #    else
132 #      error Unsupported architecture
133 #    endif
135 // Condition Variable
136 typedef void* __libcpp_condvar_t;
137 #    define _LIBCPP_CONDVAR_INITIALIZER 0
139 // Execute Once
140 typedef void* __libcpp_exec_once_flag;
141 #    define _LIBCPP_EXEC_ONCE_INITIALIZER 0
143 // Thread ID
144 typedef long __libcpp_thread_id;
146 // Thread
147 #    define _LIBCPP_NULL_THREAD 0U
149 typedef void* __libcpp_thread_t;
151 // Thread Local Storage
152 typedef long __libcpp_tls_key;
154 #    define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall
155 #  endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
157 #  if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
158 // Mutex
159 _LIBCPP_THREAD_ABI_VISIBILITY
160 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t* __m);
162 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
163 __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m);
165 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool
166 __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m);
168 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
169 __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t* __m);
171 _LIBCPP_THREAD_ABI_VISIBILITY
172 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t* __m);
174 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_lock(__libcpp_mutex_t* __m);
176 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m);
178 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_unlock(__libcpp_mutex_t* __m);
180 _LIBCPP_THREAD_ABI_VISIBILITY
181 int __libcpp_mutex_destroy(__libcpp_mutex_t* __m);
183 // Condition variable
184 _LIBCPP_THREAD_ABI_VISIBILITY
185 int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
187 _LIBCPP_THREAD_ABI_VISIBILITY
188 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
190 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
191 __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
193 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
194 __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, __libcpp_timespec_t* __ts);
196 _LIBCPP_THREAD_ABI_VISIBILITY
197 int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
199 // Execute once
200 _LIBCPP_THREAD_ABI_VISIBILITY
201 int __libcpp_execute_once(__libcpp_exec_once_flag* __flag, void (*__init_routine)());
203 // Thread id
204 _LIBCPP_THREAD_ABI_VISIBILITY
205 bool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2);
207 _LIBCPP_THREAD_ABI_VISIBILITY
208 bool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2);
210 // Thread
211 _LIBCPP_THREAD_ABI_VISIBILITY
212 bool __libcpp_thread_isnull(const __libcpp_thread_t* __t);
214 _LIBCPP_THREAD_ABI_VISIBILITY
215 int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg);
217 _LIBCPP_THREAD_ABI_VISIBILITY
218 __libcpp_thread_id __libcpp_thread_get_current_id();
220 _LIBCPP_THREAD_ABI_VISIBILITY
221 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t);
223 _LIBCPP_THREAD_ABI_VISIBILITY
224 int __libcpp_thread_join(__libcpp_thread_t* __t);
226 _LIBCPP_THREAD_ABI_VISIBILITY
227 int __libcpp_thread_detach(__libcpp_thread_t* __t);
229 _LIBCPP_THREAD_ABI_VISIBILITY
230 void __libcpp_thread_yield();
232 _LIBCPP_THREAD_ABI_VISIBILITY
233 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
235 // Thread local storage
236 _LIBCPP_THREAD_ABI_VISIBILITY
237 int __libcpp_tls_create(__libcpp_tls_key* __key, void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
239 _LIBCPP_THREAD_ABI_VISIBILITY
240 void* __libcpp_tls_get(__libcpp_tls_key __key);
242 _LIBCPP_THREAD_ABI_VISIBILITY
243 int __libcpp_tls_set(__libcpp_tls_key __key, void* __p);
245 #  endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
247 #  if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
249 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t* __m) {
250   pthread_mutexattr_t __attr;
251   int __ec = pthread_mutexattr_init(&__attr);
252   if (__ec)
253     return __ec;
254   __ec = pthread_mutexattr_settype(&__attr, PTHREAD_MUTEX_RECURSIVE);
255   if (__ec) {
256     pthread_mutexattr_destroy(&__attr);
257     return __ec;
258   }
259   __ec = pthread_mutex_init(__m, &__attr);
260   if (__ec) {
261     pthread_mutexattr_destroy(&__attr);
262     return __ec;
263   }
264   __ec = pthread_mutexattr_destroy(&__attr);
265   if (__ec) {
266     pthread_mutex_destroy(__m);
267     return __ec;
268   }
269   return 0;
272 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m) { return pthread_mutex_lock(__m); }
274 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m) { return pthread_mutex_trylock(__m) == 0; }
276 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t* __m) { return pthread_mutex_unlock(__m); }
278 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t* __m) { return pthread_mutex_destroy(__m); }
280 int __libcpp_mutex_lock(__libcpp_mutex_t* __m) { return pthread_mutex_lock(__m); }
282 bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m) { return pthread_mutex_trylock(__m) == 0; }
284 int __libcpp_mutex_unlock(__libcpp_mutex_t* __m) { return pthread_mutex_unlock(__m); }
286 int __libcpp_mutex_destroy(__libcpp_mutex_t* __m) { return pthread_mutex_destroy(__m); }
288 // Condition Variable
289 int __libcpp_condvar_signal(__libcpp_condvar_t* __cv) { return pthread_cond_signal(__cv); }
291 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv) { return pthread_cond_broadcast(__cv); }
293 int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) { return pthread_cond_wait(__cv, __m); }
295 int __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, __libcpp_timespec_t* __ts) {
296   return pthread_cond_timedwait(__cv, __m, __ts);
299 int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv) { return pthread_cond_destroy(__cv); }
301 // Execute once
302 int __libcpp_execute_once(__libcpp_exec_once_flag* __flag, void (*__init_routine)()) {
303   return pthread_once(__flag, __init_routine);
306 // Thread id
307 // Returns non-zero if the thread ids are equal, otherwise 0
308 bool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2) { return __t1 == __t2; }
310 // Returns non-zero if t1 < t2, otherwise 0
311 bool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2) { return __t1 < __t2; }
313 // Thread
314 bool __libcpp_thread_isnull(const __libcpp_thread_t* __t) { return __libcpp_thread_get_id(__t) == 0; }
316 int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg) {
317   return pthread_create(__t, nullptr, __func, __arg);
320 __libcpp_thread_id __libcpp_thread_get_current_id() {
321   const __libcpp_thread_t __current_thread = pthread_self();
322   return __libcpp_thread_get_id(&__current_thread);
325 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t) {
326 #    if defined(__MVS__)
327   return __t->__;
328 #    else
329   return *__t;
330 #    endif
333 int __libcpp_thread_join(__libcpp_thread_t* __t) { return pthread_join(*__t, nullptr); }
335 int __libcpp_thread_detach(__libcpp_thread_t* __t) { return pthread_detach(*__t); }
337 void __libcpp_thread_yield() { sched_yield(); }
339 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) {
340   __libcpp_timespec_t __ts = std::__convert_to_timespec<__libcpp_timespec_t>(__ns);
341   while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
342     ;
345 // Thread local storage
346 int __libcpp_tls_create(__libcpp_tls_key* __key, void (*__at_exit)(void*)) {
347   return pthread_key_create(__key, __at_exit);
350 void* __libcpp_tls_get(__libcpp_tls_key __key) { return pthread_getspecific(__key); }
352 int __libcpp_tls_set(__libcpp_tls_key __key, void* __p) { return pthread_setspecific(__key, __p); }
354 #  elif defined(_LIBCPP_HAS_THREAD_API_C11)
356 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t* __m) {
357   return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL;
360 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m) {
361   return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
364 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m) { return mtx_trylock(__m) == thrd_success; }
366 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t* __m) {
367   return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
370 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t* __m) {
371   mtx_destroy(__m);
372   return 0;
375 int __libcpp_mutex_lock(__libcpp_mutex_t* __m) { return mtx_lock(__m) == thrd_success ? 0 : EINVAL; }
377 bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m) { return mtx_trylock(__m) == thrd_success; }
379 int __libcpp_mutex_unlock(__libcpp_mutex_t* __m) { return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; }
381 int __libcpp_mutex_destroy(__libcpp_mutex_t* __m) {
382   mtx_destroy(__m);
383   return 0;
386 // Condition Variable
387 int __libcpp_condvar_signal(__libcpp_condvar_t* __cv) { return cnd_signal(__cv) == thrd_success ? 0 : EINVAL; }
389 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv) { return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL; }
391 int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) {
392   return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL;
395 int __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, timespec* __ts) {
396   int __ec = cnd_timedwait(__cv, __m, __ts);
397   return __ec == thrd_timedout ? ETIMEDOUT : __ec;
400 int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv) {
401   cnd_destroy(__cv);
402   return 0;
405 // Execute once
406 int __libcpp_execute_once(__libcpp_exec_once_flag* flag, void (*init_routine)(void)) {
407   ::call_once(flag, init_routine);
408   return 0;
411 // Thread id
412 // Returns non-zero if the thread ids are equal, otherwise 0
413 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) { return thrd_equal(t1, t2) != 0; }
415 // Returns non-zero if t1 < t2, otherwise 0
416 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) { return t1 < t2; }
418 // Thread
419 bool __libcpp_thread_isnull(const __libcpp_thread_t* __t) { return __libcpp_thread_get_id(__t) == 0; }
421 int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg) {
422   int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg);
423   return __ec == thrd_nomem ? ENOMEM : __ec;
426 __libcpp_thread_id __libcpp_thread_get_current_id() { return thrd_current(); }
428 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t) { return *__t; }
430 int __libcpp_thread_join(__libcpp_thread_t* __t) { return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL; }
432 int __libcpp_thread_detach(__libcpp_thread_t* __t) { return thrd_detach(*__t) == thrd_success ? 0 : EINVAL; }
434 void __libcpp_thread_yield() { thrd_yield(); }
436 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) {
437   __libcpp_timespec_t __ts = std::__convert_to_timespec<__libcpp_timespec_t>(__ns);
438   thrd_sleep(&__ts, nullptr);
441 // Thread local storage
442 int __libcpp_tls_create(__libcpp_tls_key* __key, void (*__at_exit)(void*)) {
443   return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL;
446 void* __libcpp_tls_get(__libcpp_tls_key __key) { return tss_get(__key); }
448 int __libcpp_tls_set(__libcpp_tls_key __key, void* __p) { return tss_set(__key, __p) == thrd_success ? 0 : EINVAL; }
450 #  endif
452 #endif // !_LIBCPP_HAS_NO_THREADS
454 _LIBCPP_END_NAMESPACE_STD
456 #endif // _LIBCPP___THREADING_SUPPORT