Coverage Report

Created: 2020-03-31 06:27

/Users/buildslave/jenkins/workspace/coverage/llvm-project/libcxx/include/__threading_support
Line
Count
Source (jump to first uncovered line)
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
46
#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
#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
281
     defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL))
282
283
struct __libcpp_timed_backoff_policy {
284
  _LIBCPP_THREAD_ABI_VISIBILITY
285
  bool operator()(chrono::nanoseconds __elapsed) const;
286
};
287
288
template<class _Fn, class _BFn>
289
_LIBCPP_INLINE_VISIBILITY
290
bool __libcpp_thread_poll_with_backoff(
291
  _Fn && __f, _BFn && __bf, chrono::nanoseconds __max_elapsed = chrono::nanoseconds::zero());
292
293
namespace __thread_detail {
294
295
inline __libcpp_timespec_t __convert_to_timespec(const chrono::nanoseconds& __ns)
296
0
{
297
0
  using namespace chrono;
298
0
  seconds __s = duration_cast<seconds>(__ns);
299
0
  __libcpp_timespec_t __ts;
300
0
  typedef decltype(__ts.tv_sec) __ts_sec;
301
0
  const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max();
302
0
303
0
  if (__s.count() < __ts_sec_max)
304
0
  {
305
0
    __ts.tv_sec = static_cast<__ts_sec>(__s.count());
306
0
    __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
307
0
  }
308
0
  else
309
0
  {
310
0
    __ts.tv_sec = __ts_sec_max;
311
0
    __ts.tv_nsec = 999999999; // (10^9 - 1)
312
0
  }
313
0
314
0
  return __ts;
315
0
}
316
317
}
318
319
#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
320
321
int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
322
21.5k
{
323
21.5k
  pthread_mutexattr_t attr;
324
21.5k
  int __ec = pthread_mutexattr_init(&attr);
325
21.5k
  if (__ec)
326
0
    return __ec;
327
21.5k
  __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
328
21.5k
  if (__ec) {
329
0
    pthread_mutexattr_destroy(&attr);
330
0
    return __ec;
331
0
  }
332
21.5k
  __ec = pthread_mutex_init(__m, &attr);
333
21.5k
  if (__ec) {
334
0
    pthread_mutexattr_destroy(&attr);
335
0
    return __ec;
336
0
  }
337
21.5k
  __ec = pthread_mutexattr_destroy(&attr);
338
21.5k
  if (__ec) {
339
0
    pthread_mutex_destroy(__m);
340
0
    return __ec;
341
0
  }
342
21.5k
  return 0;
343
21.5k
}
344
345
int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
346
70.1k
{
347
70.1k
  return pthread_mutex_lock(__m);
348
70.1k
}
349
350
bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
351
9
{
352
9
  return pthread_mutex_trylock(__m) == 0;
353
9
}
354
355
int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
356
70.1k
{
357
70.1k
  return pthread_mutex_unlock(__m);
358
70.1k
}
359
360
int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
361
6.54k
{
362
6.54k
  return pthread_mutex_destroy(__m);
363
6.54k
}
364
365
int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
366
454k
{
367
454k
  return pthread_mutex_lock(__m);
368
454k
}
369
370
bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
371
0
{
372
0
  return pthread_mutex_trylock(__m) == 0;
373
0
}
374
375
int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
376
454k
{
377
454k
  return pthread_mutex_unlock(__m);
378
454k
}
379
380
int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
381
16.0k
{
382
16.0k
  return pthread_mutex_destroy(__m);
383
16.0k
}
384
385
// Condition Variable
386
int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
387
117
{
388
117
  return pthread_cond_signal(__cv);
389
117
}
390
391
int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
392
158k
{
393
158k
  return pthread_cond_broadcast(__cv);
394
158k
}
395
396
int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
397
170
{
398
170
  return pthread_cond_wait(__cv, __m);
399
170
}
400
401
int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
402
                               __libcpp_timespec_t *__ts)
403
13
{
404
13
  return pthread_cond_timedwait(__cv, __m, __ts);
405
13
}
406
407
int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
408
127
{
409
127
  return pthread_cond_destroy(__cv);
410
127
}
411
412
#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES
413
414
// Semaphore
415
bool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init)
416
{
417
    return sem_init(__sem, 0, __init) == 0;
418
}
419
420
bool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem)
421
{
422
    return sem_destroy(__sem) == 0;
423
}
424
425
bool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem)
426
{
427
    return sem_post(__sem) == 0;
428
}
429
430
bool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem)
431
{
432
    return sem_wait(__sem) == 0;
433
}
434
435
bool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, chrono::nanoseconds const& __ns)
436
{
437
    auto const __abs_time = chrono::system_clock::now().time_since_epoch() + __ns;
438
    __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__abs_time);
