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