1 //===------------------------- thread.cpp----------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "thread" 11 #include "exception" 12 #include "vector" 13 #include "future" 14 #include <sys/types.h> 15 #if !_WIN32 16 #if !__sun__ && !__linux__ 17 #include <sys/sysctl.h> 18 #else 19 #include <unistd.h> 20 #endif // !__sun__ && !__linux__ 21 #endif // !_WIN32 22 23 _LIBCPP_BEGIN_NAMESPACE_STD 24 25 thread::~thread() 26 { 27 if (__t_ != 0) 28 terminate(); 29 } 30 31 void 32 thread::join() 33 { 34 int ec = pthread_join(__t_, 0); 35 #ifndef _LIBCPP_NO_EXCEPTIONS 36 if (ec) 37 throw system_error(error_code(ec, system_category()), "thread::join failed"); 38 #endif // _LIBCPP_NO_EXCEPTIONS 39 __t_ = 0; 40 } 41 42 void 43 thread::detach() 44 { 45 int ec = EINVAL; 46 if (__t_ != 0) 47 { 48 ec = pthread_detach(__t_); 49 if (ec == 0) 50 __t_ = 0; 51 } 52 #ifndef _LIBCPP_NO_EXCEPTIONS 53 if (ec) 54 throw system_error(error_code(ec, system_category()), "thread::detach failed"); 55 #endif // _LIBCPP_NO_EXCEPTIONS 56 } 57 58 unsigned 59 thread::hardware_concurrency() _NOEXCEPT 60 { 61 #if defined(CTL_HW) && defined(HW_NCPU) 62 unsigned n; 63 int mib[2] = {CTL_HW, HW_NCPU}; 64 std::size_t s = sizeof(n); 65 sysctl(mib, 2, &n, &s, 0, 0); 66 return n; 67 #elif defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) && defined(_SC_NPROCESSORS_ONLN) 68 long result = sysconf(_SC_NPROCESSORS_ONLN); 69 if (result < 0 || result > UINT_MAX) 70 result = 0; 71 return result; 72 #else // defined(CTL_HW) && defined(HW_NCPU) 73 // TODO: grovel through /proc or check cpuid on x86 and similar 74 // instructions on other architectures. 75 return 0; // Means not computable [thread.thread.static] 76 #endif // defined(CTL_HW) && defined(HW_NCPU) 77 } 78 79 namespace this_thread 80 { 81 82 void 83 sleep_for(const chrono::nanoseconds& ns) 84 { 85 using namespace chrono; 86 if (ns >= nanoseconds::zero()) 87 { 88 timespec ts; 89 ts.tv_sec = static_cast<decltype(ts.tv_sec)>(duration_cast<seconds>(ns).count()); 90 ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns - seconds(ts.tv_sec)).count()); 91 nanosleep(&ts, 0); 92 } 93 } 94 95 } // this_thread 96 97 __thread_specific_ptr<__thread_struct>& 98 __thread_local_data() 99 { 100 static __thread_specific_ptr<__thread_struct> __p; 101 return __p; 102 } 103 104 // __thread_struct_imp 105 106 template <class T> 107 class _LIBCPP_HIDDEN __hidden_allocator 108 { 109 public: 110 typedef T value_type; 111 112 T* allocate(size_t __n) 113 {return static_cast<T*>(::operator new(__n * sizeof(T)));} 114 void deallocate(T* __p, size_t) {::operator delete((void*)__p);} 115 116 size_t max_size() const {return size_t(~0) / sizeof(T);} 117 }; 118 119 class _LIBCPP_HIDDEN __thread_struct_imp 120 { 121 typedef vector<__assoc_sub_state*, 122 __hidden_allocator<__assoc_sub_state*> > _AsyncStates; 123 typedef vector<pair<condition_variable*, mutex*>, 124 __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify; 125 126 _AsyncStates async_states_; 127 _Notify notify_; 128 129 __thread_struct_imp(const __thread_struct_imp&); 130 __thread_struct_imp& operator=(const __thread_struct_imp&); 131 public: 132 __thread_struct_imp() {} 133 ~__thread_struct_imp(); 134 135 void notify_all_at_thread_exit(condition_variable* cv, mutex* m); 136 void __make_ready_at_thread_exit(__assoc_sub_state* __s); 137 }; 138 139 __thread_struct_imp::~__thread_struct_imp() 140 { 141 for (_Notify::iterator i = notify_.begin(), e = notify_.end(); 142 i != e; ++i) 143 { 144 i->second->unlock(); 145 i->first->notify_all(); 146 } 147 for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end(); 148 i != e; ++i) 149 { 150 (*i)->__make_ready(); 151 (*i)->__release_shared(); 152 } 153 } 154 155 void 156 __thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 157 { 158 notify_.push_back(pair<condition_variable*, mutex*>(cv, m)); 159 } 160 161 void 162 __thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s) 163 { 164 async_states_.push_back(__s); 165 __s->__add_shared(); 166 } 167 168 // __thread_struct 169 170 __thread_struct::__thread_struct() 171 : __p_(new __thread_struct_imp) 172 { 173 } 174 175 __thread_struct::~__thread_struct() 176 { 177 delete __p_; 178 } 179 180 void 181 __thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 182 { 183 __p_->notify_all_at_thread_exit(cv, m); 184 } 185 186 void 187 __thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s) 188 { 189 __p_->__make_ready_at_thread_exit(__s); 190 } 191 192 _LIBCPP_END_NAMESPACE_STD 193