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 #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 template <class T> 96 class _LIBCPP_HIDDEN __hidden_allocator 97 { 98 public: 99 typedef T value_type; 100 101 T* allocate(size_t __n) 102 {return static_cast<T*>(::operator new(__n * sizeof(T)));} 103 void deallocate(T* __p, size_t) {::operator delete((void*)__p);} 104 105 size_t max_size() const {return size_t(~0) / sizeof(T);} 106 }; 107 108 class _LIBCPP_HIDDEN __thread_struct_imp 109 { 110 typedef vector<__assoc_sub_state*, 111 __hidden_allocator<__assoc_sub_state*> > _AsyncStates; 112 typedef vector<pair<condition_variable*, mutex*>, 113 __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify; 114 115 _AsyncStates async_states_; 116 _Notify notify_; 117 118 __thread_struct_imp(const __thread_struct_imp&); 119 __thread_struct_imp& operator=(const __thread_struct_imp&); 120 public: 121 __thread_struct_imp() {} 122 ~__thread_struct_imp(); 123 124 void notify_all_at_thread_exit(condition_variable* cv, mutex* m); 125 void __make_ready_at_thread_exit(__assoc_sub_state* __s); 126 }; 127 128 __thread_struct_imp::~__thread_struct_imp() 129 { 130 for (_Notify::iterator i = notify_.begin(), e = notify_.end(); 131 i != e; ++i) 132 { 133 i->second->unlock(); 134 i->first->notify_all(); 135 } 136 for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end(); 137 i != e; ++i) 138 { 139 (*i)->__make_ready(); 140 (*i)->__release_shared(); 141 } 142 } 143 144 void 145 __thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 146 { 147 notify_.push_back(pair<condition_variable*, mutex*>(cv, m)); 148 } 149 150 void 151 __thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s) 152 { 153 async_states_.push_back(__s); 154 __s->__add_shared(); 155 } 156 157 // __thread_struct 158 159 __thread_struct::__thread_struct() 160 : __p_(new __thread_struct_imp) 161 { 162 } 163 164 __thread_struct::~__thread_struct() 165 { 166 delete __p_; 167 } 168 169 void 170 __thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 171 { 172 __p_->notify_all_at_thread_exit(cv, m); 173 } 174 175 void 176 __thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s) 177 { 178 __p_->__make_ready_at_thread_exit(__s); 179 } 180 181 _LIBCPP_END_NAMESPACE_STD 182