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" 14243376Sdim#include "limits" 15227825Stheraven#include <sys/types.h> 16250514Sdim#if !defined(_WIN32) 17262801Sdim#if !defined(__sun__) && !defined(__linux__) && !defined(_AIX) 18227825Stheraven#include <sys/sysctl.h> 19262801Sdim#endif // !__sun__ && !__linux__ && !_AIX 20243376Sdim#include <unistd.h> 21243376Sdim#endif // !_WIN32 22227825Stheraven 23253222Sdim#if defined(__NetBSD__) 24253222Sdim#pragma weak pthread_create // Do not create libpthread dependency 25253222Sdim#endif 26253222Sdim#if defined(_WIN32) 27253222Sdim#include <windows.h> 28253222Sdim#endif 29253222Sdim 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"); 45250514Sdim#else 46250514Sdim (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 68243376Sdimthread::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; 76253222Sdim#elif defined(_SC_NPROCESSORS_ONLN) 77243376Sdim long result = sysconf(_SC_NPROCESSORS_ONLN); 78250514Sdim // sysconf returns -1 if the name is invalid, the option does not exist or 79250514Sdim // does not have a definite limit. 80250514Sdim // if sysconf returns some other negative number, we have no idea 81250514Sdim // what is going on. Default to something safe. 82250514Sdim if (result < 0) 83250514Sdim return 0; 84250514Sdim return static_cast<unsigned>(result); 85253222Sdim#elif defined(_WIN32) 86253222Sdim SYSTEM_INFO info; 87253222Sdim GetSystemInfo(&info); 88253222Sdim 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. 92262801Sdim# if defined(_MSC_VER) && ! defined(__clang__) 93262801Sdim _LIBCPP_WARNING("hardware_concurrency not yet implemented") 94262801Sdim# else 95262801Sdim# warning hardware_concurrency not yet implemented 96262801Sdim# endif 97227825Stheraven return 0; // Means not computable [thread.thread.static] 98227825Stheraven#endif // defined(CTL_HW) && defined(HW_NCPU) 99227825Stheraven} 100227825Stheraven 101227825Stheravennamespace this_thread 102227825Stheraven{ 103227825Stheraven 104227825Stheravenvoid 105227825Stheravensleep_for(const chrono::nanoseconds& ns) 106227825Stheraven{ 107227825Stheraven using namespace chrono; 108243376Sdim if (ns > nanoseconds::zero()) 109227825Stheraven { 110243376Sdim seconds s = duration_cast<seconds>(ns); 111227825Stheraven timespec ts; 112243376Sdim typedef decltype(ts.tv_sec) ts_sec; 113243376Sdim _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max(); 114243376Sdim if (s.count() < ts_sec_max) 115243376Sdim { 116243376Sdim ts.tv_sec = static_cast<ts_sec>(s.count()); 117243376Sdim ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns-s).count()); 118243376Sdim } 119243376Sdim else 120243376Sdim { 121243376Sdim ts.tv_sec = ts_sec_max; 122243376Sdim ts.tv_nsec = giga::num - 1; 123243376Sdim } 124227825Stheraven nanosleep(&ts, 0); 125227825Stheraven } 126227825Stheraven} 127227825Stheraven 128227825Stheraven} // this_thread 129227825Stheraven 130227825Stheraven__thread_specific_ptr<__thread_struct>& 131227825Stheraven__thread_local_data() 132227825Stheraven{ 133227825Stheraven static __thread_specific_ptr<__thread_struct> __p; 134227825Stheraven return __p; 135227825Stheraven} 136227825Stheraven 137227825Stheraven// __thread_struct_imp 138227825Stheraven 139227825Stheraventemplate <class T> 140227825Stheravenclass _LIBCPP_HIDDEN __hidden_allocator 141227825Stheraven{ 142227825Stheravenpublic: 143227825Stheraven typedef T value_type; 144227825Stheraven 145227825Stheraven T* allocate(size_t __n) 146227825Stheraven {return static_cast<T*>(::operator new(__n * sizeof(T)));} 147227825Stheraven void deallocate(T* __p, size_t) {::operator delete((void*)__p);} 148227825Stheraven 149227825Stheraven size_t max_size() const {return size_t(~0) / sizeof(T);} 150227825Stheraven}; 151227825Stheraven 152227825Stheravenclass _LIBCPP_HIDDEN __thread_struct_imp 153227825Stheraven{ 154227825Stheraven typedef vector<__assoc_sub_state*, 155227825Stheraven __hidden_allocator<__assoc_sub_state*> > _AsyncStates; 156227825Stheraven typedef vector<pair<condition_variable*, mutex*>, 157227825Stheraven __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify; 158227825Stheraven 159227825Stheraven _AsyncStates async_states_; 160227825Stheraven _Notify notify_; 161227825Stheraven 162227825Stheraven __thread_struct_imp(const __thread_struct_imp&); 163227825Stheraven __thread_struct_imp& operator=(const __thread_struct_imp&); 164227825Stheravenpublic: 165227825Stheraven __thread_struct_imp() {} 166227825Stheraven ~__thread_struct_imp(); 167227825Stheraven 168227825Stheraven void notify_all_at_thread_exit(condition_variable* cv, mutex* m); 169227825Stheraven void __make_ready_at_thread_exit(__assoc_sub_state* __s); 170227825Stheraven}; 171227825Stheraven 172227825Stheraven__thread_struct_imp::~__thread_struct_imp() 173227825Stheraven{ 174227825Stheraven for (_Notify::iterator i = notify_.begin(), e = notify_.end(); 175227825Stheraven i != e; ++i) 176227825Stheraven { 177227825Stheraven i->second->unlock(); 178227825Stheraven i->first->notify_all(); 179227825Stheraven } 180227825Stheraven for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end(); 181227825Stheraven i != e; ++i) 182227825Stheraven { 183227825Stheraven (*i)->__make_ready(); 184227825Stheraven (*i)->__release_shared(); 185227825Stheraven } 186227825Stheraven} 187227825Stheraven 188227825Stheravenvoid 189227825Stheraven__thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 190227825Stheraven{ 191227825Stheraven notify_.push_back(pair<condition_variable*, mutex*>(cv, m)); 192227825Stheraven} 193227825Stheraven 194227825Stheravenvoid 195227825Stheraven__thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s) 196227825Stheraven{ 197227825Stheraven async_states_.push_back(__s); 198227825Stheraven __s->__add_shared(); 199227825Stheraven} 200227825Stheraven 201227825Stheraven// __thread_struct 202227825Stheraven 203227825Stheraven__thread_struct::__thread_struct() 204227825Stheraven : __p_(new __thread_struct_imp) 205227825Stheraven{ 206227825Stheraven} 207227825Stheraven 208227825Stheraven__thread_struct::~__thread_struct() 209227825Stheraven{ 210227825Stheraven delete __p_; 211227825Stheraven} 212227825Stheraven 213227825Stheravenvoid 214227825Stheraven__thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 215227825Stheraven{ 216227825Stheraven __p_->notify_all_at_thread_exit(cv, m); 217227825Stheraven} 218227825Stheraven 219227825Stheravenvoid 220227825Stheraven__thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s) 221227825Stheraven{ 222227825Stheraven __p_->__make_ready_at_thread_exit(__s); 223227825Stheraven} 224227825Stheraven 225227825Stheraven_LIBCPP_END_NAMESPACE_STD 226