xref: /aosp_15_r20/external/libcxx/src/thread.cpp (revision 58b9f456b02922dfdb1fad8a988d5fd8765ecb80)
1*58b9f456SAndroid Build Coastguard Worker //===------------------------- thread.cpp----------------------------------===//
2*58b9f456SAndroid Build Coastguard Worker //
3*58b9f456SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*58b9f456SAndroid Build Coastguard Worker //
5*58b9f456SAndroid Build Coastguard Worker // This file is dual licensed under the MIT and the University of Illinois Open
6*58b9f456SAndroid Build Coastguard Worker // Source Licenses. See LICENSE.TXT for details.
7*58b9f456SAndroid Build Coastguard Worker //
8*58b9f456SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*58b9f456SAndroid Build Coastguard Worker 
10*58b9f456SAndroid Build Coastguard Worker #include "__config"
11*58b9f456SAndroid Build Coastguard Worker #ifndef _LIBCPP_HAS_NO_THREADS
12*58b9f456SAndroid Build Coastguard Worker 
13*58b9f456SAndroid Build Coastguard Worker #include "thread"
14*58b9f456SAndroid Build Coastguard Worker #include "exception"
15*58b9f456SAndroid Build Coastguard Worker #include "vector"
16*58b9f456SAndroid Build Coastguard Worker #include "future"
17*58b9f456SAndroid Build Coastguard Worker #include "limits"
18*58b9f456SAndroid Build Coastguard Worker #include <sys/types.h>
19*58b9f456SAndroid Build Coastguard Worker 
20*58b9f456SAndroid Build Coastguard Worker #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
21*58b9f456SAndroid Build Coastguard Worker # include <sys/param.h>
22*58b9f456SAndroid Build Coastguard Worker # if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
23*58b9f456SAndroid Build Coastguard Worker #   include <sys/sysctl.h>
24*58b9f456SAndroid Build Coastguard Worker # endif
25*58b9f456SAndroid Build Coastguard Worker #endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
26*58b9f456SAndroid Build Coastguard Worker 
27*58b9f456SAndroid Build Coastguard Worker #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__CloudABI__) || defined(__Fuchsia__)
28*58b9f456SAndroid Build Coastguard Worker # include <unistd.h>
29*58b9f456SAndroid Build Coastguard Worker #endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__CloudABI__) || defined(__Fuchsia__)
30*58b9f456SAndroid Build Coastguard Worker 
31*58b9f456SAndroid Build Coastguard Worker #if defined(__NetBSD__)
32*58b9f456SAndroid Build Coastguard Worker #pragma weak pthread_create // Do not create libpthread dependency
33*58b9f456SAndroid Build Coastguard Worker #endif
34*58b9f456SAndroid Build Coastguard Worker 
35*58b9f456SAndroid Build Coastguard Worker #if defined(_LIBCPP_WIN32API)
36*58b9f456SAndroid Build Coastguard Worker #include <windows.h>
37*58b9f456SAndroid Build Coastguard Worker #endif
38*58b9f456SAndroid Build Coastguard Worker 
39*58b9f456SAndroid Build Coastguard Worker _LIBCPP_BEGIN_NAMESPACE_STD
40*58b9f456SAndroid Build Coastguard Worker 
~thread()41*58b9f456SAndroid Build Coastguard Worker thread::~thread()
42*58b9f456SAndroid Build Coastguard Worker {
43*58b9f456SAndroid Build Coastguard Worker     if (!__libcpp_thread_isnull(&__t_))
44*58b9f456SAndroid Build Coastguard Worker         terminate();
45*58b9f456SAndroid Build Coastguard Worker }
46*58b9f456SAndroid Build Coastguard Worker 
47*58b9f456SAndroid Build Coastguard Worker void
join()48*58b9f456SAndroid Build Coastguard Worker thread::join()
49*58b9f456SAndroid Build Coastguard Worker {
50*58b9f456SAndroid Build Coastguard Worker     int ec = EINVAL;
51*58b9f456SAndroid Build Coastguard Worker     if (!__libcpp_thread_isnull(&__t_))
52*58b9f456SAndroid Build Coastguard Worker     {
53*58b9f456SAndroid Build Coastguard Worker         ec = __libcpp_thread_join(&__t_);
54*58b9f456SAndroid Build Coastguard Worker         if (ec == 0)
55*58b9f456SAndroid Build Coastguard Worker             __t_ = _LIBCPP_NULL_THREAD;
56*58b9f456SAndroid Build Coastguard Worker     }
57*58b9f456SAndroid Build Coastguard Worker 
58*58b9f456SAndroid Build Coastguard Worker     if (ec)
59*58b9f456SAndroid Build Coastguard Worker         __throw_system_error(ec, "thread::join failed");
60*58b9f456SAndroid Build Coastguard Worker }
61*58b9f456SAndroid Build Coastguard Worker 
62*58b9f456SAndroid Build Coastguard Worker void
detach()63*58b9f456SAndroid Build Coastguard Worker thread::detach()
64*58b9f456SAndroid Build Coastguard Worker {
65*58b9f456SAndroid Build Coastguard Worker     int ec = EINVAL;
66*58b9f456SAndroid Build Coastguard Worker     if (!__libcpp_thread_isnull(&__t_))
67*58b9f456SAndroid Build Coastguard Worker     {
68*58b9f456SAndroid Build Coastguard Worker         ec = __libcpp_thread_detach(&__t_);
69*58b9f456SAndroid Build Coastguard Worker         if (ec == 0)
70*58b9f456SAndroid Build Coastguard Worker             __t_ = _LIBCPP_NULL_THREAD;
71*58b9f456SAndroid Build Coastguard Worker     }
72*58b9f456SAndroid Build Coastguard Worker 
73*58b9f456SAndroid Build Coastguard Worker     if (ec)
74*58b9f456SAndroid Build Coastguard Worker         __throw_system_error(ec, "thread::detach failed");
75*58b9f456SAndroid Build Coastguard Worker }
76*58b9f456SAndroid Build Coastguard Worker 
77*58b9f456SAndroid Build Coastguard Worker unsigned
hardware_concurrency()78*58b9f456SAndroid Build Coastguard Worker thread::hardware_concurrency() _NOEXCEPT
79*58b9f456SAndroid Build Coastguard Worker {
80*58b9f456SAndroid Build Coastguard Worker #if defined(CTL_HW) && defined(HW_NCPU)
81*58b9f456SAndroid Build Coastguard Worker     unsigned n;
82*58b9f456SAndroid Build Coastguard Worker     int mib[2] = {CTL_HW, HW_NCPU};
83*58b9f456SAndroid Build Coastguard Worker     std::size_t s = sizeof(n);
84*58b9f456SAndroid Build Coastguard Worker     sysctl(mib, 2, &n, &s, 0, 0);
85*58b9f456SAndroid Build Coastguard Worker     return n;
86*58b9f456SAndroid Build Coastguard Worker #elif defined(_SC_NPROCESSORS_ONLN)
87*58b9f456SAndroid Build Coastguard Worker     long result = sysconf(_SC_NPROCESSORS_ONLN);
88*58b9f456SAndroid Build Coastguard Worker     // sysconf returns -1 if the name is invalid, the option does not exist or
89*58b9f456SAndroid Build Coastguard Worker     // does not have a definite limit.
90*58b9f456SAndroid Build Coastguard Worker     // if sysconf returns some other negative number, we have no idea
91*58b9f456SAndroid Build Coastguard Worker     // what is going on. Default to something safe.
92*58b9f456SAndroid Build Coastguard Worker     if (result < 0)
93*58b9f456SAndroid Build Coastguard Worker         return 0;
94*58b9f456SAndroid Build Coastguard Worker     return static_cast<unsigned>(result);
95*58b9f456SAndroid Build Coastguard Worker #elif defined(_LIBCPP_WIN32API)
96*58b9f456SAndroid Build Coastguard Worker     SYSTEM_INFO info;
97*58b9f456SAndroid Build Coastguard Worker     GetSystemInfo(&info);
98*58b9f456SAndroid Build Coastguard Worker     return info.dwNumberOfProcessors;
99*58b9f456SAndroid Build Coastguard Worker #else  // defined(CTL_HW) && defined(HW_NCPU)
100*58b9f456SAndroid Build Coastguard Worker     // TODO: grovel through /proc or check cpuid on x86 and similar
101*58b9f456SAndroid Build Coastguard Worker     // instructions on other architectures.
102*58b9f456SAndroid Build Coastguard Worker #   if defined(_LIBCPP_WARNING)
103*58b9f456SAndroid Build Coastguard Worker         _LIBCPP_WARNING("hardware_concurrency not yet implemented")
104*58b9f456SAndroid Build Coastguard Worker #   else
105*58b9f456SAndroid Build Coastguard Worker #       warning hardware_concurrency not yet implemented
106*58b9f456SAndroid Build Coastguard Worker #   endif
107*58b9f456SAndroid Build Coastguard Worker     return 0;  // Means not computable [thread.thread.static]
108*58b9f456SAndroid Build Coastguard Worker #endif  // defined(CTL_HW) && defined(HW_NCPU)
109*58b9f456SAndroid Build Coastguard Worker }
110*58b9f456SAndroid Build Coastguard Worker 
111*58b9f456SAndroid Build Coastguard Worker namespace this_thread
112*58b9f456SAndroid Build Coastguard Worker {
113*58b9f456SAndroid Build Coastguard Worker 
114*58b9f456SAndroid Build Coastguard Worker void
sleep_for(const chrono::nanoseconds & ns)115*58b9f456SAndroid Build Coastguard Worker sleep_for(const chrono::nanoseconds& ns)
116*58b9f456SAndroid Build Coastguard Worker {
117*58b9f456SAndroid Build Coastguard Worker     if (ns > chrono::nanoseconds::zero())
118*58b9f456SAndroid Build Coastguard Worker     {
119*58b9f456SAndroid Build Coastguard Worker         __libcpp_thread_sleep_for(ns);
120*58b9f456SAndroid Build Coastguard Worker     }
121*58b9f456SAndroid Build Coastguard Worker }
122*58b9f456SAndroid Build Coastguard Worker 
123*58b9f456SAndroid Build Coastguard Worker }  // this_thread
124*58b9f456SAndroid Build Coastguard Worker 
125*58b9f456SAndroid Build Coastguard Worker __thread_specific_ptr<__thread_struct>&
__thread_local_data()126*58b9f456SAndroid Build Coastguard Worker __thread_local_data()
127*58b9f456SAndroid Build Coastguard Worker {
128*58b9f456SAndroid Build Coastguard Worker     static __thread_specific_ptr<__thread_struct> __p;
129*58b9f456SAndroid Build Coastguard Worker     return __p;
130*58b9f456SAndroid Build Coastguard Worker }
131*58b9f456SAndroid Build Coastguard Worker 
132*58b9f456SAndroid Build Coastguard Worker // __thread_struct_imp
133*58b9f456SAndroid Build Coastguard Worker 
134*58b9f456SAndroid Build Coastguard Worker template <class T>
135*58b9f456SAndroid Build Coastguard Worker class _LIBCPP_HIDDEN __hidden_allocator
136*58b9f456SAndroid Build Coastguard Worker {
137*58b9f456SAndroid Build Coastguard Worker public:
138*58b9f456SAndroid Build Coastguard Worker     typedef T  value_type;
139*58b9f456SAndroid Build Coastguard Worker 
allocate(size_t __n)140*58b9f456SAndroid Build Coastguard Worker     T* allocate(size_t __n)
141*58b9f456SAndroid Build Coastguard Worker         {return static_cast<T*>(::operator new(__n * sizeof(T)));}
deallocate(T * __p,size_t)142*58b9f456SAndroid Build Coastguard Worker     void deallocate(T* __p, size_t) {::operator delete(static_cast<void*>(__p));}
143*58b9f456SAndroid Build Coastguard Worker 
max_size() const144*58b9f456SAndroid Build Coastguard Worker     size_t max_size() const {return size_t(~0) / sizeof(T);}
145*58b9f456SAndroid Build Coastguard Worker };
146*58b9f456SAndroid Build Coastguard Worker 
147*58b9f456SAndroid Build Coastguard Worker class _LIBCPP_HIDDEN __thread_struct_imp
148*58b9f456SAndroid Build Coastguard Worker {
149*58b9f456SAndroid Build Coastguard Worker     typedef vector<__assoc_sub_state*,
150*58b9f456SAndroid Build Coastguard Worker                           __hidden_allocator<__assoc_sub_state*> > _AsyncStates;
151*58b9f456SAndroid Build Coastguard Worker     typedef vector<pair<condition_variable*, mutex*>,
152*58b9f456SAndroid Build Coastguard Worker                __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify;
153*58b9f456SAndroid Build Coastguard Worker 
154*58b9f456SAndroid Build Coastguard Worker     _AsyncStates async_states_;
155*58b9f456SAndroid Build Coastguard Worker     _Notify notify_;
156*58b9f456SAndroid Build Coastguard Worker 
157*58b9f456SAndroid Build Coastguard Worker     __thread_struct_imp(const __thread_struct_imp&);
158*58b9f456SAndroid Build Coastguard Worker     __thread_struct_imp& operator=(const __thread_struct_imp&);
159*58b9f456SAndroid Build Coastguard Worker public:
__thread_struct_imp()160*58b9f456SAndroid Build Coastguard Worker     __thread_struct_imp() {}
161*58b9f456SAndroid Build Coastguard Worker     ~__thread_struct_imp();
162*58b9f456SAndroid Build Coastguard Worker 
163*58b9f456SAndroid Build Coastguard Worker     void notify_all_at_thread_exit(condition_variable* cv, mutex* m);
164*58b9f456SAndroid Build Coastguard Worker     void __make_ready_at_thread_exit(__assoc_sub_state* __s);
165*58b9f456SAndroid Build Coastguard Worker };
166*58b9f456SAndroid Build Coastguard Worker 
~__thread_struct_imp()167*58b9f456SAndroid Build Coastguard Worker __thread_struct_imp::~__thread_struct_imp()
168*58b9f456SAndroid Build Coastguard Worker {
169*58b9f456SAndroid Build Coastguard Worker     for (_Notify::iterator i = notify_.begin(), e = notify_.end();
170*58b9f456SAndroid Build Coastguard Worker             i != e; ++i)
171*58b9f456SAndroid Build Coastguard Worker     {
172*58b9f456SAndroid Build Coastguard Worker         i->second->unlock();
173*58b9f456SAndroid Build Coastguard Worker         i->first->notify_all();
174*58b9f456SAndroid Build Coastguard Worker     }
175*58b9f456SAndroid Build Coastguard Worker     for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end();
176*58b9f456SAndroid Build Coastguard Worker             i != e; ++i)
177*58b9f456SAndroid Build Coastguard Worker     {
178*58b9f456SAndroid Build Coastguard Worker         (*i)->__make_ready();
179*58b9f456SAndroid Build Coastguard Worker         (*i)->__release_shared();
180*58b9f456SAndroid Build Coastguard Worker     }
181*58b9f456SAndroid Build Coastguard Worker }
182*58b9f456SAndroid Build Coastguard Worker 
183*58b9f456SAndroid Build Coastguard Worker void
notify_all_at_thread_exit(condition_variable * cv,mutex * m)184*58b9f456SAndroid Build Coastguard Worker __thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
185*58b9f456SAndroid Build Coastguard Worker {
186*58b9f456SAndroid Build Coastguard Worker     notify_.push_back(pair<condition_variable*, mutex*>(cv, m));
187*58b9f456SAndroid Build Coastguard Worker }
188*58b9f456SAndroid Build Coastguard Worker 
189*58b9f456SAndroid Build Coastguard Worker void
__make_ready_at_thread_exit(__assoc_sub_state * __s)190*58b9f456SAndroid Build Coastguard Worker __thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s)
191*58b9f456SAndroid Build Coastguard Worker {
192*58b9f456SAndroid Build Coastguard Worker     async_states_.push_back(__s);
193*58b9f456SAndroid Build Coastguard Worker     __s->__add_shared();
194*58b9f456SAndroid Build Coastguard Worker }
195*58b9f456SAndroid Build Coastguard Worker 
196*58b9f456SAndroid Build Coastguard Worker // __thread_struct
197*58b9f456SAndroid Build Coastguard Worker 
__thread_struct()198*58b9f456SAndroid Build Coastguard Worker __thread_struct::__thread_struct()
199*58b9f456SAndroid Build Coastguard Worker     : __p_(new __thread_struct_imp)
200*58b9f456SAndroid Build Coastguard Worker {
201*58b9f456SAndroid Build Coastguard Worker }
202*58b9f456SAndroid Build Coastguard Worker 
~__thread_struct()203*58b9f456SAndroid Build Coastguard Worker __thread_struct::~__thread_struct()
204*58b9f456SAndroid Build Coastguard Worker {
205*58b9f456SAndroid Build Coastguard Worker     delete __p_;
206*58b9f456SAndroid Build Coastguard Worker }
207*58b9f456SAndroid Build Coastguard Worker 
208*58b9f456SAndroid Build Coastguard Worker void
notify_all_at_thread_exit(condition_variable * cv,mutex * m)209*58b9f456SAndroid Build Coastguard Worker __thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
210*58b9f456SAndroid Build Coastguard Worker {
211*58b9f456SAndroid Build Coastguard Worker     __p_->notify_all_at_thread_exit(cv, m);
212*58b9f456SAndroid Build Coastguard Worker }
213*58b9f456SAndroid Build Coastguard Worker 
214*58b9f456SAndroid Build Coastguard Worker void
__make_ready_at_thread_exit(__assoc_sub_state * __s)215*58b9f456SAndroid Build Coastguard Worker __thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s)
216*58b9f456SAndroid Build Coastguard Worker {
217*58b9f456SAndroid Build Coastguard Worker     __p_->__make_ready_at_thread_exit(__s);
218*58b9f456SAndroid Build Coastguard Worker }
219*58b9f456SAndroid Build Coastguard Worker 
220*58b9f456SAndroid Build Coastguard Worker _LIBCPP_END_NAMESPACE_STD
221*58b9f456SAndroid Build Coastguard Worker 
222*58b9f456SAndroid Build Coastguard Worker #endif // !_LIBCPP_HAS_NO_THREADS
223