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"
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>
24 #include <sys/prctl.h>
25 #include <sys/resource.h>
26 #include <sys/syscall.h>
31 #if defined(OS_ANDROID)
32 #include "base/android/jni_android.h"
35 // TODO(bbudge) Use time.h when NaCl toolchain supports _POSIX_TIMERS
37 #include <sys/nacl_syscalls.h>
42 #if defined(OS_MACOSX)
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
;
55 PlatformThread::Delegate
* delegate
;
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);
65 delegate
->ThreadMain();
66 #if defined(OS_ANDROID)
67 base::android::DetachFromVM();
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();
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.
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
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
;
140 NOTREACHED() << "Unknown thread priority.";
143 PlatformThread::SetThreadPriority(*thread_handle
, priority
);
147 pthread_attr_destroy(&attributes
);
156 PlatformThreadId
PlatformThread::CurrentId() {
157 // Pthreads doesn't have the concept of a thread ID, so we have to reach down
159 #if defined(OS_LINUX)
160 return syscall(__NR_gettid
);
161 #elif defined(OS_ANDROID)
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());
176 void PlatformThread::YieldCurrentThread() {
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)
197 void PlatformThread::SetName(const char* name
) {
198 // have to cast away const because ThreadLocalPointer does not support const
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
207 if (PlatformThread::CurrentId() == getpid())
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.
224 void PlatformThread::SetName(const char* name
) {
225 // have to cast away const because ThreadLocalPointer does not support const
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.
239 const char* PlatformThread::GetName() {
240 return current_thread_name
.Pointer()->Get();
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
);
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
);
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
);
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 /
273 base::ThreadRestrictions::AssertIOAllowed();
274 pthread_join(thread_handle
, NULL
);
277 #if !defined(OS_MACOSX)
278 // Mac OS X uses lower-level mach APIs.
281 void PlatformThread::SetThreadPriority(PlatformThreadHandle
, ThreadPriority
) {
282 // TODO(crogers): Implement, see http://crbug.com/116172