thread.cpp revision 253159
1179055Sjfv//===------------------------- thread.cpp----------------------------------===// 2171384Sjfv// 3230775Sjfv// The LLVM Compiler Infrastructure 4171384Sjfv// 5171384Sjfv// This file is dual licensed under the MIT and the University of Illinois Open 6171384Sjfv// Source Licenses. See LICENSE.TXT for details. 7171384Sjfv// 8171384Sjfv//===----------------------------------------------------------------------===// 9171384Sjfv 10171384Sjfv#include "thread" 11171384Sjfv#include "exception" 12171384Sjfv#include "vector" 13171384Sjfv#include "future" 14171384Sjfv#include "limits" 15171384Sjfv#include <sys/types.h> 16171384Sjfv#if !defined(_WIN32) 17171384Sjfv#if !defined(__sun__) && !defined(__linux__) 18171384Sjfv#include <sys/sysctl.h> 19171384Sjfv#endif // !__sun__ && !__linux__ 20171384Sjfv#include <unistd.h> 21171384Sjfv#endif // !_WIN32 22171384Sjfv 23171384Sjfv#if defined(__NetBSD__) 24171384Sjfv#pragma weak pthread_create // Do not create libpthread dependency 25171384Sjfv#endif 26171384Sjfv#if defined(_WIN32) 27171384Sjfv#include <windows.h> 28171384Sjfv#endif 29171384Sjfv 30171384Sjfv_LIBCPP_BEGIN_NAMESPACE_STD 31171384Sjfv 32179055Sjfvthread::~thread() 33179055Sjfv{ 34171384Sjfv if (__t_ != 0) 35171384Sjfv terminate(); 36171384Sjfv} 37171384Sjfv 38171384Sjfvvoid 39171384Sjfvthread::join() 40194875Sjfv{ 41171384Sjfv int ec = pthread_join(__t_, 0); 42230775Sjfv#ifndef _LIBCPP_NO_EXCEPTIONS 43171384Sjfv if (ec) 44171384Sjfv throw system_error(error_code(ec, system_category()), "thread::join failed"); 45230775Sjfv#else 46230775Sjfv (void)ec; 47230775Sjfv#endif // _LIBCPP_NO_EXCEPTIONS 48230775Sjfv __t_ = 0; 49230775Sjfv} 50230775Sjfv 51230775Sjfvvoid 52230775Sjfvthread::detach() 53230775Sjfv{ 54230775Sjfv int ec = EINVAL; 55230775Sjfv if (__t_ != 0) 56230775Sjfv { 57230775Sjfv ec = pthread_detach(__t_); 58230775Sjfv if (ec == 0) 59230775Sjfv __t_ = 0; 60230775Sjfv } 61230775Sjfv#ifndef _LIBCPP_NO_EXCEPTIONS 62230775Sjfv if (ec) 63230775Sjfv throw system_error(error_code(ec, system_category()), "thread::detach failed"); 64230775Sjfv#endif // _LIBCPP_NO_EXCEPTIONS 65230775Sjfv} 66230775Sjfv 67230775Sjfvunsigned 68230775Sjfvthread::hardware_concurrency() _NOEXCEPT 69238149Sjfv{ 70230775Sjfv#if defined(CTL_HW) && defined(HW_NCPU) 71230775Sjfv unsigned n; 72230775Sjfv int mib[2] = {CTL_HW, HW_NCPU}; 73230775Sjfv std::size_t s = sizeof(n); 74230775Sjfv sysctl(mib, 2, &n, &s, 0, 0); 75230775Sjfv return n; 76238149Sjfv#elif defined(_SC_NPROCESSORS_ONLN) 77171384Sjfv long result = sysconf(_SC_NPROCESSORS_ONLN); 78171384Sjfv // sysconf returns -1 if the name is invalid, the option does not exist or 79230775Sjfv // does not have a definite limit. 80230775Sjfv // if sysconf returns some other negative number, we have no idea 81230775Sjfv // what is going on. Default to something safe. 82230775Sjfv if (result < 0) 83230775Sjfv return 0; 84230775Sjfv return static_cast<unsigned>(result); 85230775Sjfv#elif defined(_WIN32) 86230775Sjfv SYSTEM_INFO info; 87230775Sjfv GetSystemInfo(&info); 88230775Sjfv return info.dwNumberOfProcessors; 89230775Sjfv#else // defined(CTL_HW) && defined(HW_NCPU) 90230775Sjfv // TODO: grovel through /proc or check cpuid on x86 and similar 91230775Sjfv // instructions on other architectures. 92230775Sjfv#warning hardware_concurrency not yet implemented 93230775Sjfv return 0; // Means not computable [thread.thread.static] 94230775Sjfv#endif // defined(CTL_HW) && defined(HW_NCPU) 95171384Sjfv} 96171384Sjfv 97230775Sjfvnamespace this_thread 98230775Sjfv{ 99230775Sjfv 100230775Sjfvvoid 101230775Sjfvsleep_for(const chrono::nanoseconds& ns) 102230775Sjfv{ 103230775Sjfv using namespace chrono; 104230775Sjfv if (ns > nanoseconds::zero()) 105230775Sjfv { 106230775Sjfv seconds s = duration_cast<seconds>(ns); 107230775Sjfv timespec ts; 108230775Sjfv typedef decltype(ts.tv_sec) ts_sec; 109230775Sjfv _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max(); 110171384Sjfv if (s.count() < ts_sec_max) 111190873Sjfv { 112230775Sjfv ts.tv_sec = static_cast<ts_sec>(s.count()); 113230775Sjfv ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns-s).count()); 114190873Sjfv } 115230775Sjfv else 116230775Sjfv { 117190873Sjfv ts.tv_sec = ts_sec_max; 118190873Sjfv ts.tv_nsec = giga::num - 1; 119230775Sjfv } 120230775Sjfv nanosleep(&ts, 0); 121230775Sjfv } 122230775Sjfv} 123238149Sjfv 124190873Sjfv} // this_thread 125238149Sjfv 126171384Sjfv__thread_specific_ptr<__thread_struct>& 127230775Sjfv__thread_local_data() 128230775Sjfv{ 129230775Sjfv static __thread_specific_ptr<__thread_struct> __p; 130230775Sjfv return __p; 131230775Sjfv} 132230775Sjfv 133230775Sjfv// __thread_struct_imp 134230775Sjfv 135230775Sjfvtemplate <class T> 136230775Sjfvclass _LIBCPP_HIDDEN __hidden_allocator 137190873Sjfv{ 138190873Sjfvpublic: 139190873Sjfv typedef T value_type; 140190873Sjfv 141190873Sjfv T* allocate(size_t __n) 142230775Sjfv {return static_cast<T*>(::operator new(__n * sizeof(T)));} 143230775Sjfv void deallocate(T* __p, size_t) {::operator delete((void*)__p);} 144230775Sjfv 145230775Sjfv size_t max_size() const {return size_t(~0) / sizeof(T);} 146230775Sjfv}; 147230775Sjfv 148230775Sjfvclass _LIBCPP_HIDDEN __thread_struct_imp 149230775Sjfv{ 150230775Sjfv typedef vector<__assoc_sub_state*, 151230775Sjfv __hidden_allocator<__assoc_sub_state*> > _AsyncStates; 152230775Sjfv typedef vector<pair<condition_variable*, mutex*>, 153230775Sjfv __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify; 154230775Sjfv 155230775Sjfv _AsyncStates async_states_; 156230775Sjfv _Notify notify_; 157230775Sjfv 158171384Sjfv __thread_struct_imp(const __thread_struct_imp&); 159171384Sjfv __thread_struct_imp& operator=(const __thread_struct_imp&); 160230775Sjfvpublic: 161230775Sjfv __thread_struct_imp() {} 162230775Sjfv ~__thread_struct_imp(); 163230775Sjfv 164230775Sjfv void notify_all_at_thread_exit(condition_variable* cv, mutex* m); 165230775Sjfv void __make_ready_at_thread_exit(__assoc_sub_state* __s); 166230775Sjfv}; 167230775Sjfv 168230775Sjfv__thread_struct_imp::~__thread_struct_imp() 169230775Sjfv{ 170230775Sjfv for (_Notify::iterator i = notify_.begin(), e = notify_.end(); 171230775Sjfv i != e; ++i) 172230775Sjfv { 173171384Sjfv i->second->unlock(); 174171384Sjfv i->first->notify_all(); 175230775Sjfv } 176230775Sjfv for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end(); 177230775Sjfv i != e; ++i) 178230775Sjfv { 179230775Sjfv (*i)->__make_ready(); 180230775Sjfv (*i)->__release_shared(); 181230775Sjfv } 182230775Sjfv} 183230775Sjfv 184230775Sjfvvoid 185230775Sjfv__thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 186230775Sjfv{ 187230775Sjfv notify_.push_back(pair<condition_variable*, mutex*>(cv, m)); 188230775Sjfv} 189230775Sjfv 190230775Sjfvvoid 191230775Sjfv__thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s) 192230775Sjfv{ 193179055Sjfv async_states_.push_back(__s); 194179055Sjfv __s->__add_shared(); 195179055Sjfv} 196179055Sjfv 197179055Sjfv// __thread_struct 198179055Sjfv 199230775Sjfv__thread_struct::__thread_struct() 200230775Sjfv : __p_(new __thread_struct_imp) 201230775Sjfv{ 202179055Sjfv} 203179055Sjfv 204179055Sjfv__thread_struct::~__thread_struct() 205179055Sjfv{ 206179055Sjfv delete __p_; 207179055Sjfv} 208230775Sjfv 209230775Sjfvvoid 210230775Sjfv__thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 211230775Sjfv{ 212230775Sjfv __p_->notify_all_at_thread_exit(cv, m); 213230775Sjfv} 214230775Sjfv 215230775Sjfvvoid 216230775Sjfv__thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s) 217230775Sjfv{ 218171384Sjfv __p_->__make_ready_at_thread_exit(__s); 219171384Sjfv} 220230775Sjfv 221230775Sjfv_LIBCPP_END_NAMESPACE_STD 222230775Sjfv