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