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