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
19 #if __has_include(<unistd.h>)
20 # include <unistd.h> // for sysconf
23 #if defined(__NetBSD__)
24 #pragma weak pthread_create // Do not create libpthread dependency
27 #if defined(_LIBCPP_WIN32API)
31 #if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
32 #pragma comment(lib, "pthread")
35 _LIBCPP_BEGIN_NAMESPACE_STD
39 if (!__libcpp_thread_isnull(&__t_
))
47 if (!__libcpp_thread_isnull(&__t_
))
49 ec
= __libcpp_thread_join(&__t_
);
51 __t_
= _LIBCPP_NULL_THREAD
;
55 __throw_system_error(ec
, "thread::join failed");
62 if (!__libcpp_thread_isnull(&__t_
))
64 ec
= __libcpp_thread_detach(&__t_
);
66 __t_
= _LIBCPP_NULL_THREAD
;
70 __throw_system_error(ec
, "thread::detach failed");
74 thread::hardware_concurrency() noexcept
76 #if defined(_SC_NPROCESSORS_ONLN)
77 long result
= sysconf(_SC_NPROCESSORS_ONLN
);
78 // sysconf returns -1 if the name is invalid, the option does not exist or
79 // does not have a definite limit.
80 // if sysconf returns some other negative number, we have no idea
81 // what is going on. Default to something safe.
84 return static_cast<unsigned>(result
);
85 #elif defined(_LIBCPP_WIN32API)
88 return info
.dwNumberOfProcessors
;
89 #else // defined(CTL_HW) && defined(HW_NCPU)
90 // TODO: grovel through /proc or check cpuid on x86 and similar
91 // instructions on other architectures.
92 # if defined(_LIBCPP_WARNING)
93 _LIBCPP_WARNING("hardware_concurrency not yet implemented")
95 # warning hardware_concurrency not yet implemented
97 return 0; // Means not computable [thread.thread.static]
98 #endif // defined(CTL_HW) && defined(HW_NCPU)
101 namespace this_thread
105 sleep_for(const chrono::nanoseconds
& ns
)
107 if (ns
> chrono::nanoseconds::zero())
109 __libcpp_thread_sleep_for(ns
);
115 __thread_specific_ptr
<__thread_struct
>&
116 __thread_local_data()
118 // Even though __thread_specific_ptr's destructor doesn't actually destroy
119 // anything (see comments there), we can't call it at all because threads may
120 // outlive the static variable and calling its destructor means accessing an
121 // object outside of its lifetime, which is UB.
122 alignas(__thread_specific_ptr
<__thread_struct
>) static char __b
[sizeof(__thread_specific_ptr
<__thread_struct
>)];
123 static __thread_specific_ptr
<__thread_struct
>* __p
= new (__b
) __thread_specific_ptr
<__thread_struct
>();
127 // __thread_struct_imp
130 class _LIBCPP_HIDDEN __hidden_allocator
133 typedef T value_type
;
135 T
* allocate(size_t __n
)
136 {return static_cast<T
*>(::operator new(__n
* sizeof(T
)));}
137 void deallocate(T
* __p
, size_t) {::operator delete(static_cast<void*>(__p
));}
139 size_t max_size() const {return size_t(~0) / sizeof(T
);}
142 class _LIBCPP_HIDDEN __thread_struct_imp
144 typedef vector
<__assoc_sub_state
*,
145 __hidden_allocator
<__assoc_sub_state
*> > _AsyncStates
;
146 typedef vector
<pair
<condition_variable
*, mutex
*>,
147 __hidden_allocator
<pair
<condition_variable
*, mutex
*> > > _Notify
;
149 _AsyncStates async_states_
;
152 __thread_struct_imp(const __thread_struct_imp
&);
153 __thread_struct_imp
& operator=(const __thread_struct_imp
&);
155 __thread_struct_imp() {}
156 ~__thread_struct_imp();
158 void notify_all_at_thread_exit(condition_variable
* cv
, mutex
* m
);
159 void __make_ready_at_thread_exit(__assoc_sub_state
* __s
);
162 __thread_struct_imp::~__thread_struct_imp()
164 for (_Notify::iterator i
= notify_
.begin(), e
= notify_
.end();
168 i
->first
->notify_all();
170 for (_AsyncStates::iterator i
= async_states_
.begin(), e
= async_states_
.end();
173 (*i
)->__make_ready();
174 (*i
)->__release_shared();
179 __thread_struct_imp::notify_all_at_thread_exit(condition_variable
* cv
, mutex
* m
)
181 notify_
.push_back(pair
<condition_variable
*, mutex
*>(cv
, m
));
185 __thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state
* __s
)
187 async_states_
.push_back(__s
);
193 __thread_struct::__thread_struct()
194 : __p_(new __thread_struct_imp
)
198 __thread_struct::~__thread_struct()
204 __thread_struct::notify_all_at_thread_exit(condition_variable
* cv
, mutex
* m
)
206 __p_
->notify_all_at_thread_exit(cv
, m
);
210 __thread_struct::__make_ready_at_thread_exit(__assoc_sub_state
* __s
)
212 __p_
->__make_ready_at_thread_exit(__s
);
215 _LIBCPP_END_NAMESPACE_STD
217 #endif // !_LIBCPP_HAS_NO_THREADS