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