]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/libcxx/include/__threading_support
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / libcxx / include / __threading_support
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
10 #ifndef _LIBCPP_THREADING_SUPPORT
11 #define _LIBCPP_THREADING_SUPPORT
12
13 #include <__config>
14 #include <chrono>
15 #include <iosfwd>
16 #include <errno.h>
17
18 #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
19 #pragma GCC system_header
20 #endif
21
22 #if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
23 # include <__external_threading>
24 #elif !defined(_LIBCPP_HAS_NO_THREADS)
25
26 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
27 # include <pthread.h>
28 # include <sched.h>
29 # ifdef __APPLE__
30 #  define _LIBCPP_NO_NATIVE_SEMAPHORES
31 # endif
32 # ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
33 # include <semaphore.h>
34 # endif
35 #elif defined(_LIBCPP_HAS_THREAD_API_C11)
36 # include <threads.h>
37 #endif
38
39 #if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
40     defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \
41     defined(_LIBCPP_HAS_THREAD_API_WIN32)
42 #define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
43 #else
44 #define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
45 #endif
46
47 #if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis)
48 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
49 #else
50 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
51 #endif
52
53 typedef ::timespec __libcpp_timespec_t;
54 #endif // !defined(_LIBCPP_HAS_NO_THREADS)
55
56 _LIBCPP_PUSH_MACROS
57 #include <__undef_macros>
58
59 _LIBCPP_BEGIN_NAMESPACE_STD
60
61 #if !defined(_LIBCPP_HAS_NO_THREADS)
62
63 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
64 // Mutex
65 typedef pthread_mutex_t __libcpp_mutex_t;
66 #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
67
68 typedef pthread_mutex_t __libcpp_recursive_mutex_t;
69
70 // Condition Variable
71 typedef pthread_cond_t __libcpp_condvar_t;
72 #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
73
74 #ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
75 // Semaphore
76 typedef sem_t __libcpp_semaphore_t;
77 # define _LIBCPP_SEMAPHORE_MAX SEM_VALUE_MAX
78 #endif
79
80 // Execute once
81 typedef pthread_once_t __libcpp_exec_once_flag;
82 #define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
83
84 // Thread id
85 typedef pthread_t __libcpp_thread_id;
86
87 // Thread
88 #define _LIBCPP_NULL_THREAD 0U
89
90 typedef pthread_t __libcpp_thread_t;
91
92 // Thread Local Storage
93 typedef pthread_key_t __libcpp_tls_key;
94
95 #define _LIBCPP_TLS_DESTRUCTOR_CC
96 #elif defined(_LIBCPP_HAS_THREAD_API_C11)
97 // Mutex
98 typedef mtx_t __libcpp_mutex_t;
99 // mtx_t is a struct so using {} for initialization is valid.
100 #define _LIBCPP_MUTEX_INITIALIZER {}
101
102 typedef mtx_t __libcpp_recursive_mutex_t;
103
104 // Condition Variable
105 typedef cnd_t __libcpp_condvar_t;
106 // cnd_t is a struct so using {} for initialization is valid.
107 #define _LIBCPP_CONDVAR_INITIALIZER {}
108
109 // Execute once
110 typedef once_flag __libcpp_exec_once_flag;
111 #define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT
112
113 // Thread id
114 typedef thrd_t __libcpp_thread_id;
115
116 // Thread
117 #define _LIBCPP_NULL_THREAD 0U
118
119 typedef thrd_t __libcpp_thread_t;
120
121 // Thread Local Storage
122 typedef tss_t __libcpp_tls_key;
123
124 #define _LIBCPP_TLS_DESTRUCTOR_CC
125 #elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
126 // Mutex
127 typedef void* __libcpp_mutex_t;
128 #define _LIBCPP_MUTEX_INITIALIZER 0
129
130 #if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__)
131 typedef void* __libcpp_recursive_mutex_t[6];
132 #elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__)
133 typedef void* __libcpp_recursive_mutex_t[5];
134 #else
135 # error Unsupported architecture
136 #endif
137
138 // Condition Variable
139 typedef void* __libcpp_condvar_t;
140 #define _LIBCPP_CONDVAR_INITIALIZER 0
141
142 // Semaphore
143 typedef void* __libcpp_semaphore_t;
144
145 // Execute Once
146 typedef void* __libcpp_exec_once_flag;
147 #define _LIBCPP_EXEC_ONCE_INITIALIZER 0
148
149 // Thread ID
150 typedef long __libcpp_thread_id;
151
152 // Thread
153 #define _LIBCPP_NULL_THREAD 0U
154
155 typedef void* __libcpp_thread_t;
156
157 // Thread Local Storage
158 typedef long __libcpp_tls_key;
159
160 #define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall
161 #endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
162
163 #if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
164 // Mutex
165 _LIBCPP_THREAD_ABI_VISIBILITY
166 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
167
168 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
169 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
170
171 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
172 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
173
174 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
175 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
176
177 _LIBCPP_THREAD_ABI_VISIBILITY
178 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
179
180 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
181 int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
182
183 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
184 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
185
186 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
187 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
188
189 _LIBCPP_THREAD_ABI_VISIBILITY
190 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
191
192 // Condition variable
193 _LIBCPP_THREAD_ABI_VISIBILITY
194 int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
195
196 _LIBCPP_THREAD_ABI_VISIBILITY
197 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
198
199 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
200 int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
201
202 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
203 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
204                                __libcpp_timespec_t *__ts);
205
206 _LIBCPP_THREAD_ABI_VISIBILITY
207 int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
208
209 #ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
210
211 // Semaphore
212 _LIBCPP_THREAD_ABI_VISIBILITY
213 bool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init);
214
215 _LIBCPP_THREAD_ABI_VISIBILITY
216 bool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem);
217
218 _LIBCPP_THREAD_ABI_VISIBILITY
219 bool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem);
220
221 _LIBCPP_THREAD_ABI_VISIBILITY
222 bool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem);
223
224 _LIBCPP_THREAD_ABI_VISIBILITY
225 bool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns);
226
227 #endif // _LIBCPP_NO_NATIVE_SEMAPHORES
228
229 // Execute once
230 _LIBCPP_THREAD_ABI_VISIBILITY
231 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
232                           void (*init_routine)());
233
234 // Thread id
235 _LIBCPP_THREAD_ABI_VISIBILITY
236 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
237
238 _LIBCPP_THREAD_ABI_VISIBILITY
239 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
240
241 // Thread
242 _LIBCPP_THREAD_ABI_VISIBILITY
243 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
244
245 _LIBCPP_THREAD_ABI_VISIBILITY
246 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
247                            void *__arg);
248
249 _LIBCPP_THREAD_ABI_VISIBILITY
250 __libcpp_thread_id __libcpp_thread_get_current_id();
251
252 _LIBCPP_THREAD_ABI_VISIBILITY
253 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
254
255 _LIBCPP_THREAD_ABI_VISIBILITY
256 int __libcpp_thread_join(__libcpp_thread_t *__t);
257
258 _LIBCPP_THREAD_ABI_VISIBILITY
259 int __libcpp_thread_detach(__libcpp_thread_t *__t);
260
261 _LIBCPP_THREAD_ABI_VISIBILITY
262 void __libcpp_thread_yield();
263
264 _LIBCPP_THREAD_ABI_VISIBILITY
265 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
266
267 // Thread local storage
268 _LIBCPP_THREAD_ABI_VISIBILITY
269 int __libcpp_tls_create(__libcpp_tls_key* __key,
270                         void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
271
272 _LIBCPP_THREAD_ABI_VISIBILITY
273 void *__libcpp_tls_get(__libcpp_tls_key __key);
274
275 _LIBCPP_THREAD_ABI_VISIBILITY
276 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
277
278 #endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
279
280 struct __libcpp_timed_backoff_policy {
281   _LIBCPP_THREAD_ABI_VISIBILITY
282   bool operator()(chrono::nanoseconds __elapsed) const;
283 };
284
285 inline _LIBCPP_INLINE_VISIBILITY
286 bool __libcpp_timed_backoff_policy::operator()(chrono::nanoseconds __elapsed) const
287 {
288     if(__elapsed > chrono::milliseconds(128))
289         __libcpp_thread_sleep_for(chrono::milliseconds(8));
290     else if(__elapsed > chrono::microseconds(64))
291         __libcpp_thread_sleep_for(__elapsed / 2);
292     else if(__elapsed > chrono::microseconds(4))
293       __libcpp_thread_yield();
294     else
295       ; // poll
296     return false;
297 }
298
299 static _LIBCPP_CONSTEXPR const int __libcpp_polling_count = 64;
300
301 template<class _Fn, class _BFn>
302 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
303 bool __libcpp_thread_poll_with_backoff(
304   _Fn && __f, _BFn && __bf, chrono::nanoseconds __max_elapsed = chrono::nanoseconds::zero())
305 {
306     auto const __start = chrono::high_resolution_clock::now();
307     for(int __count = 0;;) {
308       if(__f())
309         return true; // _Fn completion means success
310       if(__count < __libcpp_polling_count) {
311         __count += 1;
312         continue;
313       }
314       chrono::nanoseconds const __elapsed = chrono::high_resolution_clock::now() - __start;
315       if(__max_elapsed != chrono::nanoseconds::zero() && __max_elapsed < __elapsed)
316           return false; // timeout failure
317       if(__bf(__elapsed))
318         return false; // _BFn completion means failure
319     }
320 }
321
322 #if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
323      defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL))
324
325
326 namespace __thread_detail {
327
328 inline __libcpp_timespec_t __convert_to_timespec(const chrono::nanoseconds& __ns)
329 {
330   using namespace chrono;
331   seconds __s = duration_cast<seconds>(__ns);
332   __libcpp_timespec_t __ts;
333   typedef decltype(__ts.tv_sec) __ts_sec;
334   const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max();
335
336   if (__s.count() < __ts_sec_max)
337   {
338     __ts.tv_sec = static_cast<__ts_sec>(__s.count());
339     __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
340   }
341   else
342   {
343     __ts.tv_sec = __ts_sec_max;
344     __ts.tv_nsec = 999999999; // (10^9 - 1)
345   }
346
347   return __ts;
348 }
349
350 }
351
352 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
353
354 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
355 {
356   pthread_mutexattr_t attr;
357   int __ec = pthread_mutexattr_init(&attr);
358   if (__ec)
359     return __ec;
360   __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
361   if (__ec) {
362     pthread_mutexattr_destroy(&attr);
363     return __ec;
364   }
365   __ec = pthread_mutex_init(__m, &attr);
366   if (__ec) {
367     pthread_mutexattr_destroy(&attr);
368     return __ec;
369   }
370   __ec = pthread_mutexattr_destroy(&attr);
371   if (__ec) {
372     pthread_mutex_destroy(__m);
373     return __ec;
374   }
375   return 0;
376 }
377
378 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
379 {
380   return pthread_mutex_lock(__m);
381 }
382
383 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
384 {
385   return pthread_mutex_trylock(__m) == 0;
386 }
387
388 int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
389 {
390   return pthread_mutex_unlock(__m);
391 }
392
393 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
394 {
395   return pthread_mutex_destroy(__m);
396 }
397
398 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
399 {
400   return pthread_mutex_lock(__m);
401 }
402
403 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
404 {
405   return pthread_mutex_trylock(__m) == 0;
406 }
407
408 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
409 {
410   return pthread_mutex_unlock(__m);
411 }
412
413 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
414 {
415   return pthread_mutex_destroy(__m);
416 }
417
418 // Condition Variable
419 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
420 {
421   return pthread_cond_signal(__cv);
422 }
423
424 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
425 {
426   return pthread_cond_broadcast(__cv);
427 }
428
429 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
430 {
431   return pthread_cond_wait(__cv, __m);
432 }
433
434 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
435                                __libcpp_timespec_t *__ts)
436 {
437   return pthread_cond_timedwait(__cv, __m, __ts);
438 }
439
440 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
441 {
442   return pthread_cond_destroy(__cv);
443 }
444
445 #ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
446
447 // Semaphore
448 bool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init)
449 {
450     return sem_init(__sem, 0, __init) == 0;
451 }
452
453 bool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem)
454 {
455     return sem_destroy(__sem) == 0;
456 }
457
458 bool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem)
459 {
460     return sem_post(__sem) == 0;
461 }
462
463 bool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem)
464 {
465     return sem_wait(__sem) == 0;
466 }
467
468 bool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns)
469 {
470     auto const __abs_time = chrono::system_clock::now().time_since_epoch() + __ns;
471     __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__abs_time);
472     return sem_timedwait(__sem, &__ts) == 0;
473 }
474
475 #endif //_LIBCPP_NO_NATIVE_SEMAPHORES
476
477 // Execute once
478 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
479                           void (*init_routine)()) {
480   return pthread_once(flag, init_routine);
481 }
482
483 // Thread id
484 // Returns non-zero if the thread ids are equal, otherwise 0
485 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
486 {
487   return pthread_equal(t1, t2) != 0;
488 }
489
490 // Returns non-zero if t1 < t2, otherwise 0
491 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
492 {
493   return t1 < t2;
494 }
495
496 // Thread
497 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
498   return *__t == 0;
499 }
500
501 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
502                            void *__arg)
503 {
504   return pthread_create(__t, 0, __func, __arg);
505 }
506
507 __libcpp_thread_id __libcpp_thread_get_current_id()
508 {
509   return pthread_self();
510 }
511
512 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
513 {
514   return *__t;
515 }
516
517 int __libcpp_thread_join(__libcpp_thread_t *__t)
518 {
519   return pthread_join(*__t, 0);
520 }
521
522 int __libcpp_thread_detach(__libcpp_thread_t *__t)
523 {
524   return pthread_detach(*__t);
525 }
526
527 void __libcpp_thread_yield()
528 {
529   sched_yield();
530 }
531
532 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
533 {
534    __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
535    while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
536 }
537
538 // Thread local storage
539 int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
540 {
541   return pthread_key_create(__key, __at_exit);
542 }
543
544 void *__libcpp_tls_get(__libcpp_tls_key __key)
545 {
546   return pthread_getspecific(__key);
547 }
548
549 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
550 {
551     return pthread_setspecific(__key, __p);
552 }
553
554 #elif defined(_LIBCPP_HAS_THREAD_API_C11)
555
556 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
557 {
558   return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL;
559 }
560
561 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
562 {
563   return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
564 }
565
566 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
567 {
568   return mtx_trylock(__m) == thrd_success;
569 }
570
571 int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
572 {
573   return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
574 }
575
576 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
577 {
578   mtx_destroy(__m);
579   return 0;
580 }
581
582 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
583 {
584   return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
585 }
586
587 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
588 {
589   return mtx_trylock(__m) == thrd_success;
590 }
591
592 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
593 {
594   return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
595 }
596
597 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
598 {
599   mtx_destroy(__m);
600   return 0;
601 }
602
603 // Condition Variable
604 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
605 {
606   return cnd_signal(__cv) == thrd_success ? 0 : EINVAL;
607 }
608
609 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
610 {
611   return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL;
612 }
613
614 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
615 {
616   return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL;
617 }
618
619 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
620                                timespec *__ts)
621 {
622   int __ec = cnd_timedwait(__cv, __m, __ts);
623   return __ec == thrd_timedout ? ETIMEDOUT : __ec;
624 }
625
626 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
627 {
628   cnd_destroy(__cv);
629   return 0;
630 }
631
632 // Execute once
633 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
634                           void (*init_routine)(void)) {
635   ::call_once(flag, init_routine);
636   return 0;
637 }
638
639 // Thread id
640 // Returns non-zero if the thread ids are equal, otherwise 0
641 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
642 {
643   return thrd_equal(t1, t2) != 0;
644 }
645
646 // Returns non-zero if t1 < t2, otherwise 0
647 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
648 {
649   return t1 < t2;
650 }
651
652 // Thread
653 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
654   return *__t == 0;
655 }
656
657 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
658                            void *__arg)
659 {
660   int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg);
661   return __ec == thrd_nomem ? ENOMEM : __ec;
662 }
663
664 __libcpp_thread_id __libcpp_thread_get_current_id()
665 {
666   return thrd_current();
667 }
668
669 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
670 {
671   return *__t;
672 }
673
674 int __libcpp_thread_join(__libcpp_thread_t *__t)
675 {
676   return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL;
677 }
678
679 int __libcpp_thread_detach(__libcpp_thread_t *__t)
680 {
681   return thrd_detach(*__t) == thrd_success ? 0 : EINVAL;
682 }
683
684 void __libcpp_thread_yield()
685 {
686   thrd_yield();
687 }
688
689 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
690 {
691    __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
692   thrd_sleep(&__ts, nullptr);
693 }
694
695 // Thread local storage
696 int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
697 {
698   return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL;
699 }
700
701 void *__libcpp_tls_get(__libcpp_tls_key __key)
702 {
703   return tss_get(__key);
704 }
705
706 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
707 {
708   return tss_set(__key, __p) == thrd_success ? 0 : EINVAL;
709 }
710
711 #endif
712
713
714 #endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
715
716 class _LIBCPP_TYPE_VIS thread;
717 class _LIBCPP_TYPE_VIS __thread_id;
718
719 namespace this_thread
720 {
721
722 _LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
723
724 }  // this_thread
725
726 template<> struct hash<__thread_id>;
727
728 class _LIBCPP_TEMPLATE_VIS __thread_id
729 {
730     // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
731     // NULL is the no-thread value on Darwin.  Someone needs to check
732     // on other platforms.  We assume 0 works everywhere for now.
733     __libcpp_thread_id __id_;
734
735 public:
736     _LIBCPP_INLINE_VISIBILITY
737     __thread_id() _NOEXCEPT : __id_(0) {}
738
739     friend _LIBCPP_INLINE_VISIBILITY
740         bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
741         { // don't pass id==0 to underlying routines
742         if (__x.__id_ == 0) return __y.__id_ == 0;
743         if (__y.__id_ == 0) return false;
744         return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
745         }
746     friend _LIBCPP_INLINE_VISIBILITY
747         bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
748         {return !(__x == __y);}
749     friend _LIBCPP_INLINE_VISIBILITY
750         bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
751         { // id==0 is always less than any other thread_id
752         if (__x.__id_ == 0) return __y.__id_ != 0;
753         if (__y.__id_ == 0) return false;
754         return  __libcpp_thread_id_less(__x.__id_, __y.__id_);
755         }
756     friend _LIBCPP_INLINE_VISIBILITY
757         bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
758         {return !(__y < __x);}
759     friend _LIBCPP_INLINE_VISIBILITY
760         bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
761         {return   __y < __x ;}
762     friend _LIBCPP_INLINE_VISIBILITY
763         bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
764         {return !(__x < __y);}
765
766     _LIBCPP_INLINE_VISIBILITY
767     void __reset() { __id_ = 0; }
768
769     template<class _CharT, class _Traits>
770     friend
771     _LIBCPP_INLINE_VISIBILITY
772     basic_ostream<_CharT, _Traits>&
773     operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id);
774
775 private:
776     _LIBCPP_INLINE_VISIBILITY
777     __thread_id(__libcpp_thread_id __id) : __id_(__id) {}
778
779     friend __thread_id this_thread::get_id() _NOEXCEPT;
780     friend class _LIBCPP_TYPE_VIS thread;
781     friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
782 };
783
784 namespace this_thread
785 {
786
787 inline _LIBCPP_INLINE_VISIBILITY
788 __thread_id
789 get_id() _NOEXCEPT
790 {
791     return __libcpp_thread_get_current_id();
792 }
793
794 }  // this_thread
795
796 #endif // !_LIBCPP_HAS_NO_THREADS
797
798 _LIBCPP_END_NAMESPACE_STD
799
800 _LIBCPP_POP_MACROS
801
802 #endif // _LIBCPP_THREADING_SUPPORT