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