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