1// thread -*- C++ -*- 2 3// Copyright (C) 2008-2015 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> 41static 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 71namespace std _GLIBCXX_VISIBILITY(default) 72{ 73 extern "C" 74 { 75 static 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 nullptr; 96 } 97 } // extern "C" 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 __cpp_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 _M_start_thread(std::move(__b), nullptr); 141 } 142 143 void 144 thread::_M_start_thread(__shared_base_type __b, void (*)()) 145 { 146 auto ptr = __b.get(); 147 ptr->_M_this_ptr = std::move(__b); 148 int __e = __gthread_create(&_M_id._M_thread, 149 &execute_native_thread_routine, ptr); 150 if (__e) 151 { 152 ptr->_M_this_ptr.reset(); 153 __throw_system_error(__e); 154 } 155 } 156 157 unsigned int 158 thread::hardware_concurrency() noexcept 159 { 160 int __n = _GLIBCXX_NPROCS; 161 if (__n < 0) 162 __n = 0; 163 return __n; 164 } 165 166_GLIBCXX_END_NAMESPACE_VERSION 167 168namespace this_thread 169{ 170_GLIBCXX_BEGIN_NAMESPACE_VERSION 171 172 void 173 __sleep_for(chrono::seconds __s, chrono::nanoseconds __ns) 174 { 175#ifdef _GLIBCXX_USE_NANOSLEEP 176 __gthread_time_t __ts = 177 { 178 static_cast<std::time_t>(__s.count()), 179 static_cast<long>(__ns.count()) 180 }; 181 ::nanosleep(&__ts, 0); 182#elif defined(_GLIBCXX_HAVE_SLEEP) 183# ifdef _GLIBCXX_HAVE_USLEEP 184 ::sleep(__s.count()); 185 if (__ns.count() > 0) 186 { 187 long __us = __ns.count() / 1000; 188 if (__us == 0) 189 __us = 1; 190 ::usleep(__us); 191 } 192# else 193 ::sleep(__s.count() + (__ns.count() >= 1000000)); 194# endif 195#elif defined(_GLIBCXX_HAVE_WIN32_SLEEP) 196 unsigned long ms = __ns.count() / 1000000; 197 if (__ns.count() > 0 && ms == 0) 198 ms = 1; 199 ::Sleep(chrono::milliseconds(__s).count() + ms); 200#endif 201 } 202 203_GLIBCXX_END_NAMESPACE_VERSION 204} 205 206} // namespace std 207 208#endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1 209