439
    return sem_timedwait(__sem, &__ts) == 0;
440
}
441
442
#endif //_LIBCPP_NO_NATIVE_SEMAPHORES
443
444
// Execute once
445
int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
446
0
                          void (*init_routine)()) {
447
0
  return pthread_once(flag, init_routine);
448
0
}
449
450
// Thread id
451
// Returns non-zero if the thread ids are equal, otherwise 0
452
bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
453
32
{
454
32
  return pthread_equal(t1, t2) != 0;
455
32
}
456
457
// Returns non-zero if t1 < t2, otherwise 0
458
bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
459
0
{
460
0
  return t1 < t2;
461
0
}
462
463
// Thread
464
99
bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
465
99
  return *__t == 0;
466
99
}
467
468
int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
469
                           void *__arg)
470
{
471
  return pthread_create(__t, 0, __func, __arg);
472
}
473
474
__libcpp_thread_id __libcpp_thread_get_current_id()
475
67.0k
{
476
67.0k
  return pthread_self();
477
67.0k
}
478
479
__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
480
{
481
  return *__t;
482
}
483
484
int __libcpp_thread_join(__libcpp_thread_t *__t)
485
38
{
486
38
  return pthread_join(*__t, 0);
487
38
}
488
489
int __libcpp_thread_detach(__libcpp_thread_t *__t)
490
8
{
491
8
  return pthread_detach(*__t);
492
8
}
493
494
void __libcpp_thread_yield()
495
0
{
496
0
  sched_yield();
497
0
}
498
499
void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
500
0
{
501
0
   __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
502
0
   while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
503
0
}
504
505
// Thread local storage
506
int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
507
14
{
508
14
  return pthread_key_create(__key, __at_exit);
509
14
}
510
511
void *__libcpp_tls_get(__libcpp_tls_key __key)
512
0
{
513
0
  return pthread_getspecific(__key);
514
0
}
515
516
int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
517
6.06k
{
518
6.06k
    return pthread_setspecific(__key, __p);
519
6.06k
}
520
521
#elif defined(_LIBCPP_HAS_THREAD_API_C11)
522
523
int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
524
{
525
  return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL;
526
}
527
528
int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
529
{
530
  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
531
}
532
533
bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
534
{
535
  return mtx_trylock(__m) == thrd_success;
536
}
537
538
int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
539
{
540
  return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
541
}
542
543
int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
544
{
545
  mtx_destroy(__m);
546
  return 0;
547
}
548
549
int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
550
{
551
  return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
552
}
553
554
bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
555
{
556
  return mtx_trylock(__m) == thrd_success;
557
}
558
559
int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
560
{
561
  return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
562
}
563
564
int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
565
{
566
  mtx_destroy(__m);
567
  return 0;
568
}
569
570
// Condition Variable
571
int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
572
{
573
  return cnd_signal(__cv) == thrd_success ? 0 : EINVAL;
574
}
575
576
int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
577
{
578
  return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL;
579
}
580
581
int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
582
{
583
  return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL;
584
}
585
586
int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
587
                               timespec *__ts)
588
{
589
  int __ec = cnd_timedwait(__cv, __m, __ts);
590
  return __ec == thrd_timedout ? ETIMEDOUT : __ec;
591
}
592
593
int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
594
{
595
  cnd_destroy(__cv);
596
  return 0;
597
}
598
599
// Execute once
600
int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
601
                          void (*init_routine)(void)) {
602
  ::call_once(flag, init_routine);
603
  return 0;
604
}
605
606
// Thread id
607
// Returns non-zero if the thread ids are equal, otherwise 0
608
bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
609
{
610
  return thrd_equal(t1, t2) != 0;
611
}
612
613
// Returns non-zero if t1 < t2, otherwise 0
614
bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
615
{
616
  return t1 < t2;
617
}
618
619
// Thread
620
bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
621
  return *__t == 0;
622
}
623
624
int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
625
                           void *__arg)
626
{
627
  int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg);
628
  return __ec == thrd_nomem ? ENOMEM : __ec;
