1 //===------------------------- thread.cpp----------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
11 #ifndef _LIBCPP_HAS_NO_THREADS
13 #include <__thread/poll_with_backoff.h>
14 #include <__thread/timed_backoff_policy.h>
21 #if __has_include(<unistd.h>)
22 # include <unistd.h> // for sysconf
25 #if defined(__NetBSD__)
26 #pragma weak pthread_create // Do not create libpthread dependency
29 #if defined(_LIBCPP_WIN32API)
33 #if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
34 #pragma comment(lib, "pthread")
37 _LIBCPP_BEGIN_NAMESPACE_STD
41 if (!__libcpp_thread_isnull(&__t_
))
49 if (!__libcpp_thread_isnull(&__t_
))
51 ec
= __libcpp_thread_join(&__t_
);
53 __t_
= _LIBCPP_NULL_THREAD
;
57 __throw_system_error(ec
, "thread::join failed");
64 if (!__libcpp_thread_isnull(&__t_
))
66 ec
= __libcpp_thread_detach(&__t_
);
68 __t_
= _LIBCPP_NULL_THREAD
;
72 __throw_system_error(ec
, "thread::detach failed");
76 thread::hardware_concurrency() noexcept
78 #if defined(_SC_NPROCESSORS_ONLN)
79 long result
= sysconf(_SC_NPROCESSORS_ONLN
);
80 // sysconf returns -1 if the name is invalid, the option does not exist or
81 // does not have a definite limit.
82 // if sysconf returns some other negative number, we have no idea
83 // what is going on. Default to something safe.
86 return static_cast<unsigned>(result
);
87 #elif defined(_LIBCPP_WIN32API)
90 return info
.dwNumberOfProcessors
;
91 #else // defined(CTL_HW) && defined(HW_NCPU)
92 // TODO: grovel through /proc or check cpuid on x86 and similar
93 // instructions on other architectures.
94 # if defined(_LIBCPP_WARNING)
95 _LIBCPP_WARNING("hardware_concurrency not yet implemented")
97 # warning hardware_concurrency not yet implemented
99 return 0; // Means not computable [thread.thread.static]
100 #endif // defined(CTL_HW) && defined(HW_NCPU)
103 namespace this_thread
107 sleep_for(const chrono::nanoseconds
& ns
)
109 if (ns
> chrono::nanoseconds::zero())
111 __libcpp_thread_sleep_for(ns
);
117 __thread_specific_ptr
<__thread_struct
>&
118 __thread_local_data()
120 // Even though __thread_specific_ptr's destructor doesn't actually destroy
121 // anything (see comments there), we can't call it at all because threads may
122 // outlive the static variable and calling its destructor means accessing an
123 // object outside of its lifetime, which is UB.
124 alignas(__thread_specific_ptr
<__thread_struct
>) static char __b
[sizeof(__thread_specific_ptr
<__thread_struct
>)];
125 static __thread_specific_ptr
<__thread_struct
>* __p
= new (__b
) __thread_specific_ptr
<__thread_struct
>();
129 // __thread_struct_imp
132 class _LIBCPP_HIDDEN __hidden_allocator
135 typedef T value_type
;
137 T
* allocate(size_t __n
)
138 {return static_cast<T
*>(::operator new(__n
* sizeof(T
)));}
139 void deallocate(T
* __p
, size_t) {::operator delete(static_cast<void*>(__p
));}
141 size_t max_size() const {return size_t(~0) / sizeof(T
);}
144 class _LIBCPP_HIDDEN __thread_struct_imp
146 typedef vector
<__assoc_sub_state
*,
147 __hidden_allocator
<__assoc_sub_state
*> > _AsyncStates
;
148 typedef vector
<pair
<condition_variable
*, mutex
*>,
149 __hidden_allocator
<pair
<condition_variable
*, mutex
*> > > _Notify
;
151 _AsyncStates async_states_
;
154 __thread_struct_imp(const __thread_struct_imp
&);
155 __thread_struct_imp
& operator=(const __thread_struct_imp
&);
157 __thread_struct_imp() {}
158 ~__thread_struct_imp();
160 void notify_all_at_thread_exit(condition_variable
* cv
, mutex
* m
);
161 void __make_ready_at_thread_exit(__assoc_sub_state
* __s
);
164 __thread_struct_imp::~__thread_struct_imp()
166 for (_Notify::iterator i
= notify_
.begin(), e
= notify_
.end();
169 i
->first
->notify_all();
172 for (_AsyncStates::iterator i
= async_states_
.begin(), e
= async_states_
.end();
175 (*i
)->__make_ready();
176 (*i
)->__release_shared();
181 __thread_struct_imp::notify_all_at_thread_exit(condition_variable
* cv
, mutex
* m
)
183 notify_
.push_back(pair
<condition_variable
*, mutex
*>(cv
, m
));
187 __thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state
* __s
)
189 async_states_
.push_back(__s
);
195 __thread_struct::__thread_struct()
196 : __p_(new __thread_struct_imp
)
200 __thread_struct::~__thread_struct()
206 __thread_struct::notify_all_at_thread_exit(condition_variable
* cv
, mutex
* m
)
208 __p_
->notify_all_at_thread_exit(cv
, m
);
212 __thread_struct::__make_ready_at_thread_exit(__assoc_sub_state
* __s
)
214 __p_
->__make_ready_at_thread_exit(__s
);
217 _LIBCPP_END_NAMESPACE_STD
219 #endif // !_LIBCPP_HAS_NO_THREADS