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