1 // thread -*- C++ -*- 2 3 // Copyright (C) 2008-2013 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 26 #include <thread> 27 #include <system_error> 28 #include <cerrno> 29 #include <cxxabi_forced.h> 30 31 #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) 32 33 #if defined(_GLIBCXX_USE_GET_NPROCS) 34 # include <sys/sysinfo.h> 35 # define _GLIBCXX_NPROCS get_nprocs() 36 #elif defined(_GLIBCXX_USE_PTHREADS_NUM_PROCESSORS_NP) 37 # define _GLIBCXX_NPROCS pthread_num_processors_np() 38 #elif defined(_GLIBCXX_USE_SYSCTL_HW_NCPU) 39 # include <stddef.h> 40 # include <sys/sysctl.h> 41 static inline int get_nprocs() 42 { 43 int count; 44 size_t size = sizeof(count); 45 int mib[] = { CTL_HW, HW_NCPU }; 46 if (!sysctl(mib, 2, &count, &size, NULL, 0)) 47 return count; 48 return 0; 49 } 50 # define _GLIBCXX_NPROCS get_nprocs() 51 #elif defined(_GLIBCXX_USE_SC_NPROCESSORS_ONLN) 52 # include <unistd.h> 53 # define _GLIBCXX_NPROCS sysconf(_SC_NPROCESSORS_ONLN) 54 #elif defined(_GLIBCXX_USE_SC_NPROC_ONLN) 55 # include <unistd.h> 56 # define _GLIBCXX_NPROCS sysconf(_SC_NPROC_ONLN) 57 #else 58 # define _GLIBCXX_NPROCS 0 59 #endif 60 61 #ifndef _GLIBCXX_USE_NANOSLEEP 62 # ifdef _GLIBCXX_HAVE_SLEEP 63 # include <unistd.h> 64 # elif defined(_GLIBCXX_HAVE_WIN32_SLEEP) 65 # include <windows.h> 66 # else 67 # error "No sleep function known for this target" 68 # endif 69 #endif 70 71 namespace std _GLIBCXX_VISIBILITY(default) 72 { 73 namespace 74 { 75 extern "C" void* 76 execute_native_thread_routine(void* __p) 77 { 78 thread::_Impl_base* __t = static_cast<thread::_Impl_base*>(__p); 79 thread::__shared_base_type __local; 80 __local.swap(__t->_M_this_ptr); 81 82 __try 83 { 84 __t->_M_run(); 85 } 86 __catch(const __cxxabiv1::__forced_unwind&) 87 { 88 __throw_exception_again; 89 } 90 __catch(...) 91 { 92 std::terminate(); 93 } 94 95 return 0; 96 } 97 } 98 99 _GLIBCXX_BEGIN_NAMESPACE_VERSION 100 101 void 102 thread::join() 103 { 104 int __e = EINVAL; 105 106 if (_M_id != id()) 107 __e = __gthread_join(_M_id._M_thread, 0); 108 109 if (__e) 110 __throw_system_error(__e); 111 112 _M_id = id(); 113 } 114 115 void 116 thread::detach() 117 { 118 int __e = EINVAL; 119 120 if (_M_id != id()) 121 __e = __gthread_detach(_M_id._M_thread); 122 123 if (__e) 124 __throw_system_error(__e); 125 126 _M_id = id(); 127 } 128 129 void 130 thread::_M_start_thread(__shared_base_type __b) 131 { 132 if (!__gthread_active_p()) 133 #if __EXCEPTIONS 134 throw system_error(make_error_code(errc::operation_not_permitted), 135 "Enable multithreading to use std::thread"); 136 #else 137 __throw_system_error(int(errc::operation_not_permitted)); 138 #endif 139 140 __b->_M_this_ptr = __b; 141 int __e = __gthread_create(&_M_id._M_thread, 142 &execute_native_thread_routine, __b.get()); 143 if (__e) 144 { 145 __b->_M_this_ptr.reset(); 146 __throw_system_error(__e); 147 } 148 } 149 150 unsigned int 151 thread::hardware_concurrency() noexcept 152 { 153 int __n = _GLIBCXX_NPROCS; 154 if (__n < 0) 155 __n = 0; 156 return __n; 157 } 158 159 _GLIBCXX_END_NAMESPACE_VERSION 160 161 namespace this_thread 162 { 163 _GLIBCXX_BEGIN_NAMESPACE_VERSION 164 165 void 166 __sleep_for(chrono::seconds __s, chrono::nanoseconds __ns) 167 { 168 #ifdef _GLIBCXX_USE_NANOSLEEP 169 __gthread_time_t __ts = 170 { 171 static_cast<std::time_t>(__s.count()), 172 static_cast<long>(__ns.count()) 173 }; 174 ::nanosleep(&__ts, 0); 175 #elif defined(_GLIBCXX_HAVE_SLEEP) 176 # ifdef _GLIBCXX_HAVE_USLEEP 177 ::sleep(__s.count()); 178 if (__ns.count() > 0) 179 { 180 long __us = __ns.count() / 1000; 181 if (__us == 0) 182 __us = 1; 183 ::usleep(__us); 184 } 185 # else 186 ::sleep(__s.count() + (__ns.count() >= 1000000)); 187 # endif 188 #elif defined(_GLIBCXX_HAVE_WIN32_SLEEP) 189 unsigned long ms = __ns.count() / 1000000; 190 if (__ns.count() > 0 && ms == 0) 191 ms = 1; 192 ::Sleep(chrono::milliseconds(__s).count() + ms); 193 #endif 194 } 195 196 _GLIBCXX_END_NAMESPACE_VERSION 197 } 198 199 } // namespace std 200 201 #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1 202