]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libc++/include/__threading_support
Merge ^/head r312309 through r312623.
[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 _LIBCPP_BEGIN_NAMESPACE_STD
44
45 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
46 // Mutex
47 typedef pthread_mutex_t __libcpp_mutex_t;
48 #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
49
50 typedef pthread_mutex_t __libcpp_recursive_mutex_t;
51
52 // Condition Variable
53 typedef pthread_cond_t __libcpp_condvar_t;
54 #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
55
56 // Execute once
57 typedef pthread_once_t __libcpp_exec_once_flag;
58 #define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
59
60 // Thread id
61 typedef pthread_t __libcpp_thread_id;
62
63 // Thread
64 typedef pthread_t __libcpp_thread_t;
65
66 // Thrad Local Storage
67 typedef pthread_key_t __libcpp_tls_key;
68
69 #define _LIBCPP_TLS_DESTRUCTOR_CC
70 #else
71 // Mutex
72 typedef SRWLOCK __libcpp_mutex_t;
73 #define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT
74
75 typedef CRITICAL_SECTION __libcpp_recursive_mutex_t;
76
77 // Condition Variable
78 typedef CONDITION_VARIABLE __libcpp_condvar_t;
79 #define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT
80
81 // Execute Once
82 typedef INIT_ONCE __libcpp_exec_once_flag;
83 #define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT
84
85 // Thread ID
86 typedef DWORD __libcpp_thread_id;
87
88 // Thread
89 typedef HANDLE __libcpp_thread_t;
90
91 // Thread Local Storage
92 typedef DWORD __libcpp_tls_key;
93
94 #define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI
95 #endif
96
97 // Mutex
98 _LIBCPP_THREAD_ABI_VISIBILITY
99 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
100
101 _LIBCPP_THREAD_ABI_VISIBILITY
102 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
103
104 _LIBCPP_THREAD_ABI_VISIBILITY
105 int __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
106
107 _LIBCPP_THREAD_ABI_VISIBILITY
108 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
109
110 _LIBCPP_THREAD_ABI_VISIBILITY
111 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
112
113 _LIBCPP_THREAD_ABI_VISIBILITY
114 int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
115
116 _LIBCPP_THREAD_ABI_VISIBILITY
117 int __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
118
119 _LIBCPP_THREAD_ABI_VISIBILITY
120 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
121
122 _LIBCPP_THREAD_ABI_VISIBILITY
123 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
124
125 // Condition variable
126 _LIBCPP_THREAD_ABI_VISIBILITY
127 int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
128
129 _LIBCPP_THREAD_ABI_VISIBILITY
130 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
131
132 _LIBCPP_THREAD_ABI_VISIBILITY
133 int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
134
135 _LIBCPP_THREAD_ABI_VISIBILITY
136 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
137                                timespec *__ts);
138
139 _LIBCPP_THREAD_ABI_VISIBILITY
140 int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
141
142 // Execute once
143 _LIBCPP_THREAD_ABI_VISIBILITY
144 int __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
150 mach_port_t __libcpp_thread_get_port();
151 #endif
152
153 _LIBCPP_THREAD_ABI_VISIBILITY
154 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
155
156 _LIBCPP_THREAD_ABI_VISIBILITY
157 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
158
159 // Thread
160 _LIBCPP_THREAD_ABI_VISIBILITY
161 int __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
171 int __libcpp_thread_join(__libcpp_thread_t *__t);
172
173 _LIBCPP_THREAD_ABI_VISIBILITY
174 int __libcpp_thread_detach(__libcpp_thread_t *__t);
175
176 _LIBCPP_THREAD_ABI_VISIBILITY
177 void __libcpp_thread_yield();
178
179 // Thread local storage
180 _LIBCPP_THREAD_ABI_VISIBILITY
181 int __libcpp_tls_create(__libcpp_tls_key* __key,
182                         void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
183
184 _LIBCPP_THREAD_ABI_VISIBILITY
185 void *__libcpp_tls_get(__libcpp_tls_key __key);
186
187 _LIBCPP_THREAD_ABI_VISIBILITY
188 int __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
195 int __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
219 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
220 {
221   return pthread_mutex_lock(__m);
222 }
223
224 int __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
225 {
226   return pthread_mutex_trylock(__m);
227 }
228
229 int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
230 {
231   return pthread_mutex_unlock(__m);
232 }
233
234 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
235 {
236   return pthread_mutex_destroy(__m);
237 }
238
239 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
240 {
241   return pthread_mutex_lock(__m);
242 }
243
244 int __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
245 {
246   return pthread_mutex_trylock(__m);
247 }
248
249 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
250 {
251   return pthread_mutex_unlock(__m);
252 }
253
254 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
255 {
256   return pthread_mutex_destroy(__m);
257 }
258
259 // Condition Variable
260 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
261 {
262   return pthread_cond_signal(__cv);
263 }
264
265 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
266 {
267   return pthread_cond_broadcast(__cv);
268 }
269
270 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
271 {
272   return pthread_cond_wait(__cv, __m);
273 }
274
275 int __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
281 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
282 {
283   return pthread_cond_destroy(__cv);
284 }
285
286 // Execute once
287 int __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__)
294 mach_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
300 bool __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
306 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
307 {
308   return t1 < t2;
309 }
310
311 // Thread
312 int __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
328 int __libcpp_thread_join(__libcpp_thread_t *__t)
329 {
330   return pthread_join(*__t, 0);
331 }
332
333 int __libcpp_thread_detach(__libcpp_thread_t *__t)
334 {
335   return pthread_detach(*__t);
336 }
337
338 void __libcpp_thread_yield()
339 {
340   sched_yield();
341 }
342
343 // Thread local storage
344 int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
345 {
346   return pthread_key_create(__key, __at_exit);
347 }
348
349 void *__libcpp_tls_get(__libcpp_tls_key __key)
350 {
351   return pthread_getspecific(__key);
352 }
353
354 int __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
362 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
363 {
364   InitializeCriticalSection(__m);
365   return 0;
366 }
367
368 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
369 {
370   EnterCriticalSection(__m);
371   return 0;
372 }
373
374 int __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
375 {
376   TryEnterCriticalSection(__m);
377   return 0;
378 }
379
380 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
381 {
382   LeaveCriticalSection(__m);
383   return 0;
384 }
385
386 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
387 {
388   DeleteCriticalSection(__m);
389   return 0;
390 }
391
392 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
393 {
394   AcquireSRWLockExclusive(__m);
395   return 0;
396 }
397
398 int __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
399 {
400   TryAcquireSRWLockExclusive(__m);
401   return 0;
402 }
403
404 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
405 {
406   ReleaseSRWLockExclusive(__m);
407   return 0;
408 }
409
410 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
411 {
412   static_cast<void>(__m);
413   return 0;
414 }
415
416 // Condition Variable
417 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
418 {
419   WakeConditionVariable(__cv);
420   return 0;
421 }
422
423 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
424 {
425   WakeAllConditionVariable(__cv);
426   return 0;
427 }
428
429 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
430 {
431   SleepConditionVariableSRW(__cv, __m, INFINITE, 0);
432   return 0;
433 }
434
435 int __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
453 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
454 {
455   static_cast<void>(__cv);
456   return 0;
457 }
458
459 // Execute Once
460 static 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
472 int __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
482 bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs,
483                               __libcpp_thread_id __rhs)
484 {
485   return __lhs == __rhs;
486 }
487
488 bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs)
489 {
490   return __lhs < __rhs;
491 }
492
493 // Thread
494 struct __libcpp_beginthreadex_thunk_data
495 {
496   void *(*__func)(void *);
497   void *__arg;
498 };
499
500 static 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
509 int __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
534 int __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
543 int __libcpp_thread_detach(__libcpp_thread_t *__t)
544 {
545   if (!CloseHandle(*__t))
546     return GetLastError();
547   return 0;
548 }
549
550 void __libcpp_thread_yield()
551 {
552   SwitchToThread();
553 }
554
555 // Thread Local Storage
556 int __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
565 void *__libcpp_tls_get(__libcpp_tls_key __key)
566 {
567   return FlsGetValue(__key);
568 }
569
570 int __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