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 10278724Sdim#include "__config" 11278724Sdim#ifndef _LIBCPP_HAS_NO_THREADS 12278724Sdim 13227825Stheraven#include "thread" 14227825Stheraven#include "exception" 15227825Stheraven#include "vector" 16227825Stheraven#include "future" 17241903Sdim#include "limits" 18227825Stheraven#include <sys/types.h> 19249998Sdim#if !defined(_WIN32) 20278724Sdim# if !defined(__sun__) && !defined(__linux__) && !defined(_AIX) && !defined(__native_client__) 21278724Sdim# include <sys/sysctl.h> 22278724Sdim# endif // !defined(__sun__) && !defined(__linux__) && !defined(_AIX) && !defined(__native_client__) 23278724Sdim# include <unistd.h> 24241903Sdim#endif // !_WIN32 25227825Stheraven 26253159Stheraven#if defined(__NetBSD__) 27253159Stheraven#pragma weak pthread_create // Do not create libpthread dependency 28253159Stheraven#endif 29253159Stheraven#if defined(_WIN32) 30253159Stheraven#include <windows.h> 31253159Stheraven#endif 32253159Stheraven 33227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD 34227825Stheraven 35227825Stheraventhread::~thread() 36227825Stheraven{ 37227825Stheraven if (__t_ != 0) 38227825Stheraven terminate(); 39227825Stheraven} 40227825Stheraven 41227825Stheravenvoid 42227825Stheraventhread::join() 43227825Stheraven{ 44227825Stheraven int ec = pthread_join(__t_, 0); 45227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 46227825Stheraven if (ec) 47227825Stheraven throw system_error(error_code(ec, system_category()), "thread::join failed"); 48249998Sdim#else 49249998Sdim (void)ec; 50227825Stheraven#endif // _LIBCPP_NO_EXCEPTIONS 51227825Stheraven __t_ = 0; 52227825Stheraven} 53227825Stheraven 54227825Stheravenvoid 55227825Stheraventhread::detach() 56227825Stheraven{ 57227825Stheraven int ec = EINVAL; 58227825Stheraven if (__t_ != 0) 59227825Stheraven { 60227825Stheraven ec = pthread_detach(__t_); 61227825Stheraven if (ec == 0) 62227825Stheraven __t_ = 0; 63227825Stheraven } 64227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 65227825Stheraven if (ec) 66227825Stheraven throw system_error(error_code(ec, system_category()), "thread::detach failed"); 67227825Stheraven#endif // _LIBCPP_NO_EXCEPTIONS 68227825Stheraven} 69227825Stheraven 70227825Stheravenunsigned 71241903Sdimthread::hardware_concurrency() _NOEXCEPT 72227825Stheraven{ 73227825Stheraven#if defined(CTL_HW) && defined(HW_NCPU) 74232950Stheraven unsigned n; 75227825Stheraven int mib[2] = {CTL_HW, HW_NCPU}; 76227825Stheraven std::size_t s = sizeof(n); 77227825Stheraven sysctl(mib, 2, &n, &s, 0, 0); 78227825Stheraven return n; 79253159Stheraven#elif defined(_SC_NPROCESSORS_ONLN) 80241903Sdim long result = sysconf(_SC_NPROCESSORS_ONLN); 81246487Stheraven // sysconf returns -1 if the name is invalid, the option does not exist or 82246487Stheraven // does not have a definite limit. 83249998Sdim // if sysconf returns some other negative number, we have no idea 84249998Sdim // what is going on. Default to something safe. 85249998Sdim if (result < 0) 86246487Stheraven return 0; 87249998Sdim return static_cast<unsigned>(result); 88253159Stheraven#elif defined(_WIN32) 89253159Stheraven SYSTEM_INFO info; 90253159Stheraven GetSystemInfo(&info); 91253159Stheraven return info.dwNumberOfProcessors; 92227825Stheraven#else // defined(CTL_HW) && defined(HW_NCPU) 93227825Stheraven // TODO: grovel through /proc or check cpuid on x86 and similar 94227825Stheraven // instructions on other architectures. 95262801Sdim# if defined(_MSC_VER) && ! defined(__clang__) 96262801Sdim _LIBCPP_WARNING("hardware_concurrency not yet implemented") 97262801Sdim# else 98262801Sdim# warning hardware_concurrency not yet implemented 99262801Sdim# endif 100227825Stheraven return 0; // Means not computable [thread.thread.static] 101227825Stheraven#endif // defined(CTL_HW) && defined(HW_NCPU) 102227825Stheraven} 103227825Stheraven 104227825Stheravennamespace this_thread 105227825Stheraven{ 106227825Stheraven 107227825Stheravenvoid 108227825Stheravensleep_for(const chrono::nanoseconds& ns) 109227825Stheraven{ 110227825Stheraven using namespace chrono; 111241903Sdim if (ns > nanoseconds::zero()) 112227825Stheraven { 113241903Sdim seconds s = duration_cast<seconds>(ns); 114227825Stheraven timespec ts; 115241903Sdim typedef decltype(ts.tv_sec) ts_sec; 116241903Sdim _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max(); 117241903Sdim if (s.count() < ts_sec_max) 118241903Sdim { 119241903Sdim ts.tv_sec = static_cast<ts_sec>(s.count()); 120241903Sdim ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns-s).count()); 121241903Sdim } 122241903Sdim else 123241903Sdim { 124241903Sdim ts.tv_sec = ts_sec_max; 125241903Sdim ts.tv_nsec = giga::num - 1; 126241903Sdim } 127278724Sdim 128278724Sdim while (nanosleep(&ts, &ts) == -1 && errno == EINTR) 129278724Sdim ; 130227825Stheraven } 131227825Stheraven} 132227825Stheraven 133227825Stheraven} // this_thread 134227825Stheraven 135227825Stheraven__thread_specific_ptr<__thread_struct>& 136227825Stheraven__thread_local_data() 137227825Stheraven{ 138227825Stheraven static __thread_specific_ptr<__thread_struct> __p; 139227825Stheraven return __p; 140227825Stheraven} 141227825Stheraven 142227825Stheraven// __thread_struct_imp 143227825Stheraven 144227825Stheraventemplate <class T> 145227825Stheravenclass _LIBCPP_HIDDEN __hidden_allocator 146227825Stheraven{ 147227825Stheravenpublic: 148227825Stheraven typedef T value_type; 149227825Stheraven 150227825Stheraven T* allocate(size_t __n) 151227825Stheraven {return static_cast<T*>(::operator new(__n * sizeof(T)));} 152278724Sdim void deallocate(T* __p, size_t) {::operator delete(static_cast<void*>(__p));} 153227825Stheraven 154227825Stheraven size_t max_size() const {return size_t(~0) / sizeof(T);} 155227825Stheraven}; 156227825Stheraven 157227825Stheravenclass _LIBCPP_HIDDEN __thread_struct_imp 158227825Stheraven{ 159227825Stheraven typedef vector<__assoc_sub_state*, 160227825Stheraven __hidden_allocator<__assoc_sub_state*> > _AsyncStates; 161227825Stheraven typedef vector<pair<condition_variable*, mutex*>, 162227825Stheraven __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify; 163227825Stheraven 164227825Stheraven _AsyncStates async_states_; 165227825Stheraven _Notify notify_; 166227825Stheraven 167227825Stheraven __thread_struct_imp(const __thread_struct_imp&); 168227825Stheraven __thread_struct_imp& operator=(const __thread_struct_imp&); 169227825Stheravenpublic: 170227825Stheraven __thread_struct_imp() {} 171227825Stheraven ~__thread_struct_imp(); 172227825Stheraven 173227825Stheraven void notify_all_at_thread_exit(condition_variable* cv, mutex* m); 174227825Stheraven void __make_ready_at_thread_exit(__assoc_sub_state* __s); 175227825Stheraven}; 176227825Stheraven 177227825Stheraven__thread_struct_imp::~__thread_struct_imp() 178227825Stheraven{ 179227825Stheraven for (_Notify::iterator i = notify_.begin(), e = notify_.end(); 180227825Stheraven i != e; ++i) 181227825Stheraven { 182227825Stheraven i->second->unlock(); 183227825Stheraven i->first->notify_all(); 184227825Stheraven } 185227825Stheraven for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end(); 186227825Stheraven i != e; ++i) 187227825Stheraven { 188227825Stheraven (*i)->__make_ready(); 189227825Stheraven (*i)->__release_shared(); 190227825Stheraven } 191227825Stheraven} 192227825Stheraven 193227825Stheravenvoid 194227825Stheraven__thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 195227825Stheraven{ 196227825Stheraven notify_.push_back(pair<condition_variable*, mutex*>(cv, m)); 197227825Stheraven} 198227825Stheraven 199227825Stheravenvoid 200227825Stheraven__thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s) 201227825Stheraven{ 202227825Stheraven async_states_.push_back(__s); 203227825Stheraven __s->__add_shared(); 204227825Stheraven} 205227825Stheraven 206227825Stheraven// __thread_struct 207227825Stheraven 208227825Stheraven__thread_struct::__thread_struct() 209227825Stheraven : __p_(new __thread_struct_imp) 210227825Stheraven{ 211227825Stheraven} 212227825Stheraven 213227825Stheraven__thread_struct::~__thread_struct() 214227825Stheraven{ 215227825Stheraven delete __p_; 216227825Stheraven} 217227825Stheraven 218227825Stheravenvoid 219227825Stheraven__thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 220227825Stheraven{ 221227825Stheraven __p_->notify_all_at_thread_exit(cv, m); 222227825Stheraven} 223227825Stheraven 224227825Stheravenvoid 225227825Stheraven__thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s) 226227825Stheraven{ 227227825Stheraven __p_->__make_ready_at_thread_exit(__s); 228227825Stheraven} 229227825Stheraven 230227825Stheraven_LIBCPP_END_NAMESPACE_STD 231278724Sdim 232278724Sdim#endif // !_LIBCPP_HAS_NO_THREADS 233