Refactor SetOmahaExperimentLabel out of gcpai and into install_util.
[chromium-blink-merge.git] / base / threading / platform_thread_posix.cc
blob444edc58a6268649115f2f1583bc7b56374d961d
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.
5 #include "base/threading/platform_thread.h"
7 #include <errno.h>
8 #include <sched.h>
10 #include "base/lazy_instance.h"
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/safe_strerror_posix.h"
14 #include "base/threading/thread_local.h"
15 #include "base/threading/thread_restrictions.h"
16 #include "base/tracked_objects.h"
18 #if defined(OS_MACOSX)
19 #include <sys/resource.h>
20 #include <algorithm>
21 #endif
23 #if defined(OS_LINUX)
24 #include <sys/prctl.h>
25 #include <sys/resource.h>
26 #include <sys/syscall.h>
27 #include <sys/time.h>
28 #include <unistd.h>
29 #endif
31 #if defined(OS_ANDROID)
32 #include "base/android/jni_android.h"
33 #endif
35 // TODO(bbudge) Use time.h when NaCl toolchain supports _POSIX_TIMERS
36 #if defined(OS_NACL)
37 #include <sys/nacl_syscalls.h>
38 #endif
40 namespace base {
42 #if defined(OS_MACOSX)
43 void InitThreading();
44 #endif
46 namespace {
48 #if !defined(OS_MACOSX)
49 // Mac name code is in in platform_thread_mac.mm.
50 LazyInstance<ThreadLocalPointer<char> >::Leaky
51 current_thread_name = LAZY_INSTANCE_INITIALIZER;
52 #endif
54 struct ThreadParams {
55 PlatformThread::Delegate* delegate;
56 bool joinable;
59 void* ThreadFunc(void* params) {
60 ThreadParams* thread_params = static_cast<ThreadParams*>(params);
61 PlatformThread::Delegate* delegate = thread_params->delegate;
62 if (!thread_params->joinable)
63 base::ThreadRestrictions::SetSingletonAllowed(false);
64 delete thread_params;
65 delegate->ThreadMain();
66 #if defined(OS_ANDROID)
67 base::android::DetachFromVM();
68 #endif
69 return NULL;
72 bool CreateThread(size_t stack_size, bool joinable,
73 PlatformThread::Delegate* delegate,
74 PlatformThreadHandle* thread_handle,
75 ThreadPriority priority) {
76 #if defined(OS_MACOSX)
77 base::InitThreading();
78 #endif // OS_MACOSX
80 bool success = false;
81 pthread_attr_t attributes;
82 pthread_attr_init(&attributes);
84 // Pthreads are joinable by default, so only specify the detached attribute if
85 // the thread should be non-joinable.
86 if (!joinable) {
87 pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);
90 #if defined(OS_MACOSX) && !defined(OS_IOS)
91 // The Mac OS X default for a pthread stack size is 512kB.
92 // Libc-594.1.4/pthreads/pthread.c's pthread_attr_init uses
93 // DEFAULT_STACK_SIZE for this purpose.
95 // 512kB isn't quite generous enough for some deeply recursive threads that
96 // otherwise request the default stack size by specifying 0. Here, adopt
97 // glibc's behavior as on Linux, which is to use the current stack size
98 // limit (ulimit -s) as the default stack size. See
99 // glibc-2.11.1/nptl/nptl-init.c's __pthread_initialize_minimal_internal. To
100 // avoid setting the limit below the Mac OS X default or the minimum usable
101 // stack size, these values are also considered. If any of these values
102 // can't be determined, or if stack size is unlimited (ulimit -s unlimited),
103 // stack_size is left at 0 to get the system default.
105 // Mac OS X normally only applies ulimit -s to the main thread stack. On
106 // contemporary OS X and Linux systems alike, this value is generally 8MB
107 // or in that neighborhood.
108 if (stack_size == 0) {
109 size_t default_stack_size;
110 struct rlimit stack_rlimit;
111 if (pthread_attr_getstacksize(&attributes, &default_stack_size) == 0 &&
112 getrlimit(RLIMIT_STACK, &stack_rlimit) == 0 &&
113 stack_rlimit.rlim_cur != RLIM_INFINITY) {
114 stack_size = std::max(std::max(default_stack_size,
115 static_cast<size_t>(PTHREAD_STACK_MIN)),
116 static_cast<size_t>(stack_rlimit.rlim_cur));
119 #endif // OS_MACOSX && !OS_IOS
121 if (stack_size > 0)
122 pthread_attr_setstacksize(&attributes, stack_size);
124 ThreadParams* params = new ThreadParams;
125 params->delegate = delegate;
126 params->joinable = joinable;
127 success = !pthread_create(thread_handle, &attributes, ThreadFunc, params);
129 if (priority != kThreadPriority_Normal) {
130 #if defined(OS_LINUX)
131 if (priority == kThreadPriority_RealtimeAudio) {
132 // Linux isn't posix compliant with setpriority(2), it will set a thread
133 // priority if it is passed a tid, not affecting the rest of the threads
134 // in the process. Setting this priority will only succeed if the user
135 // has been granted permission to adjust nice values on the system.
136 const int kNiceSetting = -10;
137 if (setpriority(PRIO_PROCESS, PlatformThread::CurrentId(), kNiceSetting))
138 DVLOG(1) << "Failed to set nice value of thread to " << kNiceSetting;
139 } else {
140 NOTREACHED() << "Unknown thread priority.";
142 #else
143 PlatformThread::SetThreadPriority(*thread_handle, priority);
144 #endif
147 pthread_attr_destroy(&attributes);
148 if (!success)
149 delete params;
150 return success;
153 } // namespace
155 // static
156 PlatformThreadId PlatformThread::CurrentId() {
157 // Pthreads doesn't have the concept of a thread ID, so we have to reach down
158 // into the kernel.
159 #if defined(OS_LINUX)
160 return syscall(__NR_gettid);
161 #elif defined(OS_ANDROID)
162 return gettid();
163 #elif defined(OS_SOLARIS)
164 return pthread_self();
165 #elif defined(OS_NACL) && defined(__GLIBC__)
166 return pthread_self();
167 #elif defined(OS_NACL) && !defined(__GLIBC__)
168 // Pointers are 32-bits in NaCl.
169 return reinterpret_cast<int32>(pthread_self());
170 #elif defined(OS_POSIX)
171 return reinterpret_cast<int64>(pthread_self());
172 #endif
175 // static
176 void PlatformThread::YieldCurrentThread() {
177 sched_yield();
180 // static
181 void PlatformThread::Sleep(TimeDelta duration) {
182 struct timespec sleep_time, remaining;
184 // Break the duration into seconds and nanoseconds.
185 // NOTE: TimeDelta's microseconds are int64s while timespec's
186 // nanoseconds are longs, so this unpacking must prevent overflow.
187 sleep_time.tv_sec = duration.InSeconds();
188 duration -= TimeDelta::FromSeconds(sleep_time.tv_sec);
189 sleep_time.tv_nsec = duration.InMicroseconds() * 1000; // nanoseconds
191 while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR)
192 sleep_time = remaining;
195 #if defined(OS_LINUX)
196 // static
197 void PlatformThread::SetName(const char* name) {
198 // have to cast away const because ThreadLocalPointer does not support const
199 // void*
200 current_thread_name.Pointer()->Set(const_cast<char*>(name));
201 tracked_objects::ThreadData::InitializeThreadContext(name);
203 // On linux we can get the thread names to show up in the debugger by setting
204 // the process name for the LWP. We don't want to do this for the main
205 // thread because that would rename the process, causing tools like killall
206 // to stop working.
207 if (PlatformThread::CurrentId() == getpid())
208 return;
210 // http://0pointer.de/blog/projects/name-your-threads.html
211 // Set the name for the LWP (which gets truncated to 15 characters).
212 // Note that glibc also has a 'pthread_setname_np' api, but it may not be
213 // available everywhere and it's only benefit over using prctl directly is
214 // that it can set the name of threads other than the current thread.
215 int err = prctl(PR_SET_NAME, name);
216 // We expect EPERM failures in sandboxed processes, just ignore those.
217 if (err < 0 && errno != EPERM)
218 DPLOG(ERROR) << "prctl(PR_SET_NAME)";
220 #elif defined(OS_MACOSX)
221 // Mac is implemented in platform_thread_mac.mm.
222 #else
223 // static
224 void PlatformThread::SetName(const char* name) {
225 // have to cast away const because ThreadLocalPointer does not support const
226 // void*
227 current_thread_name.Pointer()->Set(const_cast<char*>(name));
228 tracked_objects::ThreadData::InitializeThreadContext(name);
230 // (This should be relatively simple to implement for the BSDs; I
231 // just don't have one handy to test the code on.)
233 #endif // defined(OS_LINUX)
236 #if !defined(OS_MACOSX)
237 // Mac is implemented in platform_thread_mac.mm.
238 // static
239 const char* PlatformThread::GetName() {
240 return current_thread_name.Pointer()->Get();
242 #endif
244 // static
245 bool PlatformThread::Create(size_t stack_size, Delegate* delegate,
246 PlatformThreadHandle* thread_handle) {
247 return CreateThread(stack_size, true /* joinable thread */,
248 delegate, thread_handle, kThreadPriority_Normal);
251 // static
252 bool PlatformThread::CreateWithPriority(size_t stack_size, Delegate* delegate,
253 PlatformThreadHandle* thread_handle,
254 ThreadPriority priority) {
255 return CreateThread(stack_size, true, // joinable thread
256 delegate, thread_handle, priority);
259 // static
260 bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) {
261 PlatformThreadHandle unused;
263 bool result = CreateThread(stack_size, false /* non-joinable thread */,
264 delegate, &unused, kThreadPriority_Normal);
265 return result;
268 // static
269 void PlatformThread::Join(PlatformThreadHandle thread_handle) {
270 // Joining another thread may block the current thread for a long time, since
271 // the thread referred to by |thread_handle| may still be running long-lived /
272 // blocking tasks.
273 base::ThreadRestrictions::AssertIOAllowed();
274 pthread_join(thread_handle, NULL);
277 #if !defined(OS_MACOSX)
278 // Mac OS X uses lower-level mach APIs.
280 // static
281 void PlatformThread::SetThreadPriority(PlatformThreadHandle, ThreadPriority) {
282 // TODO(crogers): Implement, see http://crbug.com/116172
284 #endif
286 } // namespace base