1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/threading/platform_thread.h"
6
7 #include <errno.h>
8 #include <pthread.h>
9 #include <sched.h>
10 #include <stddef.h>
11 #include <stdint.h>
12 #include <sys/time.h>
13 #include <sys/types.h>
14 #include <unistd.h>
15
16 #include <memory>
17
18 #include "base/debug/activity_tracker.h"
19 #include "base/lazy_instance.h"
20 #include "base/logging.h"
21 #include "base/no_destructor.h"
22 #include "base/threading/platform_thread_internal_posix.h"
23 #include "base/threading/scoped_blocking_call.h"
24 #include "base/threading/thread_id_name_manager.h"
25 #include "build/build_config.h"
26
27 #if !defined(OS_MACOSX) && !defined(OS_FUCHSIA) && !defined(OS_NACL)
28 #include "base/posix/can_lower_nice_to.h"
29 #endif
30
31 #if defined(OS_LINUX)
32 #include <sys/syscall.h>
33 #endif
34
35 #if defined(OS_FUCHSIA)
36 #include <zircon/process.h>
37 #else
38 #include <sys/resource.h>
39 #endif
40
41 namespace base {
42
43 void InitThreading();
44 void TerminateOnThread();
45 size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes);
46
47 namespace {
48
49 struct ThreadParams {
ThreadParamsbase::__anond33134d10111::ThreadParams50 ThreadParams()
51 : delegate(nullptr), joinable(false), priority(ThreadPriority::NORMAL) {}
52
53 PlatformThread::Delegate* delegate;
54 bool joinable;
55 ThreadPriority priority;
56 };
57
ThreadFunc(void * params)58 void* ThreadFunc(void* params) {
59 PlatformThread::Delegate* delegate = nullptr;
60
61 {
62 std::unique_ptr<ThreadParams> thread_params(
63 static_cast<ThreadParams*>(params));
64
65 delegate = thread_params->delegate;
66 if (!thread_params->joinable)
67 base::ThreadRestrictions::SetSingletonAllowed(false);
68
69 #if !defined(OS_NACL) && !defined(OS_BSD)
70 // Threads on linux/android may inherit their priority from the thread
71 // where they were created. This explicitly sets the priority of all new
72 // threads.
73 PlatformThread::SetCurrentThreadPriority(thread_params->priority);
74 #endif
75 }
76
77 ThreadIdNameManager::GetInstance()->RegisterThread(
78 PlatformThread::CurrentHandle().platform_handle(),
79 PlatformThread::CurrentId());
80
81 delegate->ThreadMain();
82
83 ThreadIdNameManager::GetInstance()->RemoveName(
84 PlatformThread::CurrentHandle().platform_handle(),
85 PlatformThread::CurrentId());
86
87 base::TerminateOnThread();
88 return nullptr;
89 }
90
CreateThread(size_t stack_size,bool joinable,PlatformThread::Delegate * delegate,PlatformThreadHandle * thread_handle,ThreadPriority priority)91 bool CreateThread(size_t stack_size,
92 bool joinable,
93 PlatformThread::Delegate* delegate,
94 PlatformThreadHandle* thread_handle,
95 ThreadPriority priority) {
96 DCHECK(thread_handle);
97 base::InitThreading();
98
99 pthread_attr_t attributes;
100 pthread_attr_init(&attributes);
101
102 // Pthreads are joinable by default, so only specify the detached
103 // attribute if the thread should be non-joinable.
104 if (!joinable)
105 pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);
106
107 // Get a better default if available.
108 if (stack_size == 0)
109 stack_size = base::GetDefaultThreadStackSize(attributes);
110
111 if (stack_size > 0)
112 pthread_attr_setstacksize(&attributes, stack_size);
113
114 std::unique_ptr<ThreadParams> params(new ThreadParams);
115 params->delegate = delegate;
116 params->joinable = joinable;
117 params->priority = priority;
118
119 pthread_t handle;
120 int err = pthread_create(&handle, &attributes, ThreadFunc, params.get());
121 bool success = !err;
122 if (success) {
123 // ThreadParams should be deleted on the created thread after used.
124 ignore_result(params.release());
125 } else {
126 // Value of |handle| is undefined if pthread_create fails.
127 handle = 0;
128 errno = err;
129 PLOG(ERROR) << "pthread_create";
130 }
131 *thread_handle = PlatformThreadHandle(handle);
132
133 pthread_attr_destroy(&attributes);
134
135 return success;
136 }
137
138 #if defined(OS_LINUX)
139
140 // Store the thread ids in local storage since calling the SWI can
141 // expensive and PlatformThread::CurrentId is used liberally. Clear
142 // the stored value after a fork() because forking changes the thread
143 // id. Forking without going through fork() (e.g. clone()) is not
144 // supported, but there is no known usage. Using thread_local is
145 // fine here (despite being banned) since it is going to be allowed
146 // but is blocked on a clang bug for Mac (https://crbug.com/829078)
147 // and we can't use ThreadLocalStorage because of re-entrancy due to
148 // CHECK/DCHECKs.
149 thread_local pid_t g_thread_id = -1;
150
151 class InitAtFork {
152 public:
InitAtFork()153 InitAtFork() { pthread_atfork(nullptr, nullptr, internal::ClearTidCache); }
154 };
155
156 #endif // defined(OS_LINUX)
157
158 } // namespace
159
160 #if defined(OS_LINUX)
161
162 namespace internal {
163
ClearTidCache()164 void ClearTidCache() {
165 g_thread_id = -1;
166 }
167
168 } // namespace internal
169
170 #endif // defined(OS_LINUX)
171
172 // static
CurrentId()173 PlatformThreadId PlatformThread::CurrentId() {
174 // Pthreads doesn't have the concept of a thread ID, so we have to reach down
175 // into the kernel.
176 #if defined(OS_MACOSX)
177 return pthread_mach_thread_np(pthread_self());
178 #elif defined(OS_LINUX)
179 static NoDestructor<InitAtFork> init_at_fork;
180 if (g_thread_id == -1) {
181 g_thread_id = syscall(__NR_gettid);
182 } else {
183 DCHECK_EQ(g_thread_id, syscall(__NR_gettid))
184 << "Thread id stored in TLS is different from thread id returned by "
185 "the system. It is likely that the process was forked without going "
186 "through fork().";
187 }
188 return g_thread_id;
189 #elif defined(OS_ANDROID)
190 return gettid();
191 #elif defined(OS_FUCHSIA)
192 return zx_thread_self();
193 #elif defined(OS_SOLARIS) || defined(OS_QNX)
194 return pthread_self();
195 #elif defined(OS_NACL) && defined(__GLIBC__)
196 return pthread_self();
197 #elif defined(OS_NACL) && !defined(__GLIBC__)
198 // Pointers are 32-bits in NaCl.
199 return reinterpret_cast<int32_t>(pthread_self());
200 #elif defined(OS_POSIX) && defined(OS_AIX)
201 return pthread_self();
202 #elif defined(OS_POSIX) && !defined(OS_AIX)
203 return reinterpret_cast<int64_t>(pthread_self());
204 #endif
205 }
206
207 // static
CurrentRef()208 PlatformThreadRef PlatformThread::CurrentRef() {
209 return PlatformThreadRef(pthread_self());
210 }
211
212 // static
CurrentHandle()213 PlatformThreadHandle PlatformThread::CurrentHandle() {
214 return PlatformThreadHandle(pthread_self());
215 }
216
217 // static
YieldCurrentThread()218 void PlatformThread::YieldCurrentThread() {
219 sched_yield();
220 }
221
222 // static
Sleep(TimeDelta duration)223 void PlatformThread::Sleep(TimeDelta duration) {
224 struct timespec sleep_time, remaining;
225
226 // Break the duration into seconds and nanoseconds.
227 // NOTE: TimeDelta's microseconds are int64s while timespec's
228 // nanoseconds are longs, so this unpacking must prevent overflow.
229 sleep_time.tv_sec = duration.InSeconds();
230 duration -= TimeDelta::FromSeconds(sleep_time.tv_sec);
231 sleep_time.tv_nsec = duration.InMicroseconds() * 1000; // nanoseconds
232
233 while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR)
234 sleep_time = remaining;
235 }
236
237 // static
GetName()238 const char* PlatformThread::GetName() {
239 return ThreadIdNameManager::GetInstance()->GetName(CurrentId());
240 }
241
242 // static
CreateWithPriority(size_t stack_size,Delegate * delegate,PlatformThreadHandle * thread_handle,ThreadPriority priority)243 bool PlatformThread::CreateWithPriority(size_t stack_size, Delegate* delegate,
244 PlatformThreadHandle* thread_handle,
245 ThreadPriority priority) {
246 return CreateThread(stack_size, true /* joinable thread */, delegate,
247 thread_handle, priority);
248 }
249
250 // static
CreateNonJoinable(size_t stack_size,Delegate * delegate)251 bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) {
252 return CreateNonJoinableWithPriority(stack_size, delegate,
253 ThreadPriority::NORMAL);
254 }
255
256 // static
CreateNonJoinableWithPriority(size_t stack_size,Delegate * delegate,ThreadPriority priority)257 bool PlatformThread::CreateNonJoinableWithPriority(size_t stack_size,
258 Delegate* delegate,
259 ThreadPriority priority) {
260 PlatformThreadHandle unused;
261
262 bool result = CreateThread(stack_size, false /* non-joinable thread */,
263 delegate, &unused, priority);
264 return result;
265 }
266
267 // static
Join(PlatformThreadHandle thread_handle)268 void PlatformThread::Join(PlatformThreadHandle thread_handle) {
269 // Record the event that this thread is blocking upon (for hang diagnosis).
270 base::debug::ScopedThreadJoinActivity thread_activity(&thread_handle);
271
272 // Joining another thread may block the current thread for a long time, since
273 // the thread referred to by |thread_handle| may still be running long-lived /
274 // blocking tasks.
275 base::internal::ScopedBlockingCallWithBaseSyncPrimitives scoped_blocking_call(
276 FROM_HERE, base::BlockingType::MAY_BLOCK);
277 CHECK_EQ(0, pthread_join(thread_handle.platform_handle(), nullptr));
278 }
279
280 // static
Detach(PlatformThreadHandle thread_handle)281 void PlatformThread::Detach(PlatformThreadHandle thread_handle) {
282 CHECK_EQ(0, pthread_detach(thread_handle.platform_handle()));
283 }
284
285 // Mac and Fuchsia have their own Set/GetCurrentThreadPriority()
286 // implementations.
287 #if !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
288
289 // static
CanIncreaseThreadPriority(ThreadPriority priority)290 bool PlatformThread::CanIncreaseThreadPriority(ThreadPriority priority) {
291 #if defined(OS_NACL)
292 return false;
293 #else
294 auto platform_specific_ability =
295 internal::CanIncreaseCurrentThreadPriorityForPlatform(priority);
296 if (platform_specific_ability)
297 return platform_specific_ability.value();
298
299 return internal::CanLowerNiceTo(
300 internal::ThreadPriorityToNiceValue(priority));
301 #endif // defined(OS_NACL)
302 }
303
304 // static
SetCurrentThreadPriorityImpl(ThreadPriority priority)305 void PlatformThread::SetCurrentThreadPriorityImpl(ThreadPriority priority) {
306 #if defined(OS_NACL)
307 NOTIMPLEMENTED();
308 #else
309 if (internal::SetCurrentThreadPriorityForPlatform(priority))
310 return;
311
312 // setpriority(2) should change the whole thread group's (i.e. process)
313 // priority. However, as stated in the bugs section of
314 // http://man7.org/linux/man-pages/man2/getpriority.2.html: "under the current
315 // Linux/NPTL implementation of POSIX threads, the nice value is a per-thread
316 // attribute". Also, 0 is prefered to the current thread id since it is
317 // equivalent but makes sandboxing easier (https://crbug.com/399473).
318 const int nice_setting = internal::ThreadPriorityToNiceValue(priority);
319 if (setpriority(PRIO_PROCESS, 0, nice_setting)) {
320 DVPLOG(1) << "Failed to set nice value of thread ("
321 << PlatformThread::CurrentId() << ") to " << nice_setting;
322 }
323 #endif // defined(OS_NACL)
324 }
325
326 // static
GetCurrentThreadPriority()327 ThreadPriority PlatformThread::GetCurrentThreadPriority() {
328 #if defined(OS_NACL)
329 NOTIMPLEMENTED();
330 return ThreadPriority::NORMAL;
331 #else
332 // Mirrors SetCurrentThreadPriority()'s implementation.
333 auto platform_specific_priority =
334 internal::GetCurrentThreadPriorityForPlatform();
335 if (platform_specific_priority)
336 return platform_specific_priority.value();
337
338 // Need to clear errno before calling getpriority():
339 // http://man7.org/linux/man-pages/man2/getpriority.2.html
340 errno = 0;
341 int nice_value = getpriority(PRIO_PROCESS, 0);
342 if (errno != 0) {
343 DVPLOG(1) << "Failed to get nice value of thread ("
344 << PlatformThread::CurrentId() << ")";
345 return ThreadPriority::NORMAL;
346 }
347
348 return internal::NiceValueToThreadPriority(nice_value);
349 #endif // !defined(OS_NACL)
350 }
351
352 #endif // !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
353
354 // static
GetDefaultThreadStackSize()355 size_t PlatformThread::GetDefaultThreadStackSize() {
356 pthread_attr_t attributes;
357 pthread_attr_init(&attributes);
358 return base::GetDefaultThreadStackSize(attributes);
359 }
360
361 } // namespace base
362