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