]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - include/__threading_support
Vendor import of stripped libc++ trunk r375505, the last commit before
[FreeBSD/FreeBSD.git] / include / __threading_support
1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef _LIBCPP_THREADING_SUPPORT
11 #define _LIBCPP_THREADING_SUPPORT
12
13 #include <__config>
14 #include <chrono>
15 #include <iosfwd>
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 #endif
30
31 #if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
32     defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \
33     defined(_LIBCPP_HAS_THREAD_API_WIN32)
34 #define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
35 #else
36 #define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
37 #endif
38
39 #if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis)
40 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
41 #else
42 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
43 #endif
44
45 typedef ::timespec __libcpp_timespec_t;
46 #endif // !defined(_LIBCPP_HAS_NO_THREADS)
47
48 _LIBCPP_PUSH_MACROS
49 #include <__undef_macros>
50
51 _LIBCPP_BEGIN_NAMESPACE_STD
52
53 #if !defined(_LIBCPP_HAS_NO_THREADS)
54
55 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
56 // Mutex
57 typedef pthread_mutex_t __libcpp_mutex_t;
58 #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
59
60 typedef pthread_mutex_t __libcpp_recursive_mutex_t;
61
62 // Condition Variable
63 typedef pthread_cond_t __libcpp_condvar_t;
64 #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
65
66 // Execute once
67 typedef pthread_once_t __libcpp_exec_once_flag;
68 #define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
69
70 // Thread id
71 typedef pthread_t __libcpp_thread_id;
72
73 // Thread
74 #define _LIBCPP_NULL_THREAD 0U
75
76 typedef pthread_t __libcpp_thread_t;
77
78 // Thread Local Storage
79 typedef pthread_key_t __libcpp_tls_key;
80
81 #define _LIBCPP_TLS_DESTRUCTOR_CC
82 #elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
83 // Mutex
84 typedef void* __libcpp_mutex_t;
85 #define _LIBCPP_MUTEX_INITIALIZER 0
86
87 #if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__)
88 typedef void* __libcpp_recursive_mutex_t[6];
89 #elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__)
90 typedef void* __libcpp_recursive_mutex_t[5];
91 #else
92 # error Unsupported architecture
93 #endif
94
95 // Condition Variable
96 typedef void* __libcpp_condvar_t;
97 #define _LIBCPP_CONDVAR_INITIALIZER 0
98
99 // Execute Once
100 typedef void* __libcpp_exec_once_flag;
101 #define _LIBCPP_EXEC_ONCE_INITIALIZER 0
102
103 // Thread ID
104 typedef long __libcpp_thread_id;
105
106 // Thread
107 #define _LIBCPP_NULL_THREAD 0U
108
109 typedef void* __libcpp_thread_t;
110
111 // Thread Local Storage
112 typedef long __libcpp_tls_key;
113
114 #define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall
115 #endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
116
117 #if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
118 // Mutex
119 _LIBCPP_THREAD_ABI_VISIBILITY
120 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
121
122 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
123 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
124
125 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
126 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
127
128 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
129 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
130
131 _LIBCPP_THREAD_ABI_VISIBILITY
132 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
133
134 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
135 int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
136
137 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
138 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
139
140 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
141 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
142
143 _LIBCPP_THREAD_ABI_VISIBILITY
144 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
145
146 // Condition variable
147 _LIBCPP_THREAD_ABI_VISIBILITY
148 int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
149
150 _LIBCPP_THREAD_ABI_VISIBILITY
151 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
152
153 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
154 int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
155
156 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
157 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
158                                __libcpp_timespec_t *__ts);
159
160 _LIBCPP_THREAD_ABI_VISIBILITY
161 int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
162
163 // Execute once
164 _LIBCPP_THREAD_ABI_VISIBILITY
165 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
166                           void (*init_routine)());
167
168 // Thread id
169 _LIBCPP_THREAD_ABI_VISIBILITY
170 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
171
172 _LIBCPP_THREAD_ABI_VISIBILITY
173 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
174
175 // Thread
176 _LIBCPP_THREAD_ABI_VISIBILITY
177 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
178
179 _LIBCPP_THREAD_ABI_VISIBILITY
180 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
181                            void *__arg);
182
183 _LIBCPP_THREAD_ABI_VISIBILITY
184 __libcpp_thread_id __libcpp_thread_get_current_id();
185
186 _LIBCPP_THREAD_ABI_VISIBILITY
187 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
188
189 _LIBCPP_THREAD_ABI_VISIBILITY
190 int __libcpp_thread_join(__libcpp_thread_t *__t);
191
192 _LIBCPP_THREAD_ABI_VISIBILITY
193 int __libcpp_thread_detach(__libcpp_thread_t *__t);
194
195 _LIBCPP_THREAD_ABI_VISIBILITY
196 void __libcpp_thread_yield();
197
198 _LIBCPP_THREAD_ABI_VISIBILITY
199 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
200
201 // Thread local storage
202 _LIBCPP_THREAD_ABI_VISIBILITY
203 int __libcpp_tls_create(__libcpp_tls_key* __key,
204                         void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
205
206 _LIBCPP_THREAD_ABI_VISIBILITY
207 void *__libcpp_tls_get(__libcpp_tls_key __key);
208
209 _LIBCPP_THREAD_ABI_VISIBILITY
210 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
211
212 #endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
213
214 #if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
215      defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) && \
216     defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
217
218 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
219 {
220   pthread_mutexattr_t attr;
221   int __ec = pthread_mutexattr_init(&attr);
222   if (__ec)
223     return __ec;
224   __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
225   if (__ec) {
226     pthread_mutexattr_destroy(&attr);
227     return __ec;
228   }
229   __ec = pthread_mutex_init(__m, &attr);
230   if (__ec) {
231     pthread_mutexattr_destroy(&attr);
232     return __ec;
233   }
234   __ec = pthread_mutexattr_destroy(&attr);
235   if (__ec) {
236     pthread_mutex_destroy(__m);
237     return __ec;
238   }
239   return 0;
240 }
241
242 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
243 {
244   return pthread_mutex_lock(__m);
245 }
246
247 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
248 {
249   return pthread_mutex_trylock(__m) == 0;
250 }
251
252 int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
253 {
254   return pthread_mutex_unlock(__m);
255 }
256
257 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
258 {
259   return pthread_mutex_destroy(__m);
260 }
261
262 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
263 {
264   return pthread_mutex_lock(__m);
265 }
266
267 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
268 {
269   return pthread_mutex_trylock(__m) == 0;
270 }
271
272 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
273 {
274   return pthread_mutex_unlock(__m);
275 }
276
277 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
278 {
279   return pthread_mutex_destroy(__m);
280 }
281
282 // Condition Variable
283 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
284 {
285   return pthread_cond_signal(__cv);
286 }
287
288 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
289 {
290   return pthread_cond_broadcast(__cv);
291 }
292
293 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
294 {
295   return pthread_cond_wait(__cv, __m);
296 }
297
298 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
299                                __libcpp_timespec_t *__ts)
300 {
301   return pthread_cond_timedwait(__cv, __m, __ts);
302 }
303
304 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
305 {
306   return pthread_cond_destroy(__cv);
307 }
308
309 // Execute once
310 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
311                           void (*init_routine)()) {
312   return pthread_once(flag, init_routine);
313 }
314
315 // Thread id
316 // Returns non-zero if the thread ids are equal, otherwise 0
317 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
318 {
319   return pthread_equal(t1, t2) != 0;
320 }
321
322 // Returns non-zero if t1 < t2, otherwise 0
323 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
324 {
325   return t1 < t2;
326 }
327
328 // Thread
329 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
330   return *__t == 0;
331 }
332
333 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
334                            void *__arg)
335 {
336   return pthread_create(__t, 0, __func, __arg);
337 }
338
339 __libcpp_thread_id __libcpp_thread_get_current_id()
340 {
341   return pthread_self();
342 }
343
344 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
345 {
346   return *__t;
347 }
348
349 int __libcpp_thread_join(__libcpp_thread_t *__t)
350 {
351   return pthread_join(*__t, 0);
352 }
353
354 int __libcpp_thread_detach(__libcpp_thread_t *__t)
355 {
356   return pthread_detach(*__t);
357 }
358
359 void __libcpp_thread_yield()
360 {
361   sched_yield();
362 }
363
364 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
365 {
366    using namespace chrono;
367    seconds __s = duration_cast<seconds>(__ns);
368    __libcpp_timespec_t __ts;
369    typedef decltype(__ts.tv_sec) ts_sec;
370    _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits<ts_sec>::max();
371
372    if (__s.count() < __ts_sec_max)
373    {
374      __ts.tv_sec = static_cast<ts_sec>(__s.count());
375      __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
376    }
377    else
378    {
379      __ts.tv_sec = __ts_sec_max;
380      __ts.tv_nsec = 999999999; // (10^9 - 1)
381    }
382
383    while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
384 }
385
386 // Thread local storage
387 int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
388 {
389   return pthread_key_create(__key, __at_exit);
390 }
391
392 void *__libcpp_tls_get(__libcpp_tls_key __key)
393 {
394   return pthread_getspecific(__key);
395 }
396
397 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
398 {
399     return pthread_setspecific(__key, __p);
400 }
401
402 #endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
403
404 class _LIBCPP_TYPE_VIS thread;
405 class _LIBCPP_TYPE_VIS __thread_id;
406
407 namespace this_thread
408 {
409
410 _LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
411
412 }  // this_thread
413
414 template<> struct hash<__thread_id>;
415
416 class _LIBCPP_TEMPLATE_VIS __thread_id
417 {
418     // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
419     // NULL is the no-thread value on Darwin.  Someone needs to check
420     // on other platforms.  We assume 0 works everywhere for now.
421     __libcpp_thread_id __id_;
422
423 public:
424     _LIBCPP_INLINE_VISIBILITY
425     __thread_id() _NOEXCEPT : __id_(0) {}
426
427     friend _LIBCPP_INLINE_VISIBILITY
428         bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
429         { // don't pass id==0 to underlying routines
430         if (__x.__id_ == 0) return __y.__id_ == 0;
431         if (__y.__id_ == 0) return false;
432         return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
433         }
434     friend _LIBCPP_INLINE_VISIBILITY
435         bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
436         {return !(__x == __y);}
437     friend _LIBCPP_INLINE_VISIBILITY
438         bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
439         { // id==0 is always less than any other thread_id
440         if (__x.__id_ == 0) return __y.__id_ != 0;
441         if (__y.__id_ == 0) return false;
442         return  __libcpp_thread_id_less(__x.__id_, __y.__id_);
443         }
444     friend _LIBCPP_INLINE_VISIBILITY
445         bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
446         {return !(__y < __x);}
447     friend _LIBCPP_INLINE_VISIBILITY
448         bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
449         {return   __y < __x ;}
450     friend _LIBCPP_INLINE_VISIBILITY
451         bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
452         {return !(__x < __y);}
453
454     _LIBCPP_INLINE_VISIBILITY
455     void __reset() { __id_ = 0; }
456     
457     template<class _CharT, class _Traits>
458     friend
459     _LIBCPP_INLINE_VISIBILITY
460     basic_ostream<_CharT, _Traits>&
461     operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id);
462
463 private:
464     _LIBCPP_INLINE_VISIBILITY
465     __thread_id(__libcpp_thread_id __id) : __id_(__id) {}
466
467     friend __thread_id this_thread::get_id() _NOEXCEPT;
468     friend class _LIBCPP_TYPE_VIS thread;
469     friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
470 };
471
472 namespace this_thread
473 {
474
475 inline _LIBCPP_INLINE_VISIBILITY
476 __thread_id
477 get_id() _NOEXCEPT
478 {
479     return __libcpp_thread_get_current_id();
480 }
481
482 }  // this_thread
483
484 #endif // !_LIBCPP_HAS_NO_THREADS
485
486 _LIBCPP_END_NAMESPACE_STD
487
488 _LIBCPP_POP_MACROS
489
490 #endif // _LIBCPP_THREADING_SUPPORT