Coverage Report

Created: 2020-07-11 14:00

/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
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
0
{
288
0
    if(__elapsed > chrono::milliseconds(128))
289
0
        __libcpp_thread_sleep_for(chrono::milliseconds(8));
290
0
    else if(__elapsed > chrono::microseconds(64))
291
0
        __libcpp_thread_sleep_for(__elapsed / 2);
292
0
    else if(__elapsed > chrono::microseconds(4))
293
0
      __libcpp_thread_yield();
294
0
    else
295
0
      ; // poll
296
0
    return false;
297
0
}
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
0
{
306
0
    auto const __start = chrono::high_resolution_clock::now();
307
0
    for(int __count = 0;;) {
308
0
      if(__f())
309
0
        return true; // _Fn completion means success
310
0
      if(__count < __libcpp_polling_count) {
311
0
        __count += 1;
312
0
        continue;
313
0
      }
314
0
      chrono::nanoseconds const __elapsed = chrono::high_resolution_clock::now() - __start;
315
0
      if(__max_elapsed != chrono::nanoseconds::zero() && __max_elapsed < __elapsed)
316
0
          return false; // timeout failure
317
0
      if(__bf(__elapsed))
318
0
        return false; // _BFn completion means failure
319
0
    }
320
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> >)
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
0
{
330
0
  using namespace chrono;
331
0
  seconds __s = duration_cast<seconds>(__ns);
332
0
  __libcpp_timespec_t __ts;
333
0
  typedef decltype(__ts.tv_sec) __ts_sec;
334
0
  const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max();
335
0
336
0
  if (__s.count() < __ts_sec_max)
337
0
  {
338
0
    __ts.tv_sec = static_cast<__ts_sec>(__s.count());
339
0
    __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
340
0
  }
341
0
  else
342
0
  {
343
0
    __ts.tv_sec = __ts_sec_max;
344
0
    __ts.tv_nsec = 999999999; // (10^9 - 1)
345
0
  }
346
0
347
0
  return __ts;
348
0
}
349
350
}
351
352
#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
353
354
int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
355
30.9k
{
356
30.9k
  pthread_mutexattr_t attr;
357
30.9k
  int __ec = pthread_mutexattr_init(&attr);
358
30.9k
  if (__ec)
359
0
    return __ec;
360
30.9k
  __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
361
30.9k
  if (__ec) {
362
0
    pthread_mutexattr_destroy(&attr);
363
0
    return __ec;
364
0
  }
365
30.9k
  __ec = pthread_mutex_init(__m, &attr);
366
30.9k
  if (__ec) {
367
0
    pthread_mutexattr_destroy(&attr);
368
0
    return __ec;
369
0
  }
370
30.9k
  __ec = pthread_mutexattr_destroy(&attr);
371
30.9k
  if (__ec) {
372
0
    pthread_mutex_destroy(__m);
373
0
    return __ec;
374
0
  }
375
30.9k
  return 0;
376
30.9k
}
377
378
int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
379
112k
{
380
112k
  return pthread_mutex_lock(__m);
381
112k
}
382
383
bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
384
9
{
385
9
  return pthread_mutex_trylock(__m) == 0;
386
9
}
387
388
int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
389
112k
{
390
112k
  return pthread_mutex_unlock(__m);
391
112k
}
392
393
int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
394
6.73k
{
395
6.73k
  return pthread_mutex_destroy(__m);
396
6.73k
}
397
398
int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
399
731k
{
400
731k
  return pthread_mutex_lock(__m);
401
731k
}
402
403
bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
404
0
{
405
0
  return pthread_mutex_trylock(__m) == 0;
406
0
}
407
408
int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
409
731k
{
410
731k
  return pthread_mutex_unlock(__m);
411
731k
}
412
413
int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
414
26.1k
{
415
26.1k
  return pthread_mutex_destroy(__m);
416
26.1k
}
417
418
// Condition Variable
419
int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
420
117
{
421
117
  return pthread_cond_signal(__cv);
422
117
}
423
424
int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
425
258k
{
426
258k
  return pthread_cond_broadcast(__cv);
427
258k
}
428
429
int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
430
75
{
431
75
  return pthread_cond_wait(__cv, __m);
432
75
}
433
434
int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
435
                               __libcpp_timespec_t *__ts)
436
13
{
437
13
  return pthread_cond_timedwait(__cv, __m, __ts);
438
13
}
439
440
int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
441
127
{
442
127
  return pthread_cond_destroy(__cv);
443
127
}
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
0
                          void (*init_routine)()) {
480
0
  return pthread_once(flag, init_routine);
481
0
}
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
32
{
487
32
  return pthread_equal(t1, t2) != 0;
488
32
}
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
0
{
493
0
  return t1 < t2;
494
0
}
495
496
// Thread
497
99
bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
498
99
  return *__t == 0;
499
99
}
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
105k
{
509
105k
  return pthread_self();
510
105k
}
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
38
{
519
38
  return pthread_join(*__t, 0);
520
38
}
521
522
int __libcpp_thread_detach(__libcpp_thread_t *__t)
523
8
{
524
8
  return pthread_detach(*__t);
525
8
}
526
527
void __libcpp_thread_yield()
528
0
{
529
0
  sched_yield();
530
0
}
531
532
void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
533
0
{
534
0
   __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
535
0
   while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
536
0
}
537
538
// Thread local storage
539
int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
540
14
{
541
14
  return pthread_key_create(__key, __at_exit);
542
14
}
543
544
void *__libcpp_tls_get(__libcpp_tls_key __key)
545
0
{
546
0
  return pthread_getspecific(__key);
547
0
}
548
549
int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
550
60.8k
{
551
60.8k
    return pthread_setspecific(__key, __p);
552
60.8k
}
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
0
    __thread_id() _NOEXCEPT : __id_(0) {}
738
739
    friend _LIBCPP_INLINE_VISIBILITY
740
        bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
741
32
        { // don't pass id==0 to underlying routines
742
32
        if (__x.__id_ == 0) 
return __y.__id_ == 00
;
743
32
        if (__y.__id_ == 0) 
return false0
;
744
32
        return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
745
32
        }
746
    friend _LIBCPP_INLINE_VISIBILITY
747
        bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
748
0
        {return !(__x == __y);}
749
    friend _LIBCPP_INLINE_VISIBILITY
750
        bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
751
0
        { // id==0 is always less than any other thread_id
752
0
        if (__x.__id_ == 0) return __y.__id_ != 0;
753
0
        if (__y.__id_ == 0) return false;
754
0
        return  __libcpp_thread_id_less(__x.__id_, __y.__id_);
755
0
        }
756
    friend _LIBCPP_INLINE_VISIBILITY
757
        bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
758
0
        {return !(__y < __x);}
759
    friend _LIBCPP_INLINE_VISIBILITY
760
        bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
761
0
        {return   __y < __x ;}
762
    friend _LIBCPP_INLINE_VISIBILITY
763
        bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
764
0
        {return !(__x < __y);}
765
766
    _LIBCPP_INLINE_VISIBILITY
767
0
    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
34
    __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
2
{
791
2
    return __libcpp_thread_get_current_id();
792
2
}
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