xref: /llvm-project-15.0.7/libcxx/src/thread.cpp (revision 6b0101ac)
13e519524SHoward Hinnant //===------------------------- thread.cpp----------------------------------===//
23e519524SHoward Hinnant //
35b08a8a4SHoward Hinnant //                     The LLVM Compiler Infrastructure
43e519524SHoward Hinnant //
5412dbebeSHoward Hinnant // This file is dual licensed under the MIT and the University of Illinois Open
6412dbebeSHoward Hinnant // Source Licenses. See LICENSE.TXT for details.
73e519524SHoward Hinnant //
83e519524SHoward Hinnant //===----------------------------------------------------------------------===//
93e519524SHoward Hinnant 
103e519524SHoward Hinnant #include "thread"
113e519524SHoward Hinnant #include "exception"
12167fd108SHoward Hinnant #include "vector"
13167fd108SHoward Hinnant #include "future"
14aad745a0SHoward Hinnant #include "limits"
155b00ffedSHoward Hinnant #include <sys/types.h>
16d3673eb4SHoward Hinnant #if !_WIN32
17d3673eb4SHoward Hinnant #if !__sun__ && !__linux__
183e519524SHoward Hinnant #include <sys/sysctl.h>
19d3673eb4SHoward Hinnant #else
20d3673eb4SHoward Hinnant #include <unistd.h>
21d3673eb4SHoward Hinnant #endif // !__sun__ && !__linux__
22d3673eb4SHoward Hinnant #endif // !_WIN32
233e519524SHoward Hinnant 
243e519524SHoward Hinnant _LIBCPP_BEGIN_NAMESPACE_STD
253e519524SHoward Hinnant 
263e519524SHoward Hinnant thread::~thread()
273e519524SHoward Hinnant {
28128ba719SHoward Hinnant     if (__t_ != 0)
293e519524SHoward Hinnant         terminate();
303e519524SHoward Hinnant }
313e519524SHoward Hinnant 
323e519524SHoward Hinnant void
333e519524SHoward Hinnant thread::join()
343e519524SHoward Hinnant {
353e519524SHoward Hinnant     int ec = pthread_join(__t_, 0);
3654b409fdSHoward Hinnant #ifndef _LIBCPP_NO_EXCEPTIONS
373e519524SHoward Hinnant     if (ec)
383e519524SHoward Hinnant         throw system_error(error_code(ec, system_category()), "thread::join failed");
39940e211cSHoward Hinnant #endif  // _LIBCPP_NO_EXCEPTIONS
40128ba719SHoward Hinnant     __t_ = 0;
413e519524SHoward Hinnant }
423e519524SHoward Hinnant 
433e519524SHoward Hinnant void
443e519524SHoward Hinnant thread::detach()
453e519524SHoward Hinnant {
463e519524SHoward Hinnant     int ec = EINVAL;
473e519524SHoward Hinnant     if (__t_ != 0)
483e519524SHoward Hinnant     {
493e519524SHoward Hinnant         ec = pthread_detach(__t_);
503e519524SHoward Hinnant         if (ec == 0)
513e519524SHoward Hinnant             __t_ = 0;
523e519524SHoward Hinnant     }
5354b409fdSHoward Hinnant #ifndef _LIBCPP_NO_EXCEPTIONS
543e519524SHoward Hinnant     if (ec)
553e519524SHoward Hinnant         throw system_error(error_code(ec, system_category()), "thread::detach failed");
56940e211cSHoward Hinnant #endif  // _LIBCPP_NO_EXCEPTIONS
573e519524SHoward Hinnant }
583e519524SHoward Hinnant 
593e519524SHoward Hinnant unsigned
6036101a5bSHoward Hinnant thread::hardware_concurrency() _NOEXCEPT
613e519524SHoward Hinnant {
62128ba719SHoward Hinnant #if defined(CTL_HW) && defined(HW_NCPU)
63c206366fSHoward Hinnant     unsigned n;
643e519524SHoward Hinnant     int mib[2] = {CTL_HW, HW_NCPU};
653e519524SHoward Hinnant     std::size_t s = sizeof(n);
663e519524SHoward Hinnant     sysctl(mib, 2, &n, &s, 0, 0);
673e519524SHoward Hinnant     return n;
68d3673eb4SHoward Hinnant #elif defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) && defined(_SC_NPROCESSORS_ONLN)
69d3673eb4SHoward Hinnant     long result = sysconf(_SC_NPROCESSORS_ONLN);
70*6b0101acSHoward Hinnant     // sysconf returns -1 if the name is invalid, the option does not exist or
71*6b0101acSHoward Hinnant     // does not have a definite limit.
72*6b0101acSHoward Hinnant     if (result == -1)
73*6b0101acSHoward Hinnant         return 0;
74d3673eb4SHoward Hinnant     return result;
75940e211cSHoward Hinnant #else  // defined(CTL_HW) && defined(HW_NCPU)
76128ba719SHoward Hinnant     // TODO: grovel through /proc or check cpuid on x86 and similar
77128ba719SHoward Hinnant     // instructions on other architectures.
78128ba719SHoward Hinnant     return 0;  // Means not computable [thread.thread.static]
79940e211cSHoward Hinnant #endif  // defined(CTL_HW) && defined(HW_NCPU)
803e519524SHoward Hinnant }
813e519524SHoward Hinnant 
823e519524SHoward Hinnant namespace this_thread
833e519524SHoward Hinnant {
843e519524SHoward Hinnant 
853e519524SHoward Hinnant void
863e519524SHoward Hinnant sleep_for(const chrono::nanoseconds& ns)
873e519524SHoward Hinnant {
883e519524SHoward Hinnant     using namespace chrono;
89aad745a0SHoward Hinnant     if (ns > nanoseconds::zero())
903e519524SHoward Hinnant     {
91aad745a0SHoward Hinnant         seconds s = duration_cast<seconds>(ns);
923e519524SHoward Hinnant         timespec ts;
93aad745a0SHoward Hinnant         typedef decltype(ts.tv_sec) ts_sec;
94aad745a0SHoward Hinnant         _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max();
95aad745a0SHoward Hinnant         if (s.count() < ts_sec_max)
96aad745a0SHoward Hinnant         {
97aad745a0SHoward Hinnant             ts.tv_sec = static_cast<ts_sec>(s.count());
98aad745a0SHoward Hinnant             ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns-s).count());
99aad745a0SHoward Hinnant         }
100aad745a0SHoward Hinnant         else
101aad745a0SHoward Hinnant         {
102aad745a0SHoward Hinnant             ts.tv_sec = ts_sec_max;
103aad745a0SHoward Hinnant             ts.tv_nsec = giga::num - 1;
104aad745a0SHoward Hinnant         }
1053e519524SHoward Hinnant         nanosleep(&ts, 0);
1063e519524SHoward Hinnant     }
1073e519524SHoward Hinnant }
1083e519524SHoward Hinnant 
1093e519524SHoward Hinnant }  // this_thread
1103e519524SHoward Hinnant 
11110e4a48aSHoward Hinnant __thread_specific_ptr<__thread_struct>&
11210e4a48aSHoward Hinnant __thread_local_data()
11310e4a48aSHoward Hinnant {
11410e4a48aSHoward Hinnant     static __thread_specific_ptr<__thread_struct> __p;
11510e4a48aSHoward Hinnant     return __p;
11610e4a48aSHoward Hinnant }
117167fd108SHoward Hinnant 
118167fd108SHoward Hinnant // __thread_struct_imp
119167fd108SHoward Hinnant 
120c950e77dSHoward Hinnant template <class T>
121c950e77dSHoward Hinnant class _LIBCPP_HIDDEN __hidden_allocator
122167fd108SHoward Hinnant {
123c950e77dSHoward Hinnant public:
124c950e77dSHoward Hinnant     typedef T  value_type;
125c950e77dSHoward Hinnant 
126c950e77dSHoward Hinnant     T* allocate(size_t __n)
127c950e77dSHoward Hinnant         {return static_cast<T*>(::operator new(__n * sizeof(T)));}
128c950e77dSHoward Hinnant     void deallocate(T* __p, size_t) {::operator delete((void*)__p);}
129c950e77dSHoward Hinnant 
130c950e77dSHoward Hinnant     size_t max_size() const {return size_t(~0) / sizeof(T);}
131c950e77dSHoward Hinnant };
132c950e77dSHoward Hinnant 
133c950e77dSHoward Hinnant class _LIBCPP_HIDDEN __thread_struct_imp
134c950e77dSHoward Hinnant {
135c950e77dSHoward Hinnant     typedef vector<__assoc_sub_state*,
136c950e77dSHoward Hinnant                           __hidden_allocator<__assoc_sub_state*> > _AsyncStates;
137c950e77dSHoward Hinnant     typedef vector<pair<condition_variable*, mutex*>,
138c950e77dSHoward Hinnant                __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify;
139b77c0c03SHoward Hinnant 
140167fd108SHoward Hinnant     _AsyncStates async_states_;
141b77c0c03SHoward Hinnant     _Notify notify_;
142167fd108SHoward Hinnant 
143167fd108SHoward Hinnant     __thread_struct_imp(const __thread_struct_imp&);
144167fd108SHoward Hinnant     __thread_struct_imp& operator=(const __thread_struct_imp&);
145167fd108SHoward Hinnant public:
146167fd108SHoward Hinnant     __thread_struct_imp() {}
147167fd108SHoward Hinnant     ~__thread_struct_imp();
148167fd108SHoward Hinnant 
149b77c0c03SHoward Hinnant     void notify_all_at_thread_exit(condition_variable* cv, mutex* m);
150167fd108SHoward Hinnant     void __make_ready_at_thread_exit(__assoc_sub_state* __s);
151167fd108SHoward Hinnant };
152167fd108SHoward Hinnant 
153167fd108SHoward Hinnant __thread_struct_imp::~__thread_struct_imp()
154167fd108SHoward Hinnant {
155b77c0c03SHoward Hinnant     for (_Notify::iterator i = notify_.begin(), e = notify_.end();
156b77c0c03SHoward Hinnant             i != e; ++i)
157b77c0c03SHoward Hinnant     {
158b77c0c03SHoward Hinnant         i->second->unlock();
159b77c0c03SHoward Hinnant         i->first->notify_all();
160b77c0c03SHoward Hinnant     }
161167fd108SHoward Hinnant     for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end();
162167fd108SHoward Hinnant             i != e; ++i)
163167fd108SHoward Hinnant     {
164167fd108SHoward Hinnant         (*i)->__make_ready();
165167fd108SHoward Hinnant         (*i)->__release_shared();
166167fd108SHoward Hinnant     }
167167fd108SHoward Hinnant }
168167fd108SHoward Hinnant 
169167fd108SHoward Hinnant void
170b77c0c03SHoward Hinnant __thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
171b77c0c03SHoward Hinnant {
172b77c0c03SHoward Hinnant     notify_.push_back(pair<condition_variable*, mutex*>(cv, m));
173b77c0c03SHoward Hinnant }
174b77c0c03SHoward Hinnant 
175b77c0c03SHoward Hinnant void
176167fd108SHoward Hinnant __thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s)
177167fd108SHoward Hinnant {
178167fd108SHoward Hinnant     async_states_.push_back(__s);
179167fd108SHoward Hinnant     __s->__add_shared();
180167fd108SHoward Hinnant }
181167fd108SHoward Hinnant 
182167fd108SHoward Hinnant // __thread_struct
183167fd108SHoward Hinnant 
184167fd108SHoward Hinnant __thread_struct::__thread_struct()
185167fd108SHoward Hinnant     : __p_(new __thread_struct_imp)
186167fd108SHoward Hinnant {
187167fd108SHoward Hinnant }
188167fd108SHoward Hinnant 
189167fd108SHoward Hinnant __thread_struct::~__thread_struct()
190167fd108SHoward Hinnant {
191167fd108SHoward Hinnant     delete __p_;
192167fd108SHoward Hinnant }
193167fd108SHoward Hinnant 
194167fd108SHoward Hinnant void
195b77c0c03SHoward Hinnant __thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
196b77c0c03SHoward Hinnant {
197b77c0c03SHoward Hinnant     __p_->notify_all_at_thread_exit(cv, m);
198b77c0c03SHoward Hinnant }
199b77c0c03SHoward Hinnant 
200b77c0c03SHoward Hinnant void
201167fd108SHoward Hinnant __thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s)
202167fd108SHoward Hinnant {
203167fd108SHoward Hinnant     __p_->__make_ready_at_thread_exit(__s);
204167fd108SHoward Hinnant }
205167fd108SHoward Hinnant 
2063e519524SHoward Hinnant _LIBCPP_END_NAMESPACE_STD
207