1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4//                     The LLVM Compiler Infrastructure
5//
6// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_THREADING_SUPPORT
12#define _LIBCPP_THREADING_SUPPORT
13
14#include <__config>
15#include <chrono>
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#elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
30#include <Windows.h>
31#include <process.h>
32#include <fibersapi.h>
33#endif
34
35#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
36    defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
37#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
38#else
39#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
40#endif
41
42#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis)
43#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
44#else
45#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
46#endif
47
48_LIBCPP_BEGIN_NAMESPACE_STD
49
50#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
51// Mutex
52typedef pthread_mutex_t __libcpp_mutex_t;
53#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
54
55typedef pthread_mutex_t __libcpp_recursive_mutex_t;
56
57// Condition Variable
58typedef pthread_cond_t __libcpp_condvar_t;
59#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
60
61// Execute once
62typedef pthread_once_t __libcpp_exec_once_flag;
63#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
64
65// Thread id
66typedef pthread_t __libcpp_thread_id;
67
68// Thread
69#define _LIBCPP_NULL_THREAD 0U
70
71typedef pthread_t __libcpp_thread_t;
72
73// Thrad Local Storage
74typedef pthread_key_t __libcpp_tls_key;
75
76#define _LIBCPP_TLS_DESTRUCTOR_CC
77#else
78// Mutex
79typedef SRWLOCK __libcpp_mutex_t;
80#define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT
81
82typedef CRITICAL_SECTION __libcpp_recursive_mutex_t;
83
84// Condition Variable
85typedef CONDITION_VARIABLE __libcpp_condvar_t;
86#define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT
87
88// Execute Once
89typedef INIT_ONCE __libcpp_exec_once_flag;
90#define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT
91
92// Thread ID
93typedef DWORD __libcpp_thread_id;
94
95// Thread
96#define _LIBCPP_NULL_THREAD 0U
97
98typedef HANDLE __libcpp_thread_t;
99
100// Thread Local Storage
101typedef DWORD __libcpp_tls_key;
102
103#define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI
104#endif
105
106// Mutex
107_LIBCPP_THREAD_ABI_VISIBILITY
108int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
109
110_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
111int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
112
113_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
114bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
115
116_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
117int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
118
119_LIBCPP_THREAD_ABI_VISIBILITY
120int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
121
122_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
123int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
124
125_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
126bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
127
128_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
129int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
130
131_LIBCPP_THREAD_ABI_VISIBILITY
132int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
133
134// Condition variable
135_LIBCPP_THREAD_ABI_VISIBILITY
136int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
137
138_LIBCPP_THREAD_ABI_VISIBILITY
139int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
140
141_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
142int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
143
144_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
145int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
146                               timespec *__ts);
147
148_LIBCPP_THREAD_ABI_VISIBILITY
149int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
150
151// Execute once
152_LIBCPP_THREAD_ABI_VISIBILITY
153int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
154                          void (*init_routine)(void));
155
156// Thread id
157_LIBCPP_THREAD_ABI_VISIBILITY
158bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
159
160_LIBCPP_THREAD_ABI_VISIBILITY
161bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
162
163// Thread
164_LIBCPP_THREAD_ABI_VISIBILITY
165bool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
166
167_LIBCPP_THREAD_ABI_VISIBILITY
168int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
169                           void *__arg);
170
171_LIBCPP_THREAD_ABI_VISIBILITY
172__libcpp_thread_id __libcpp_thread_get_current_id();
173
174_LIBCPP_THREAD_ABI_VISIBILITY
175__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
176
177_LIBCPP_THREAD_ABI_VISIBILITY
178int __libcpp_thread_join(__libcpp_thread_t *__t);
179
180_LIBCPP_THREAD_ABI_VISIBILITY
181int __libcpp_thread_detach(__libcpp_thread_t *__t);
182
183_LIBCPP_THREAD_ABI_VISIBILITY
184void __libcpp_thread_yield();
185
186_LIBCPP_THREAD_ABI_VISIBILITY
187void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
188
189// Thread local storage
190_LIBCPP_THREAD_ABI_VISIBILITY
191int __libcpp_tls_create(__libcpp_tls_key* __key,
192                        void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
193
194_LIBCPP_THREAD_ABI_VISIBILITY
195void *__libcpp_tls_get(__libcpp_tls_key __key);
196
197_LIBCPP_THREAD_ABI_VISIBILITY
198int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
199
200#if !defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
201    defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
202
203#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
204
205int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
206{
207  pthread_mutexattr_t attr;
208  int __ec = pthread_mutexattr_init(&attr);
209  if (__ec)
210    return __ec;
211  __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
212  if (__ec) {
213    pthread_mutexattr_destroy(&attr);
214    return __ec;
215  }
216  __ec = pthread_mutex_init(__m, &attr);
217  if (__ec) {
218    pthread_mutexattr_destroy(&attr);
219    return __ec;
220  }
221  __ec = pthread_mutexattr_destroy(&attr);
222  if (__ec) {
223    pthread_mutex_destroy(__m);
224    return __ec;
225  }
226  return 0;
227}
228
229int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
230{
231  return pthread_mutex_lock(__m);
232}
233
234bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
235{
236  return pthread_mutex_trylock(__m) == 0;
237}
238
239int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
240{
241  return pthread_mutex_unlock(__m);
242}
243
244int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
245{
246  return pthread_mutex_destroy(__m);
247}
248
249int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
250{
251  return pthread_mutex_lock(__m);
252}
253
254bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
255{
256  return pthread_mutex_trylock(__m) == 0;
257}
258
259int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
260{
261  return pthread_mutex_unlock(__m);
262}
263
264int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
265{
266  return pthread_mutex_destroy(__m);
267}
268
269// Condition Variable
270int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
271{
272  return pthread_cond_signal(__cv);
273}
274
275int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
276{
277  return pthread_cond_broadcast(__cv);
278}
279
280int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
281{
282  return pthread_cond_wait(__cv, __m);
283}
284
285int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
286                               timespec *__ts)
287{
288  return pthread_cond_timedwait(__cv, __m, __ts);
289}
290
291int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
292{
293  return pthread_cond_destroy(__cv);
294}
295
296// Execute once
297int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
298                          void (*init_routine)(void)) {
299  return pthread_once(flag, init_routine);
300}
301
302// Thread id
303// Returns non-zero if the thread ids are equal, otherwise 0
304bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
305{
306  return pthread_equal(t1, t2) != 0;
307}
308
309// Returns non-zero if t1 < t2, otherwise 0
310bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
311{
312  return t1 < t2;
313}
314
315// Thread
316bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
317  return *__t == 0;
318}
319
320int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
321                           void *__arg)
322{
323  return pthread_create(__t, 0, __func, __arg);
324}
325
326__libcpp_thread_id __libcpp_thread_get_current_id()
327{
328  return pthread_self();
329}
330
331__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
332{
333  return *__t;
334}
335
336int __libcpp_thread_join(__libcpp_thread_t *__t)
337{
338  return pthread_join(*__t, 0);
339}
340
341int __libcpp_thread_detach(__libcpp_thread_t *__t)
342{
343  return pthread_detach(*__t);
344}
345
346void __libcpp_thread_yield()
347{
348  sched_yield();
349}
350
351void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
352{
353   using namespace chrono;
354   seconds __s = duration_cast<seconds>(__ns);
355   timespec __ts;
356   typedef decltype(__ts.tv_sec) ts_sec;
357   _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits<ts_sec>::max();
358
359   if (__s.count() < __ts_sec_max)
360   {
361     __ts.tv_sec = static_cast<ts_sec>(__s.count());
362     __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
363   }
364   else
365   {
366     __ts.tv_sec = __ts_sec_max;
367     __ts.tv_nsec = 999999999; // (10^9 - 1)
368   }
369
370   while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
371}
372
373// Thread local storage
374int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
375{
376  return pthread_key_create(__key, __at_exit);
377}
378
379void *__libcpp_tls_get(__libcpp_tls_key __key)
380{
381  return pthread_getspecific(__key);
382}
383
384int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
385{
386    return pthread_setspecific(__key, __p);
387}
388
389#elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
390
391// Mutex
392int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
393{
394  InitializeCriticalSection(__m);
395  return 0;
396}
397
398int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
399{
400  EnterCriticalSection(__m);
401  return 0;
402}
403
404bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
405{
406  return TryEnterCriticalSection(__m) != 0;
407}
408
409int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
410{
411  LeaveCriticalSection(__m);
412  return 0;
413}
414
415int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
416{
417  DeleteCriticalSection(__m);
418  return 0;
419}
420
421int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
422{
423  AcquireSRWLockExclusive(__m);
424  return 0;
425}
426
427bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
428{
429  return TryAcquireSRWLockExclusive(__m) != 0;
430}
431
432int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
433{
434  ReleaseSRWLockExclusive(__m);
435  return 0;
436}
437
438int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
439{
440  static_cast<void>(__m);
441  return 0;
442}
443
444// Condition Variable
445int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
446{
447  WakeConditionVariable(__cv);
448  return 0;
449}
450
451int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
452{
453  WakeAllConditionVariable(__cv);
454  return 0;
455}
456
457int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
458{
459  SleepConditionVariableSRW(__cv, __m, INFINITE, 0);
460  return 0;
461}
462
463int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
464                               timespec *__ts)
465{
466  using namespace _VSTD::chrono;
467
468  auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec);
469  auto abstime =
470      system_clock::time_point(duration_cast<system_clock::duration>(duration));
471  auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now());
472
473  if (!SleepConditionVariableSRW(__cv, __m,
474                                 timeout_ms.count() > 0 ? timeout_ms.count()
475                                                        : 0,
476                                 0))
477    {
478      auto __ec = GetLastError();
479      return __ec == ERROR_TIMEOUT ? ETIMEDOUT : __ec;
480    }
481  return 0;
482}
483
484int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
485{
486  static_cast<void>(__cv);
487  return 0;
488}
489
490// Execute Once
491static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK
492__libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter,
493                                      PVOID *__context)
494{
495  static_cast<void>(__init_once);
496  static_cast<void>(__context);
497
498  void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter);
499  init_routine();
500  return TRUE;
501}
502
503int __libcpp_execute_once(__libcpp_exec_once_flag *__flag,
504                          void (*__init_routine)(void))
505{
506  if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk,
507                           reinterpret_cast<void *>(__init_routine), NULL))
508    return GetLastError();
509  return 0;
510}
511
512// Thread ID
513bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs,
514                              __libcpp_thread_id __rhs)
515{
516  return __lhs == __rhs;
517}
518
519bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs)
520{
521  return __lhs < __rhs;
522}
523
524// Thread
525struct __libcpp_beginthreadex_thunk_data
526{
527  void *(*__func)(void *);
528  void *__arg;
529};
530
531static inline _LIBCPP_ALWAYS_INLINE unsigned WINAPI
532__libcpp_beginthreadex_thunk(void *__raw_data)
533{
534  auto *__data =
535      static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data);
536  auto *__func = __data->__func;
537  void *__arg = __data->__arg;
538  delete __data;
539  return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg)));
540}
541
542bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
543  return *__t == 0;
544}
545
546int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
547                           void *__arg)
548{
549  auto *__data = new __libcpp_beginthreadex_thunk_data;
550  __data->__func = __func;
551  __data->__arg = __arg;
552
553  *__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0,
554                                                 __libcpp_beginthreadex_thunk,
555                                                 __data, 0, nullptr));
556
557  if (*__t)
558    return 0;
559  return GetLastError();
560}
561
562__libcpp_thread_id __libcpp_thread_get_current_id()
563{
564  return GetCurrentThreadId();
565}
566
567__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
568{
569  return GetThreadId(*__t);
570}
571
572int __libcpp_thread_join(__libcpp_thread_t *__t)
573{
574  if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED)
575    return GetLastError();
576  if (!CloseHandle(*__t))
577    return GetLastError();
578  return 0;
579}
580
581int __libcpp_thread_detach(__libcpp_thread_t *__t)
582{
583  if (!CloseHandle(*__t))
584    return GetLastError();
585  return 0;
586}
587
588void __libcpp_thread_yield()
589{
590  SwitchToThread();
591}
592
593void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
594{
595  using namespace chrono;
596  // round-up to the nearest milisecond
597  milliseconds __ms =
598      duration_cast<milliseconds>(__ns + chrono::nanoseconds(999999));
599  // FIXME(compnerd) this should be an alertable sleep (WFSO or SleepEx)
600  Sleep(__ms.count());
601}
602
603// Thread Local Storage
604int __libcpp_tls_create(__libcpp_tls_key* __key,
605                        void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*))
606{
607  *__key = FlsAlloc(__at_exit);
608  if (*__key == FLS_OUT_OF_INDEXES)
609    return GetLastError();
610  return 0;
611}
612
613void *__libcpp_tls_get(__libcpp_tls_key __key)
614{
615  return FlsGetValue(__key);
616}
617
618int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
619{
620  if (!FlsSetValue(__key, __p))
621    return GetLastError();
622  return 0;
623}
624
625#endif // _LIBCPP_HAS_THREAD_API_PTHREAD
626
627#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
628
629_LIBCPP_END_NAMESPACE_STD
630
631#endif // !_LIBCPP_HAS_NO_THREADS
632
633#endif // _LIBCPP_THREADING_SUPPORT
634