]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/src/c++11/thread.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / src / c++11 / thread.cc
CommitLineData
46e113bf
CF
1// thread -*- C++ -*-
2
83ffe9cd 3// Copyright (C) 2008-2023 Free Software Foundation, Inc.
46e113bf
CF
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
748086b7 8// Free Software Foundation; either version 3, or (at your option)
46e113bf
CF
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
748086b7
JJ
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
46e113bf 25
ce535a96 26#define _GLIBCXX_THREAD_ABI_COMPAT 1
7f40ac32 27#define _GLIBCXX_THREAD_IMPL 1
b204d772 28#include <memory> // include this first so <thread> can use shared_ptr
46e113bf 29#include <thread>
4880236e 30#include <system_error>
cbdab9c8 31#include <cerrno>
5f2862cf 32#include <cxxabi_forced.h>
46e113bf 33
5bbb1f30
JW
34#ifndef _GLIBCXX_USE_NANOSLEEP
35# ifdef _GLIBCXX_HAVE_SLEEP
36# include <unistd.h>
9149a5b7 37# elif defined(_GLIBCXX_USE_WIN32_SLEEP)
902c7559 38# define WIN32_LEAN_AND_MEAN
5bbb1f30 39# include <windows.h>
0aa1786d
JW
40# elif defined _GLIBCXX_NO_SLEEP && defined _GLIBCXX_HAS_GTHREADS
41// We expect to be able to sleep for targets that support multiple threads:
5bbb1f30
JW
42# error "No sleep function known for this target"
43# endif
44#endif
45
8ba7f29e 46#ifdef _GLIBCXX_HAS_GTHREADS
aa66b299 47
43653c33
JW
48#if defined(_GLIBCXX_USE_GET_NPROCS)
49# include <sys/sysinfo.h>
50# define _GLIBCXX_NPROCS get_nprocs()
5ee360d0
JW
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)
54# include <stddef.h>
55# include <sys/sysctl.h>
56static inline int get_nprocs()
57{
58 int count;
59 size_t size = sizeof(count);
60 int mib[] = { CTL_HW, HW_NCPU };
61 if (!sysctl(mib, 2, &count, &size, NULL, 0))
62 return count;
63 return 0;
64}
65# define _GLIBCXX_NPROCS get_nprocs()
9149a5b7 66#elif defined(_GLIBCXX_USE_GET_NPROCS_WIN32)
902c7559 67# define WIN32_LEAN_AND_MEAN
9149a5b7
EB
68# include <windows.h>
69static inline int get_nprocs()
70{
71 SYSTEM_INFO sysinfo;
72 GetSystemInfo (&sysinfo);
73 return (int)sysinfo.dwNumberOfProcessors;
74}
75# define _GLIBCXX_NPROCS get_nprocs()
43653c33
JW
76#elif defined(_GLIBCXX_USE_SC_NPROCESSORS_ONLN)
77# include <unistd.h>
78# define _GLIBCXX_NPROCS sysconf(_SC_NPROCESSORS_ONLN)
5ee360d0
JW
79#elif defined(_GLIBCXX_USE_SC_NPROC_ONLN)
80# include <unistd.h>
81# define _GLIBCXX_NPROCS sysconf(_SC_NPROC_ONLN)
47684e58 82#elif defined(_WIN32)
902c7559 83# define WIN32_LEAN_AND_MEAN
47684e58
LH
84# include <windows.h>
85static inline int get_nprocs()
86{
87 SYSTEM_INFO sysinfo;
88 GetSystemInfo(&sysinfo);
89 return (int) sysinfo.dwNumberOfProcessors;
90}
91# define _GLIBCXX_NPROCS get_nprocs()
43653c33
JW
92#else
93# define _GLIBCXX_NPROCS 0
94#endif
95
12ffa228
BK
96namespace std _GLIBCXX_VISIBILITY(default)
97{
87cec93e 98 extern "C"
46e113bf 99 {
87cec93e 100 static void*
d7afcd2b 101 execute_native_thread_routine(void* __p)
ce535a96
JW
102 {
103 thread::_State_ptr __t{ static_cast<thread::_State*>(__p) };
754d67d5 104 __t->_M_run();
ce535a96
JW
105 return nullptr;
106 }
107
108#if _GLIBCXX_THREAD_ABI_COMPAT
87cec93e 109 static void*
ce535a96 110 execute_native_thread_routine_compat(void* __p)
46e113bf 111 {
d7afcd2b
BK
112 thread::_Impl_base* __t = static_cast<thread::_Impl_base*>(__p);
113 thread::__shared_base_type __local;
ce535a96
JW
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.
d7afcd2b 117 __local.swap(__t->_M_this_ptr);
754d67d5 118 __t->_M_run();
0dc3cba1 119 return nullptr;
46e113bf 120 }
ce535a96 121#endif
87cec93e 122 } // extern "C"
46e113bf 123
12ffa228
BK
124_GLIBCXX_BEGIN_NAMESPACE_VERSION
125
ce535a96
JW
126 thread::_State::~_State() = default;
127
46e113bf
CF
128 void
129 thread::join()
130 {
cbdab9c8 131 int __e = EINVAL;
46e113bf 132
626dda69 133 if (_M_id != id())
8fc81078 134 __e = __gthread_join(_M_id._M_thread, 0);
cbdab9c8
JW
135
136 if (__e)
137 __throw_system_error(__e);
138
626dda69 139 _M_id = id();
46e113bf
CF
140 }
141
142 void
143 thread::detach()
d7afcd2b 144 {
cbdab9c8 145 int __e = EINVAL;
46e113bf 146
626dda69
CF
147 if (_M_id != id())
148 __e = __gthread_detach(_M_id._M_thread);
cbdab9c8
JW
149
150 if (__e)
151 __throw_system_error(__e);
152
626dda69 153 _M_id = id();
46e113bf
CF
154 }
155
ce535a96
JW
156 void
157 thread::_M_start_thread(_State_ptr state, void (*)())
158 {
4bbd5d0c
JW
159 if (!__gthread_active_p())
160 {
161#if __cpp_exceptions
162 throw system_error(make_error_code(errc::operation_not_permitted),
163 "Enable multithreading to use std::thread");
164#else
165 __builtin_abort();
166#endif
167 }
168
ce535a96
JW
169 const int err = __gthread_create(&_M_id._M_thread,
170 &execute_native_thread_routine,
171 state.get());
172 if (err)
173 __throw_system_error(err);
174 state.release();
175 }
176
177#if _GLIBCXX_THREAD_ABI_COMPAT
d7afcd2b 178 void
626dda69 179 thread::_M_start_thread(__shared_base_type __b)
46e113bf 180 {
45ed58a8 181 if (!__gthread_active_p())
0f3d27f0 182#if __cpp_exceptions
3722862e
JW
183 throw system_error(make_error_code(errc::operation_not_permitted),
184 "Enable multithreading to use std::thread");
185#else
45ed58a8 186 __throw_system_error(int(errc::operation_not_permitted));
3722862e 187#endif
45ed58a8 188
0dc3cba1 189 _M_start_thread(std::move(__b), nullptr);
c6b3f349
JW
190 }
191
192 void
193 thread::_M_start_thread(__shared_base_type __b, void (*)())
194 {
0dc3cba1 195 auto ptr = __b.get();
ce535a96 196 // Create a reference cycle that will be broken in the new thread.
0dc3cba1 197 ptr->_M_this_ptr = std::move(__b);
626dda69 198 int __e = __gthread_create(&_M_id._M_thread,
ce535a96 199 &execute_native_thread_routine_compat, ptr);
cbdab9c8
JW
200 if (__e)
201 {
ce535a96 202 ptr->_M_this_ptr.reset(); // break reference cycle, destroying *ptr.
46e113bf 203 __throw_system_error(__e);
cbdab9c8 204 }
46e113bf 205 }
ce535a96 206#endif
53dc5044 207
43653c33
JW
208 unsigned int
209 thread::hardware_concurrency() noexcept
210 {
211 int __n = _GLIBCXX_NPROCS;
212 if (__n < 0)
213 __n = 0;
214 return __n;
215 }
216
5bbb1f30
JW
217_GLIBCXX_END_NAMESPACE_VERSION
218} // namespace std
219
220#endif // _GLIBCXX_HAS_GTHREADS
221
0aa1786d 222#ifndef _GLIBCXX_NO_SLEEP
5bbb1f30
JW
223namespace std _GLIBCXX_VISIBILITY(default)
224{
225_GLIBCXX_BEGIN_NAMESPACE_VERSION
aa66b299
JW
226namespace this_thread
227{
aa66b299
JW
228 void
229 __sleep_for(chrono::seconds __s, chrono::nanoseconds __ns)
230 {
231#ifdef _GLIBCXX_USE_NANOSLEEP
5bbb1f30 232 struct ::timespec __ts =
aa66b299
JW
233 {
234 static_cast<std::time_t>(__s.count()),
235 static_cast<long>(__ns.count())
236 };
f55e699d
JW
237 while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
238 { }
8ed812cc 239#elif defined(_GLIBCXX_HAVE_SLEEP)
cfef4c32
JW
240 const auto target = chrono::steady_clock::now() + __s + __ns;
241 while (true)
aa66b299 242 {
cfef4c32
JW
243 unsigned secs = __s.count();
244 if (__ns.count() > 0)
245 {
246# ifdef _GLIBCXX_HAVE_USLEEP
247 long us = __ns.count() / 1000;
248 if (us == 0)
249 us = 1;
250 ::usleep(us);
8ed812cc 251# else
cfef4c32
JW
252 if (__ns.count() > 1000000 || secs == 0)
253 ++secs; // No sub-second sleep function, so round up.
aa66b299 254# endif
cfef4c32
JW
255 }
256
257 if (secs > 0)
258 {
259 // Sleep in a loop to handle interruption by signals:
260 while ((secs = ::sleep(secs)))
261 { }
262 }
263 const auto now = chrono::steady_clock::now();
264 if (now >= target)
265 break;
266 __s = chrono::duration_cast<chrono::seconds>(target - now);
267 __ns = chrono::duration_cast<chrono::nanoseconds>(target - (now + __s));
268 }
9149a5b7 269#elif defined(_GLIBCXX_USE_WIN32_SLEEP)
8ed812cc
JW
270 unsigned long ms = __ns.count() / 1000000;
271 if (__ns.count() > 0 && ms == 0)
272 ms = 1;
273 ::Sleep(chrono::milliseconds(__s).count() + ms);
aa66b299
JW
274#endif
275 }
aa66b299 276}
4a15d842 277_GLIBCXX_END_NAMESPACE_VERSION
12ffa228 278} // namespace std
0aa1786d 279#endif // ! NO_SLEEP