629
}
630
631
__libcpp_thread_id __libcpp_thread_get_current_id()
632
{
633
  return thrd_current();
634
}
635
636
__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
637
{
638
  return *__t;
639
}
640
641
int __libcpp_thread_join(__libcpp_thread_t *__t)
642
{
643
  return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL;
644
}
645
646
int __libcpp_thread_detach(__libcpp_thread_t *__t)
647
{
648
  return thrd_detach(*__t) == thrd_success ? 0 : EINVAL;
649
}
650
651
void __libcpp_thread_yield()
652
{
653
  thrd_yield();
654
}
655
656
void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
657
{
658
   __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
659
  thrd_sleep(&__ts, nullptr);
660
}
661
662
// Thread local storage
663
int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
664
{
665
  return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL;
666
}
667
668
void *__libcpp_tls_get(__libcpp_tls_key __key)
669
{
670
  return tss_get(__key);
671
}
672
673
int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
674
{
675
  return tss_set(__key, __p) == thrd_success ? 0 : EINVAL;
676
}
677
678
#endif
679
680
inline _LIBCPP_INLINE_VISIBILITY
681
bool __libcpp_timed_backoff_policy::operator()(chrono::nanoseconds __elapsed) const
682
0
{
683
0
    if(__elapsed > chrono::milliseconds(128))
684
0
        __libcpp_thread_sleep_for(chrono::milliseconds(8));
685
0
    else if(__elapsed > chrono::microseconds(64))
686
0
        __libcpp_thread_sleep_for(__elapsed / 2);
687
0
    else if(__elapsed > chrono::microseconds(4))
688
0
      __libcpp_thread_yield();
689
0
    else
690
0
      ; // poll
691
0
    return false;
692
0
}
693
694
static _LIBCPP_CONSTEXPR const int __libcpp_polling_count = 64;
695
696
template<class _Fn, class _BFn>
697
bool __libcpp_thread_poll_with_backoff(_Fn && __f, _BFn && __bf, chrono::nanoseconds __max_elapsed)
698
0
{
699
0
    auto const __start = chrono::high_resolution_clock::now();
700
0
    for(int __count = 0;;) {
701
0
      if(__f())
702
0
        return true; // _Fn completion means success
703
0
      if(__count < __libcpp_polling_count) {
704
0
        __count += 1;
705
0
        continue;
706
0
      }
707
0
      chrono::nanoseconds const __elapsed = chrono::high_resolution_clock::now() - __start;
708
0
      if(__max_elapsed != chrono::nanoseconds::zero() && __max_elapsed < __elapsed)
709
0
          return false; // timeout failure
710
0
      if(__bf(__elapsed))
711
0
        return false; // _BFn completion means failure
712
0
    }
713
0
}
Unexecuted instantiation: bool std::__1::__libcpp_thread_poll_with_backoff<std::__1::__cxx_atomic_wait_test_fn_impl<std::__1::__cxx_atomic_impl<bool, std::__1::__cxx_atomic_base_impl<bool> > const volatile, bool>&, std::__1::__libcpp_atomic_wait_backoff_impl<std::__1::__cxx_atomic_impl<bool, std::__1::__cxx_atomic_base_impl<bool> > const volatile, std::__1::__cxx_atomic_wait_test_fn_impl<std::__1::__cxx_atomic_impl<bool, std::__1::__cxx_atomic_base_impl<bool> > const volatile, bool> >&>(std::__1::__cxx_atomic_wait_test_fn_impl<std::__1::__cxx_atomic_impl<bool, std::__1::__cxx_atomic_base_impl<bool> > const volatile, bool>&&&, std::__1::__libcpp_atomic_wait_backoff_impl<std::__1::__cxx_atomic_impl<bool, std::__1::__cxx_atomic_base_impl<bool> > const volatile, std::__1::__cxx_atomic_wait_test_fn_impl<std::__1::__cxx_atomic_impl<bool, std::__1::__cxx_atomic_base_impl<bool> > const volatile, bool> >&&&, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> >)
Unexecuted instantiation: bool std::__1::__libcpp_thread_poll_with_backoff<std::__1::__cxx_atomic_wait_test_fn_impl<std::__1::__cxx_atomic_impl<bool, std::__1::__cxx_atomic_base_impl<bool> > const, bool>&, std::__1::__libcpp_atomic_wait_backoff_impl<std::__1::__cxx_atomic_impl<bool, std::__1::__cxx_atomic_base_impl<bool> > const, std::__1::__cxx_atomic_wait_test_fn_impl<std::__1::__cxx_atomic_impl<bool, std::__1::__cxx_atomic_base_impl<bool> > const, bool> >&>(std::__1::__cxx_atomic_wait_test_fn_impl<std::__1::__cxx_atomic_impl<bool, std::__1::__cxx_atomic_base_impl<bool> > const, bool>&&&, std::__1::__libcpp_atomic_wait_backoff_impl<std::__1::__cxx_atomic_impl<bool, std::__1::__cxx_atomic_base_impl<bool> > const, std::__1::__cxx_atomic_wait_test_fn_impl<std::__1::__cxx_atomic_impl<bool, std::__1::__cxx_atomic_base_impl<bool> > const, bool> >&&&, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> >)
Unexecuted instantiation: atomic.cpp:bool std::__1::__libcpp_thread_poll_with_backoff<std::__1::__libcpp_platform_wait_on_address(std::__1::__cxx_atomic_impl<long long, std::__1::__cxx_atomic_base_impl<long long> > const volatile*, long long)::$_0, std::__1::__libcpp_timed_backoff_policy>(std::__1::__libcpp_platform_wait_on_address(std::__1::__cxx_atomic_impl<long long, std::__1::__cxx_atomic_base_impl<long long> > const volatile*, long long)::$_0&&, std::__1::__libcpp_timed_backoff_policy&&, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> >)
714
715
#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
716
717
class _LIBCPP_TYPE_VIS thread;
718
class _LIBCPP_TYPE_VIS __thread_id;
719
720
namespace this_thread
721
{
722
723
_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
724
725
}  // this_thread
726
727
template<> struct hash<__thread_id>;
728
729
class _LIBCPP_TEMPLATE_VIS __thread_id
730
{
731
    // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
732
    // NULL is the no-thread value on Darwin.  Someone needs to check
733
    // on other platforms.  We assume 0 works everywhere for now.
734
    __libcpp_thread_id __id_;
735
736
public:
737
    _LIBCPP_INLINE_VISIBILITY
738
0
    __thread_id() _NOEXCEPT : __id_(0) {}
739
740
    friend _LIBCPP_INLINE_VISIBILITY
741
        bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
742
32
        { // don't pass id==0 to underlying routines
743
32
        if (__x.__id_ == 0) 
return __y.__id_ == 00
;
744
32
        if (__y.__id_ == 0) 
return false0
;
745
32
        return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
746
32
        }
747
    friend _LIBCPP_INLINE_VISIBILITY
748
        bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
749
0
        {return !(__x == __y);}
750
    friend _LIBCPP_INLINE_VISIBILITY
751
        bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
752
0
        { // id==0 is always less than any other thread_id
753
0
        if (__x.__id_ == 0) return __y.__id_ != 0;
754
0
        if (__y.__id_ == 0) return false;
755
0
        return  __libcpp_thread_id_less(__x.__id_, __y.__id_);
756
0
        }
757
    friend _LIBCPP_INLINE_VISIBILITY
758
        bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
759
0
        {return !(__y < __x);}
760
    friend _LIBCPP_INLINE_VISIBILITY
761
        bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
762
0
        {return   __y < __x ;}
763
    friend _LIBCPP_INLINE_VISIBILITY
764
        bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
765
0
        {return !(__x < __y);}
766
767
    _LIBCPP_INLINE_VISIBILITY
768
0
    void __reset() { __id_ = 0; }
769
770
    template<class _CharT, class _Traits>
771
    friend
772
    _LIBCPP_INLINE_VISIBILITY
773
    basic_ostream<_CharT, _Traits>&
774
    operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id);
775
776
private:
777
    _LIBCPP_INLINE_VISIBILITY
778
34
    __thread_id(__libcpp_thread_id __id) : __id_(__id) {}
779
780
    friend __thread_id this_thread::get_id() _NOEXCEPT;
781
    friend class _LIBCPP_TYPE_VIS thread;
782
    friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
783
};
784
785
namespace this_thread
786
{
787
788
inline _LIBCPP_INLINE_VISIBILITY
789
__thread_id
790
get_id() _NOEXCEPT
791
2
{
792
2
    return __libcpp_thread_get_current_id();
793
2
}
794
795
}  // this_thread
796
797
#endif // !_LIBCPP_HAS_NO_THREADS
798
799
_LIBCPP_END_NAMESPACE_STD
800
801
_LIBCPP_POP_MACROS
802
803
#endif // _LIBCPP_THREADING_SUPPORT