thread.cpp revision 241903
1227825Stheraven//===------------------------- thread.cpp----------------------------------===// 2227825Stheraven// 3227825Stheraven// The LLVM Compiler Infrastructure 4227825Stheraven// 5227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open 6227825Stheraven// Source Licenses. See LICENSE.TXT for details. 7227825Stheraven// 8227825Stheraven//===----------------------------------------------------------------------===// 9227825Stheraven 10227825Stheraven#include "thread" 11227825Stheraven#include "exception" 12227825Stheraven#include "vector" 13227825Stheraven#include "future" 14241903Sdim#include "limits" 15227825Stheraven#include <sys/types.h> 16241903Sdim#if !_WIN32 17241903Sdim#if !__sun__ && !__linux__ 18227825Stheraven#include <sys/sysctl.h> 19241903Sdim#else 20241903Sdim#include <unistd.h> 21241903Sdim#endif // !__sun__ && !__linux__ 22241903Sdim#endif // !_WIN32 23227825Stheraven 24227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD 25227825Stheraven 26227825Stheraventhread::~thread() 27227825Stheraven{ 28227825Stheraven if (__t_ != 0) 29227825Stheraven terminate(); 30227825Stheraven} 31227825Stheraven 32227825Stheravenvoid 33227825Stheraventhread::join() 34227825Stheraven{ 35227825Stheraven int ec = pthread_join(__t_, 0); 36227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 37227825Stheraven if (ec) 38227825Stheraven throw system_error(error_code(ec, system_category()), "thread::join failed"); 39227825Stheraven#endif // _LIBCPP_NO_EXCEPTIONS 40227825Stheraven __t_ = 0; 41227825Stheraven} 42227825Stheraven 43227825Stheravenvoid 44227825Stheraventhread::detach() 45227825Stheraven{ 46227825Stheraven int ec = EINVAL; 47227825Stheraven if (__t_ != 0) 48227825Stheraven { 49227825Stheraven ec = pthread_detach(__t_); 50227825Stheraven if (ec == 0) 51227825Stheraven __t_ = 0; 52227825Stheraven } 53227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 54227825Stheraven if (ec) 55227825Stheraven throw system_error(error_code(ec, system_category()), "thread::detach failed"); 56227825Stheraven#endif // _LIBCPP_NO_EXCEPTIONS 57227825Stheraven} 58227825Stheraven 59227825Stheravenunsigned 60241903Sdimthread::hardware_concurrency() _NOEXCEPT 61227825Stheraven{ 62227825Stheraven#if defined(CTL_HW) && defined(HW_NCPU) 63232950Stheraven unsigned n; 64227825Stheraven int mib[2] = {CTL_HW, HW_NCPU}; 65227825Stheraven std::size_t s = sizeof(n); 66227825Stheraven sysctl(mib, 2, &n, &s, 0, 0); 67227825Stheraven return n; 68241903Sdim#elif defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) && defined(_SC_NPROCESSORS_ONLN) 69241903Sdim long result = sysconf(_SC_NPROCESSORS_ONLN); 70241903Sdim if (result < 0 || result > UINT_MAX) 71241903Sdim result = 0; 72241903Sdim return result; 73227825Stheraven#else // defined(CTL_HW) && defined(HW_NCPU) 74227825Stheraven // TODO: grovel through /proc or check cpuid on x86 and similar 75227825Stheraven // instructions on other architectures. 76227825Stheraven return 0; // Means not computable [thread.thread.static] 77227825Stheraven#endif // defined(CTL_HW) && defined(HW_NCPU) 78227825Stheraven} 79227825Stheraven 80227825Stheravennamespace this_thread 81227825Stheraven{ 82227825Stheraven 83227825Stheravenvoid 84227825Stheravensleep_for(const chrono::nanoseconds& ns) 85227825Stheraven{ 86227825Stheraven using namespace chrono; 87241903Sdim if (ns > nanoseconds::zero()) 88227825Stheraven { 89241903Sdim seconds s = duration_cast<seconds>(ns); 90227825Stheraven timespec ts; 91241903Sdim typedef decltype(ts.tv_sec) ts_sec; 92241903Sdim _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max(); 93241903Sdim if (s.count() < ts_sec_max) 94241903Sdim { 95241903Sdim ts.tv_sec = static_cast<ts_sec>(s.count()); 96241903Sdim ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns-s).count()); 97241903Sdim } 98241903Sdim else 99241903Sdim { 100241903Sdim ts.tv_sec = ts_sec_max; 101241903Sdim ts.tv_nsec = giga::num - 1; 102241903Sdim } 103227825Stheraven nanosleep(&ts, 0); 104227825Stheraven } 105227825Stheraven} 106227825Stheraven 107227825Stheraven} // this_thread 108227825Stheraven 109227825Stheraven__thread_specific_ptr<__thread_struct>& 110227825Stheraven__thread_local_data() 111227825Stheraven{ 112227825Stheraven static __thread_specific_ptr<__thread_struct> __p; 113227825Stheraven return __p; 114227825Stheraven} 115227825Stheraven 116227825Stheraven// __thread_struct_imp 117227825Stheraven 118227825Stheraventemplate <class T> 119227825Stheravenclass _LIBCPP_HIDDEN __hidden_allocator 120227825Stheraven{ 121227825Stheravenpublic: 122227825Stheraven typedef T value_type; 123227825Stheraven 124227825Stheraven T* allocate(size_t __n) 125227825Stheraven {return static_cast<T*>(::operator new(__n * sizeof(T)));} 126227825Stheraven void deallocate(T* __p, size_t) {::operator delete((void*)__p);} 127227825Stheraven 128227825Stheraven size_t max_size() const {return size_t(~0) / sizeof(T);} 129227825Stheraven}; 130227825Stheraven 131227825Stheravenclass _LIBCPP_HIDDEN __thread_struct_imp 132227825Stheraven{ 133227825Stheraven typedef vector<__assoc_sub_state*, 134227825Stheraven __hidden_allocator<__assoc_sub_state*> > _AsyncStates; 135227825Stheraven typedef vector<pair<condition_variable*, mutex*>, 136227825Stheraven __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify; 137227825Stheraven 138227825Stheraven _AsyncStates async_states_; 139227825Stheraven _Notify notify_; 140227825Stheraven 141227825Stheraven __thread_struct_imp(const __thread_struct_imp&); 142227825Stheraven __thread_struct_imp& operator=(const __thread_struct_imp&); 143227825Stheravenpublic: 144227825Stheraven __thread_struct_imp() {} 145227825Stheraven ~__thread_struct_imp(); 146227825Stheraven 147227825Stheraven void notify_all_at_thread_exit(condition_variable* cv, mutex* m); 148227825Stheraven void __make_ready_at_thread_exit(__assoc_sub_state* __s); 149227825Stheraven}; 150227825Stheraven 151227825Stheraven__thread_struct_imp::~__thread_struct_imp() 152227825Stheraven{ 153227825Stheraven for (_Notify::iterator i = notify_.begin(), e = notify_.end(); 154227825Stheraven i != e; ++i) 155227825Stheraven { 156227825Stheraven i->second->unlock(); 157227825Stheraven i->first->notify_all(); 158227825Stheraven } 159227825Stheraven for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end(); 160227825Stheraven i != e; ++i) 161227825Stheraven { 162227825Stheraven (*i)->__make_ready(); 163227825Stheraven (*i)->__release_shared(); 164227825Stheraven } 165227825Stheraven} 166227825Stheraven 167227825Stheravenvoid 168227825Stheraven__thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 169227825Stheraven{ 170227825Stheraven notify_.push_back(pair<condition_variable*, mutex*>(cv, m)); 171227825Stheraven} 172227825Stheraven 173227825Stheravenvoid 174227825Stheraven__thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s) 175227825Stheraven{ 176227825Stheraven async_states_.push_back(__s); 177227825Stheraven __s->__add_shared(); 178227825Stheraven} 179227825Stheraven 180227825Stheraven// __thread_struct 181227825Stheraven 182227825Stheraven__thread_struct::__thread_struct() 183227825Stheraven : __p_(new __thread_struct_imp) 184227825Stheraven{ 185227825Stheraven} 186227825Stheraven 187227825Stheraven__thread_struct::~__thread_struct() 188227825Stheraven{ 189227825Stheraven delete __p_; 190227825Stheraven} 191227825Stheraven 192227825Stheravenvoid 193227825Stheraven__thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 194227825Stheraven{ 195227825Stheraven __p_->notify_all_at_thread_exit(cv, m); 196227825Stheraven} 197227825Stheraven 198227825Stheravenvoid 199227825Stheraven__thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s) 200227825Stheraven{ 201227825Stheraven __p_->__make_ready_at_thread_exit(__s); 202227825Stheraven} 203227825Stheraven 204227825Stheraven_LIBCPP_END_NAMESPACE_STD 205