3 // Copyright (C) 2008-2024 Free Software Foundation, Inc.
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)
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.
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.
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/>.
26 #define _GLIBCXX_THREAD_ABI_COMPAT 1
27 #define _GLIBCXX_THREAD_IMPL 1
28 #include <memory> // include this first so <thread> can use shared_ptr
30 #include <system_error>
32 #include <cxxabi_forced.h>
34 #ifndef _GLIBCXX_USE_NANOSLEEP
35 # ifdef _GLIBCXX_HAVE_SLEEP
37 # elif defined(_GLIBCXX_USE_WIN32_SLEEP)
38 # define WIN32_LEAN_AND_MEAN
40 # elif defined _GLIBCXX_NO_SLEEP && defined _GLIBCXX_HAS_GTHREADS
41 // We expect to be able to sleep for targets that support multiple threads:
42 # error "No sleep function known for this target"
46 #ifdef _GLIBCXX_HAS_GTHREADS
48 #if defined(_GLIBCXX_USE_GET_NPROCS)
49 # include <sys/sysinfo.h>
50 # define _GLIBCXX_NPROCS get_nprocs()
51 #elif defined(_GLIBCXX_USE_PTHREADS_NUM_PROCESSORS_NP)
52 # define _GLIBCXX_NPROCS pthread_num_processors_np()
53 #elif defined(_GLIBCXX_USE_SYSCTL_HW_NCPU)
55 # include <sys/sysctl.h>
56 static inline int get_nprocs()
59 size_t size
= sizeof(count
);
60 int mib
[] = { CTL_HW
, HW_NCPU
};
61 if (!sysctl(mib
, 2, &count
, &size
, NULL
, 0))
65 # define _GLIBCXX_NPROCS get_nprocs()
66 #elif defined(_GLIBCXX_USE_GET_NPROCS_WIN32)
67 # define WIN32_LEAN_AND_MEAN
69 static inline int get_nprocs()
72 GetSystemInfo (&sysinfo
);
73 return (int)sysinfo
.dwNumberOfProcessors
;
75 # define _GLIBCXX_NPROCS get_nprocs()
76 #elif defined(_GLIBCXX_USE_SC_NPROCESSORS_ONLN)
78 # define _GLIBCXX_NPROCS sysconf(_SC_NPROCESSORS_ONLN)
79 #elif defined(_GLIBCXX_USE_SC_NPROC_ONLN)
81 # define _GLIBCXX_NPROCS sysconf(_SC_NPROC_ONLN)
83 # define WIN32_LEAN_AND_MEAN
85 static inline int get_nprocs()
88 GetSystemInfo(&sysinfo
);
89 return (int) sysinfo
.dwNumberOfProcessors
;
91 # define _GLIBCXX_NPROCS get_nprocs()
93 # define _GLIBCXX_NPROCS 0
96 namespace std
_GLIBCXX_VISIBILITY(default)
101 execute_native_thread_routine(void* __p
)
103 thread::_State_ptr __t
{ static_cast<thread::_State
*>(__p
) };
108 #if _GLIBCXX_THREAD_ABI_COMPAT
110 execute_native_thread_routine_compat(void* __p
)
112 thread::_Impl_base
* __t
= static_cast<thread::_Impl_base
*>(__p
);
113 thread::__shared_base_type __local
;
114 // Now that a new thread has been created we can transfer ownership of
115 // the thread state to a local object, breaking the reference cycle
116 // created in thread::_M_start_thread.
117 __local
.swap(__t
->_M_this_ptr
);
124 _GLIBCXX_BEGIN_NAMESPACE_VERSION
126 thread::_State::~_State() = default;
134 __e
= __gthread_join(_M_id
._M_thread
, 0);
137 __throw_system_error(__e
);
148 __e
= __gthread_detach(_M_id
._M_thread
);
151 __throw_system_error(__e
);
157 thread::_M_start_thread(_State_ptr state
, void (*depend
)())
159 // Make sure it's not optimized out, not even with LTO.
160 asm ("" : : "rm" (depend
));
162 if (!__gthread_active_p())
165 throw system_error(make_error_code(errc::operation_not_permitted
),
166 "Enable multithreading to use std::thread");
172 const int err
= __gthread_create(&_M_id
._M_thread
,
173 &execute_native_thread_routine
,
176 __throw_system_error(err
);
180 #if _GLIBCXX_THREAD_ABI_COMPAT
182 thread::_M_start_thread(__shared_base_type __b
)
184 if (!__gthread_active_p())
186 throw system_error(make_error_code(errc::operation_not_permitted
),
187 "Enable multithreading to use std::thread");
189 __throw_system_error(int(errc::operation_not_permitted
));
192 _M_start_thread(std::move(__b
), nullptr);
196 thread::_M_start_thread(__shared_base_type __b
, void (*depend
)())
198 // Make sure it's not optimized out, not even with LTO.
199 asm ("" : : "rm" (depend
));
201 auto ptr
= __b
.get();
202 // Create a reference cycle that will be broken in the new thread.
203 ptr
->_M_this_ptr
= std::move(__b
);
204 int __e
= __gthread_create(&_M_id
._M_thread
,
205 &execute_native_thread_routine_compat
, ptr
);
208 ptr
->_M_this_ptr
.reset(); // break reference cycle, destroying *ptr.
209 __throw_system_error(__e
);
215 thread::hardware_concurrency() noexcept
217 int __n
= _GLIBCXX_NPROCS
;
223 _GLIBCXX_END_NAMESPACE_VERSION
226 #endif // _GLIBCXX_HAS_GTHREADS
228 #ifndef _GLIBCXX_NO_SLEEP
229 namespace std
_GLIBCXX_VISIBILITY(default)
231 _GLIBCXX_BEGIN_NAMESPACE_VERSION
232 namespace this_thread
235 __sleep_for(chrono::seconds __s
, chrono::nanoseconds __ns
)
237 #ifdef _GLIBCXX_USE_NANOSLEEP
238 struct ::timespec __ts
=
240 static_cast<std::time_t>(__s
.count()),
241 static_cast<long>(__ns
.count())
243 while (::nanosleep(&__ts
, &__ts
) == -1 && errno
== EINTR
)
245 #elif defined(_GLIBCXX_HAVE_SLEEP)
246 const auto target
= chrono::steady_clock::now() + __s
+ __ns
;
249 unsigned secs
= __s
.count();
250 if (__ns
.count() > 0)
252 # ifdef _GLIBCXX_HAVE_USLEEP
253 long us
= __ns
.count() / 1000;
258 if (__ns
.count() > 1000000 || secs
== 0)
259 ++secs
; // No sub-second sleep function, so round up.
265 // Sleep in a loop to handle interruption by signals:
266 while ((secs
= ::sleep(secs
)))
269 const auto now
= chrono::steady_clock::now();
272 __s
= chrono::duration_cast
<chrono::seconds
>(target
- now
);
273 __ns
= chrono::duration_cast
<chrono::nanoseconds
>(target
- (now
+ __s
));
275 #elif defined(_GLIBCXX_USE_WIN32_SLEEP)
276 unsigned long ms
= __ns
.count() / 1000000;
277 if (__ns
.count() > 0 && ms
== 0)
279 ::Sleep(chrono::milliseconds(__s
).count() + ms
);
283 _GLIBCXX_END_NAMESPACE_VERSION