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> 16249998Sdim#if !defined(_WIN32) 17249998Sdim#if !defined(__sun__) && !defined(__linux__) 18227825Stheraven#include <sys/sysctl.h> 19253159Stheraven#endif // !__sun__ && !__linux__ 20241903Sdim#include <unistd.h> 21241903Sdim#endif // !_WIN32 22227825Stheraven 23253159Stheraven#if defined(__NetBSD__) 24253159Stheraven#pragma weak pthread_create // Do not create libpthread dependency 25253159Stheraven#endif 26253159Stheraven#if defined(_WIN32) 27253159Stheraven#include <windows.h> 28253159Stheraven#endif 29253159Stheraven 30227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD 31227825Stheraven 32227825Stheraventhread::~thread() 33227825Stheraven{ 34227825Stheraven if (__t_ != 0) 35227825Stheraven terminate(); 36227825Stheraven} 37227825Stheraven 38227825Stheravenvoid 39227825Stheraventhread::join() 40227825Stheraven{ 41227825Stheraven int ec = pthread_join(__t_, 0); 42227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 43227825Stheraven if (ec) 44227825Stheraven throw system_error(error_code(ec, system_category()), "thread::join failed"); 45249998Sdim#else 46249998Sdim (void)ec; 47227825Stheraven#endif // _LIBCPP_NO_EXCEPTIONS 48227825Stheraven __t_ = 0; 49227825Stheraven} 50227825Stheraven 51227825Stheravenvoid 52227825Stheraventhread::detach() 53227825Stheraven{ 54227825Stheraven int ec = EINVAL; 55227825Stheraven if (__t_ != 0) 56227825Stheraven { 57227825Stheraven ec = pthread_detach(__t_); 58227825Stheraven if (ec == 0) 59227825Stheraven __t_ = 0; 60227825Stheraven } 61227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 62227825Stheraven if (ec) 63227825Stheraven throw system_error(error_code(ec, system_category()), "thread::detach failed"); 64227825Stheraven#endif // _LIBCPP_NO_EXCEPTIONS 65227825Stheraven} 66227825Stheraven 67227825Stheravenunsigned 68241903Sdimthread::hardware_concurrency() _NOEXCEPT 69227825Stheraven{ 70227825Stheraven#if defined(CTL_HW) && defined(HW_NCPU) 71232950Stheraven unsigned n; 72227825Stheraven int mib[2] = {CTL_HW, HW_NCPU}; 73227825Stheraven std::size_t s = sizeof(n); 74227825Stheraven sysctl(mib, 2, &n, &s, 0, 0); 75227825Stheraven return n; 76253159Stheraven#elif defined(_SC_NPROCESSORS_ONLN) 77241903Sdim long result = sysconf(_SC_NPROCESSORS_ONLN); 78246487Stheraven // sysconf returns -1 if the name is invalid, the option does not exist or 79246487Stheraven // does not have a definite limit. 80249998Sdim // if sysconf returns some other negative number, we have no idea 81249998Sdim // what is going on. Default to something safe. 82249998Sdim if (result < 0) 83246487Stheraven return 0; 84249998Sdim return static_cast<unsigned>(result); 85253159Stheraven#elif defined(_WIN32) 86253159Stheraven SYSTEM_INFO info; 87253159Stheraven GetSystemInfo(&info); 88253159Stheraven return info.dwNumberOfProcessors; 89227825Stheraven#else // defined(CTL_HW) && defined(HW_NCPU) 90227825Stheraven // TODO: grovel through /proc or check cpuid on x86 and similar 91227825Stheraven // instructions on other architectures. 92253159Stheraven#warning hardware_concurrency not yet implemented 93227825Stheraven return 0; // Means not computable [thread.thread.static] 94227825Stheraven#endif // defined(CTL_HW) && defined(HW_NCPU) 95227825Stheraven} 96227825Stheraven 97227825Stheravennamespace this_thread 98227825Stheraven{ 99227825Stheraven 100227825Stheravenvoid 101227825Stheravensleep_for(const chrono::nanoseconds& ns) 102227825Stheraven{ 103227825Stheraven using namespace chrono; 104241903Sdim if (ns > nanoseconds::zero()) 105227825Stheraven { 106241903Sdim seconds s = duration_cast<seconds>(ns); 107227825Stheraven timespec ts; 108241903Sdim typedef decltype(ts.tv_sec) ts_sec; 109241903Sdim _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max(); 110241903Sdim if (s.count() < ts_sec_max) 111241903Sdim { 112241903Sdim ts.tv_sec = static_cast<ts_sec>(s.count()); 113241903Sdim ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns-s).count()); 114241903Sdim } 115241903Sdim else 116241903Sdim { 117241903Sdim ts.tv_sec = ts_sec_max; 118241903Sdim ts.tv_nsec = giga::num - 1; 119241903Sdim } 120227825Stheraven nanosleep(&ts, 0); 121227825Stheraven } 122227825Stheraven} 123227825Stheraven 124227825Stheraven} // this_thread 125227825Stheraven 126227825Stheraven__thread_specific_ptr<__thread_struct>& 127227825Stheraven__thread_local_data() 128227825Stheraven{ 129227825Stheraven static __thread_specific_ptr<__thread_struct> __p; 130227825Stheraven return __p; 131227825Stheraven} 132227825Stheraven 133227825Stheraven// __thread_struct_imp 134227825Stheraven 135227825Stheraventemplate <class T> 136227825Stheravenclass _LIBCPP_HIDDEN __hidden_allocator 137227825Stheraven{ 138227825Stheravenpublic: 139227825Stheraven typedef T value_type; 140227825Stheraven 141227825Stheraven T* allocate(size_t __n) 142227825Stheraven {return static_cast<T*>(::operator new(__n * sizeof(T)));} 143227825Stheraven void deallocate(T* __p, size_t) {::operator delete((void*)__p);} 144227825Stheraven 145227825Stheraven size_t max_size() const {return size_t(~0) / sizeof(T);} 146227825Stheraven}; 147227825Stheraven 148227825Stheravenclass _LIBCPP_HIDDEN __thread_struct_imp 149227825Stheraven{ 150227825Stheraven typedef vector<__assoc_sub_state*, 151227825Stheraven __hidden_allocator<__assoc_sub_state*> > _AsyncStates; 152227825Stheraven typedef vector<pair<condition_variable*, mutex*>, 153227825Stheraven __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify; 154227825Stheraven 155227825Stheraven _AsyncStates async_states_; 156227825Stheraven _Notify notify_; 157227825Stheraven 158227825Stheraven __thread_struct_imp(const __thread_struct_imp&); 159227825Stheraven __thread_struct_imp& operator=(const __thread_struct_imp&); 160227825Stheravenpublic: 161227825Stheraven __thread_struct_imp() {} 162227825Stheraven ~__thread_struct_imp(); 163227825Stheraven 164227825Stheraven void notify_all_at_thread_exit(condition_variable* cv, mutex* m); 165227825Stheraven void __make_ready_at_thread_exit(__assoc_sub_state* __s); 166227825Stheraven}; 167227825Stheraven 168227825Stheraven__thread_struct_imp::~__thread_struct_imp() 169227825Stheraven{ 170227825Stheraven for (_Notify::iterator i = notify_.begin(), e = notify_.end(); 171227825Stheraven i != e; ++i) 172227825Stheraven { 173227825Stheraven i->second->unlock(); 174227825Stheraven i->first->notify_all(); 175227825Stheraven } 176227825Stheraven for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end(); 177227825Stheraven i != e; ++i) 178227825Stheraven { 179227825Stheraven (*i)->__make_ready(); 180227825Stheraven (*i)->__release_shared(); 181227825Stheraven } 182227825Stheraven} 183227825Stheraven 184227825Stheravenvoid 185227825Stheraven__thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 186227825Stheraven{ 187227825Stheraven notify_.push_back(pair<condition_variable*, mutex*>(cv, m)); 188227825Stheraven} 189227825Stheraven 190227825Stheravenvoid 191227825Stheraven__thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s) 192227825Stheraven{ 193227825Stheraven async_states_.push_back(__s); 194227825Stheraven __s->__add_shared(); 195227825Stheraven} 196227825Stheraven 197227825Stheraven// __thread_struct 198227825Stheraven 199227825Stheraven__thread_struct::__thread_struct() 200227825Stheraven : __p_(new __thread_struct_imp) 201227825Stheraven{ 202227825Stheraven} 203227825Stheraven 204227825Stheraven__thread_struct::~__thread_struct() 205227825Stheraven{ 206227825Stheraven delete __p_; 207227825Stheraven} 208227825Stheraven 209227825Stheravenvoid 210227825Stheraven__thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 211227825Stheraven{ 212227825Stheraven __p_->notify_all_at_thread_exit(cv, m); 213227825Stheraven} 214227825Stheraven 215227825Stheravenvoid 216227825Stheraven__thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s) 217227825Stheraven{ 218227825Stheraven __p_->__make_ready_at_thread_exit(__s); 219227825Stheraven} 220227825Stheraven 221227825Stheraven_LIBCPP_END_NAMESPACE_STD 222