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