| Howard Hinnant | 3e51952 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 1 | //===------------------------- thread.cpp----------------------------------===// | 
|  | 2 | // | 
| Howard Hinnant | 5b08a8a | 2010-05-11 21:36:01 +0000 | [diff] [blame] | 3 | //                     The LLVM Compiler Infrastructure | 
| Howard Hinnant | 3e51952 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 4 | // | 
| Howard Hinnant | 412dbeb | 2010-11-16 22:09:02 +0000 | [diff] [blame] | 5 | // This file is dual licensed under the MIT and the University of Illinois Open | 
|  | 6 | // Source Licenses. See LICENSE.TXT for details. | 
| Howard Hinnant | 3e51952 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 |  | 
| Jonathan Roelofs | b3fcc67 | 2014-09-05 19:45:05 +0000 | [diff] [blame] | 10 | #include "__config" | 
|  | 11 | #ifndef _LIBCPP_HAS_NO_THREADS | 
|  | 12 |  | 
| Howard Hinnant | 3e51952 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 13 | #include "thread" | 
|  | 14 | #include "exception" | 
| Howard Hinnant | 167fd10 | 2010-08-27 20:10:19 +0000 | [diff] [blame] | 15 | #include "vector" | 
|  | 16 | #include "future" | 
| Howard Hinnant | aad745a | 2012-08-30 19:14:33 +0000 | [diff] [blame] | 17 | #include "limits" | 
| Howard Hinnant | 5b00ffe | 2010-05-25 17:25:25 +0000 | [diff] [blame] | 18 | #include <sys/types.h> | 
| Ben Craig | 7d00f97 | 2016-01-29 13:53:23 +0000 | [diff] [blame] | 19 |  | 
|  | 20 | #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) | 
|  | 21 | # include <sys/param.h> | 
|  | 22 | # if defined(BSD) | 
| JF Bastien | b1ba015 | 2014-12-02 17:30:19 +0000 | [diff] [blame] | 23 | #   include <sys/sysctl.h> | 
| Ben Craig | 7d00f97 | 2016-01-29 13:53:23 +0000 | [diff] [blame] | 24 | # endif // defined(BSD) | 
|  | 25 | #endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) | 
|  | 26 |  | 
| Saleem Abdulrasool | b2826a1 | 2017-01-03 21:53:51 +0000 | [diff] [blame] | 27 | #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) | 
| JF Bastien | b1ba015 | 2014-12-02 17:30:19 +0000 | [diff] [blame] | 28 | # include <unistd.h> | 
| Saleem Abdulrasool | b2826a1 | 2017-01-03 21:53:51 +0000 | [diff] [blame] | 29 | #endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) | 
| Howard Hinnant | 3e51952 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 30 |  | 
| Joerg Sonnenberger | df6bbaa | 2013-05-17 21:16:18 +0000 | [diff] [blame] | 31 | #if defined(__NetBSD__) | 
|  | 32 | #pragma weak pthread_create // Do not create libpthread dependency | 
|  | 33 | #endif | 
| Saleem Abdulrasool | b2826a1 | 2017-01-03 21:53:51 +0000 | [diff] [blame] | 34 |  | 
|  | 35 | #if defined(_LIBCPP_WIN32API) | 
| Howard Hinnant | ca69356 | 2013-07-02 17:53:48 +0000 | [diff] [blame] | 36 | #include <windows.h> | 
| Saleem Abdulrasool | b2826a1 | 2017-01-03 21:53:51 +0000 | [diff] [blame] | 37 | #endif // defined(_LIBCPP_WIN32API) | 
| Joerg Sonnenberger | df6bbaa | 2013-05-17 21:16:18 +0000 | [diff] [blame] | 38 |  | 
| Howard Hinnant | 3e51952 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 39 | _LIBCPP_BEGIN_NAMESPACE_STD | 
|  | 40 |  | 
|  | 41 | thread::~thread() | 
|  | 42 | { | 
| Howard Hinnant | 128ba71 | 2010-05-24 17:49:41 +0000 | [diff] [blame] | 43 | if (__t_ != 0) | 
| Howard Hinnant | 3e51952 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 44 | terminate(); | 
|  | 45 | } | 
|  | 46 |  | 
|  | 47 | void | 
|  | 48 | thread::join() | 
|  | 49 | { | 
| Asiri Rathnayake | 1f077f6 | 2016-06-03 08:45:26 +0000 | [diff] [blame] | 50 | int ec = EINVAL; | 
|  | 51 | if (__t_ != 0) | 
|  | 52 | { | 
|  | 53 | ec = __libcpp_thread_join(&__t_); | 
|  | 54 | if (ec == 0) | 
|  | 55 | __t_ = 0; | 
|  | 56 | } | 
| Marshall Clow | d437fa5 | 2016-08-25 15:09:01 +0000 | [diff] [blame] | 57 |  | 
| Howard Hinnant | 3e51952 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 58 | if (ec) | 
| Marshall Clow | d437fa5 | 2016-08-25 15:09:01 +0000 | [diff] [blame] | 59 | __throw_system_error(ec, "thread::join failed"); | 
| Howard Hinnant | 3e51952 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 60 | } | 
|  | 61 |  | 
|  | 62 | void | 
|  | 63 | thread::detach() | 
|  | 64 | { | 
|  | 65 | int ec = EINVAL; | 
|  | 66 | if (__t_ != 0) | 
|  | 67 | { | 
| Asiri Rathnayake | c7e4239 | 2016-05-06 14:06:29 +0000 | [diff] [blame] | 68 | ec = __libcpp_thread_detach(&__t_); | 
| Howard Hinnant | 3e51952 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 69 | if (ec == 0) | 
|  | 70 | __t_ = 0; | 
|  | 71 | } | 
| Marshall Clow | d437fa5 | 2016-08-25 15:09:01 +0000 | [diff] [blame] | 72 |  | 
| Howard Hinnant | 3e51952 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 73 | if (ec) | 
| Marshall Clow | d437fa5 | 2016-08-25 15:09:01 +0000 | [diff] [blame] | 74 | __throw_system_error(ec, "thread::detach failed"); | 
| Howard Hinnant | 3e51952 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 75 | } | 
|  | 76 |  | 
|  | 77 | unsigned | 
| Howard Hinnant | 36101a5b | 2012-07-21 16:50:47 +0000 | [diff] [blame] | 78 | thread::hardware_concurrency() _NOEXCEPT | 
| Howard Hinnant | 3e51952 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 79 | { | 
| Howard Hinnant | 128ba71 | 2010-05-24 17:49:41 +0000 | [diff] [blame] | 80 | #if defined(CTL_HW) && defined(HW_NCPU) | 
| Howard Hinnant | c206366 | 2011-12-01 20:21:04 +0000 | [diff] [blame] | 81 | unsigned n; | 
| Howard Hinnant | 3e51952 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 82 | int mib[2] = {CTL_HW, HW_NCPU}; | 
|  | 83 | std::size_t s = sizeof(n); | 
|  | 84 | sysctl(mib, 2, &n, &s, 0, 0); | 
|  | 85 | return n; | 
| Howard Hinnant | 8bd1771 | 2013-06-30 00:14:43 +0000 | [diff] [blame] | 86 | #elif defined(_SC_NPROCESSORS_ONLN) | 
| Howard Hinnant | d3673eb | 2012-08-02 18:17:49 +0000 | [diff] [blame] | 87 | long result = sysconf(_SC_NPROCESSORS_ONLN); | 
| Howard Hinnant | 6b0101a | 2012-12-27 23:24:31 +0000 | [diff] [blame] | 88 | // sysconf returns -1 if the name is invalid, the option does not exist or | 
|  | 89 | // does not have a definite limit. | 
| Marshall Clow | 0749262 | 2013-02-07 18:48:09 +0000 | [diff] [blame] | 90 | // if sysconf returns some other negative number, we have no idea | 
|  | 91 | // what is going on. Default to something safe. | 
|  | 92 | if (result < 0) | 
| Howard Hinnant | 6b0101a | 2012-12-27 23:24:31 +0000 | [diff] [blame] | 93 | return 0; | 
| Marshall Clow | 63f700e | 2013-02-07 17:37:58 +0000 | [diff] [blame] | 94 | return static_cast<unsigned>(result); | 
| Saleem Abdulrasool | b2826a1 | 2017-01-03 21:53:51 +0000 | [diff] [blame] | 95 | #elif defined(_LIBCPP_WIN32API) | 
| Howard Hinnant | ca69356 | 2013-07-02 17:53:48 +0000 | [diff] [blame] | 96 | SYSTEM_INFO info; | 
|  | 97 | GetSystemInfo(&info); | 
|  | 98 | return info.dwNumberOfProcessors; | 
| Howard Hinnant | 940e211 | 2010-08-22 00:03:27 +0000 | [diff] [blame] | 99 | #else  // defined(CTL_HW) && defined(HW_NCPU) | 
| Howard Hinnant | 128ba71 | 2010-05-24 17:49:41 +0000 | [diff] [blame] | 100 | // TODO: grovel through /proc or check cpuid on x86 and similar | 
|  | 101 | // instructions on other architectures. | 
| Howard Hinnant | 80b84d4 | 2013-10-04 21:14:44 +0000 | [diff] [blame] | 102 | #   if defined(_MSC_VER) && ! defined(__clang__) | 
|  | 103 | _LIBCPP_WARNING("hardware_concurrency not yet implemented") | 
|  | 104 | #   else | 
|  | 105 | #       warning hardware_concurrency not yet implemented | 
|  | 106 | #   endif | 
| Howard Hinnant | 128ba71 | 2010-05-24 17:49:41 +0000 | [diff] [blame] | 107 | return 0;  // Means not computable [thread.thread.static] | 
| Howard Hinnant | 940e211 | 2010-08-22 00:03:27 +0000 | [diff] [blame] | 108 | #endif  // defined(CTL_HW) && defined(HW_NCPU) | 
| Howard Hinnant | 3e51952 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 109 | } | 
|  | 110 |  | 
|  | 111 | namespace this_thread | 
|  | 112 | { | 
|  | 113 |  | 
|  | 114 | void | 
|  | 115 | sleep_for(const chrono::nanoseconds& ns) | 
|  | 116 | { | 
|  | 117 | using namespace chrono; | 
| Howard Hinnant | aad745a | 2012-08-30 19:14:33 +0000 | [diff] [blame] | 118 | if (ns > nanoseconds::zero()) | 
| Howard Hinnant | 3e51952 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 119 | { | 
| Saleem Abdulrasool | deaceef | 2017-01-07 02:48:30 +0000 | [diff] [blame] | 120 | #if defined(_LIBCPP_WIN32API) | 
|  | 121 | milliseconds ms = duration_cast<milliseconds>(ns); | 
|  | 122 | if (ns > duration_cast<nanoseconds>(ms)) | 
|  | 123 | ++ms; | 
|  | 124 | Sleep(ms.count()); | 
|  | 125 | #else | 
| Howard Hinnant | aad745a | 2012-08-30 19:14:33 +0000 | [diff] [blame] | 126 | seconds s = duration_cast<seconds>(ns); | 
| Howard Hinnant | 3e51952 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 127 | timespec ts; | 
| Howard Hinnant | aad745a | 2012-08-30 19:14:33 +0000 | [diff] [blame] | 128 | typedef decltype(ts.tv_sec) ts_sec; | 
|  | 129 | _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max(); | 
|  | 130 | if (s.count() < ts_sec_max) | 
|  | 131 | { | 
|  | 132 | ts.tv_sec = static_cast<ts_sec>(s.count()); | 
|  | 133 | ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns-s).count()); | 
|  | 134 | } | 
|  | 135 | else | 
|  | 136 | { | 
|  | 137 | ts.tv_sec = ts_sec_max; | 
|  | 138 | ts.tv_nsec = giga::num - 1; | 
|  | 139 | } | 
| David Majnemer | 58a0a70 | 2014-06-04 19:43:20 +0000 | [diff] [blame] | 140 |  | 
|  | 141 | while (nanosleep(&ts, &ts) == -1 && errno == EINTR) | 
|  | 142 | ; | 
| Saleem Abdulrasool | deaceef | 2017-01-07 02:48:30 +0000 | [diff] [blame] | 143 | #endif | 
| Howard Hinnant | 3e51952 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 144 | } | 
|  | 145 | } | 
|  | 146 |  | 
|  | 147 | }  // this_thread | 
|  | 148 |  | 
| Howard Hinnant | 10e4a48 | 2010-10-14 19:18:04 +0000 | [diff] [blame] | 149 | __thread_specific_ptr<__thread_struct>& | 
|  | 150 | __thread_local_data() | 
|  | 151 | { | 
|  | 152 | static __thread_specific_ptr<__thread_struct> __p; | 
|  | 153 | return __p; | 
|  | 154 | } | 
| Howard Hinnant | 167fd10 | 2010-08-27 20:10:19 +0000 | [diff] [blame] | 155 |  | 
|  | 156 | // __thread_struct_imp | 
|  | 157 |  | 
| Howard Hinnant | c950e77 | 2010-12-17 14:46:43 +0000 | [diff] [blame] | 158 | template <class T> | 
|  | 159 | class _LIBCPP_HIDDEN __hidden_allocator | 
| Howard Hinnant | 167fd10 | 2010-08-27 20:10:19 +0000 | [diff] [blame] | 160 | { | 
| Howard Hinnant | c950e77 | 2010-12-17 14:46:43 +0000 | [diff] [blame] | 161 | public: | 
|  | 162 | typedef T  value_type; | 
|  | 163 |  | 
|  | 164 | T* allocate(size_t __n) | 
|  | 165 | {return static_cast<T*>(::operator new(__n * sizeof(T)));} | 
| Joerg Sonnenberger | 634b9dd | 2014-01-04 17:43:00 +0000 | [diff] [blame] | 166 | void deallocate(T* __p, size_t) {::operator delete(static_cast<void*>(__p));} | 
| Howard Hinnant | c950e77 | 2010-12-17 14:46:43 +0000 | [diff] [blame] | 167 |  | 
|  | 168 | size_t max_size() const {return size_t(~0) / sizeof(T);} | 
|  | 169 | }; | 
|  | 170 |  | 
|  | 171 | class _LIBCPP_HIDDEN __thread_struct_imp | 
|  | 172 | { | 
|  | 173 | typedef vector<__assoc_sub_state*, | 
|  | 174 | __hidden_allocator<__assoc_sub_state*> > _AsyncStates; | 
|  | 175 | typedef vector<pair<condition_variable*, mutex*>, | 
|  | 176 | __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify; | 
| Howard Hinnant | b77c0c0 | 2010-09-03 21:46:37 +0000 | [diff] [blame] | 177 |  | 
| Howard Hinnant | 167fd10 | 2010-08-27 20:10:19 +0000 | [diff] [blame] | 178 | _AsyncStates async_states_; | 
| Howard Hinnant | b77c0c0 | 2010-09-03 21:46:37 +0000 | [diff] [blame] | 179 | _Notify notify_; | 
| Howard Hinnant | 167fd10 | 2010-08-27 20:10:19 +0000 | [diff] [blame] | 180 |  | 
|  | 181 | __thread_struct_imp(const __thread_struct_imp&); | 
|  | 182 | __thread_struct_imp& operator=(const __thread_struct_imp&); | 
|  | 183 | public: | 
|  | 184 | __thread_struct_imp() {} | 
|  | 185 | ~__thread_struct_imp(); | 
|  | 186 |  | 
| Howard Hinnant | b77c0c0 | 2010-09-03 21:46:37 +0000 | [diff] [blame] | 187 | void notify_all_at_thread_exit(condition_variable* cv, mutex* m); | 
| Howard Hinnant | 167fd10 | 2010-08-27 20:10:19 +0000 | [diff] [blame] | 188 | void __make_ready_at_thread_exit(__assoc_sub_state* __s); | 
|  | 189 | }; | 
|  | 190 |  | 
|  | 191 | __thread_struct_imp::~__thread_struct_imp() | 
|  | 192 | { | 
| Howard Hinnant | b77c0c0 | 2010-09-03 21:46:37 +0000 | [diff] [blame] | 193 | for (_Notify::iterator i = notify_.begin(), e = notify_.end(); | 
|  | 194 | i != e; ++i) | 
|  | 195 | { | 
|  | 196 | i->second->unlock(); | 
|  | 197 | i->first->notify_all(); | 
|  | 198 | } | 
| Howard Hinnant | 167fd10 | 2010-08-27 20:10:19 +0000 | [diff] [blame] | 199 | for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end(); | 
|  | 200 | i != e; ++i) | 
|  | 201 | { | 
|  | 202 | (*i)->__make_ready(); | 
|  | 203 | (*i)->__release_shared(); | 
|  | 204 | } | 
|  | 205 | } | 
|  | 206 |  | 
|  | 207 | void | 
| Howard Hinnant | b77c0c0 | 2010-09-03 21:46:37 +0000 | [diff] [blame] | 208 | __thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m) | 
|  | 209 | { | 
|  | 210 | notify_.push_back(pair<condition_variable*, mutex*>(cv, m)); | 
|  | 211 | } | 
|  | 212 |  | 
|  | 213 | void | 
| Howard Hinnant | 167fd10 | 2010-08-27 20:10:19 +0000 | [diff] [blame] | 214 | __thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s) | 
|  | 215 | { | 
|  | 216 | async_states_.push_back(__s); | 
|  | 217 | __s->__add_shared(); | 
|  | 218 | } | 
|  | 219 |  | 
|  | 220 | // __thread_struct | 
|  | 221 |  | 
|  | 222 | __thread_struct::__thread_struct() | 
|  | 223 | : __p_(new __thread_struct_imp) | 
|  | 224 | { | 
|  | 225 | } | 
|  | 226 |  | 
|  | 227 | __thread_struct::~__thread_struct() | 
|  | 228 | { | 
|  | 229 | delete __p_; | 
|  | 230 | } | 
|  | 231 |  | 
|  | 232 | void | 
| Howard Hinnant | b77c0c0 | 2010-09-03 21:46:37 +0000 | [diff] [blame] | 233 | __thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m) | 
|  | 234 | { | 
|  | 235 | __p_->notify_all_at_thread_exit(cv, m); | 
|  | 236 | } | 
|  | 237 |  | 
|  | 238 | void | 
| Howard Hinnant | 167fd10 | 2010-08-27 20:10:19 +0000 | [diff] [blame] | 239 | __thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s) | 
|  | 240 | { | 
|  | 241 | __p_->__make_ready_at_thread_exit(__s); | 
|  | 242 | } | 
|  | 243 |  | 
| Howard Hinnant | 3e51952 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 244 | _LIBCPP_END_NAMESPACE_STD | 
| Jonathan Roelofs | b3fcc67 | 2014-09-05 19:45:05 +0000 | [diff] [blame] | 245 |  | 
|  | 246 | #endif // !_LIBCPP_HAS_NO_THREADS |