OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/threading/platform_thread.h" | 5 #include "base/threading/platform_thread.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <sched.h> | 8 #include <sched.h> |
9 | 9 |
10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
(...skipping 12 matching lines...) Expand all Loading... | |
23 #if defined(OS_LINUX) | 23 #if defined(OS_LINUX) |
24 #include <sys/prctl.h> | 24 #include <sys/prctl.h> |
25 #include <sys/resource.h> | 25 #include <sys/resource.h> |
26 #include <sys/syscall.h> | 26 #include <sys/syscall.h> |
27 #include <sys/time.h> | 27 #include <sys/time.h> |
28 #include <unistd.h> | 28 #include <unistd.h> |
29 #endif | 29 #endif |
30 | 30 |
31 #if defined(OS_ANDROID) | 31 #if defined(OS_ANDROID) |
32 #include <sys/resource.h> | 32 #include <sys/resource.h> |
33 #include "base/android/jni_android.h" | |
33 #include "base/android/thread_utils.h" | 34 #include "base/android/thread_utils.h" |
34 #include "jni/ThreadUtils_jni.h" | 35 #include "jni/ThreadUtils_jni.h" |
35 #endif | 36 #endif |
36 | 37 |
37 // TODO(bbudge) Use time.h when NaCl toolchain supports _POSIX_TIMERS | 38 // TODO(bbudge) Use time.h when NaCl toolchain supports _POSIX_TIMERS |
38 #if defined(OS_NACL) | 39 #if defined(OS_NACL) |
39 #include <sys/nacl_syscalls.h> | 40 #include <sys/nacl_syscalls.h> |
40 #endif | 41 #endif |
41 | 42 |
42 namespace base { | 43 namespace base { |
43 | 44 |
44 #if defined(OS_MACOSX) | 45 #if defined(OS_MACOSX) |
45 void InitThreading(); | 46 void InitThreading(); |
46 #endif | 47 #endif |
47 | 48 |
48 namespace { | 49 namespace { |
49 | 50 |
50 struct ThreadParams { | 51 struct ThreadParams { |
51 PlatformThread::Delegate* delegate; | 52 PlatformThread::Delegate* delegate; |
52 bool joinable; | 53 bool joinable; |
53 ThreadPriority priority; | 54 ThreadPriority priority; |
54 }; | 55 }; |
55 | 56 |
56 void SetCurrentThreadPriority(ThreadPriority priority) { | 57 |
57 #if defined(OS_LINUX) || defined(OS_ANDROID) | 58 int NiceValue(ThreadPriority priority) { |
59 // These nice values are taken from Android, which uses nice | |
60 // values like linux, but defines some preset nice values. | |
61 // Process.THREAD_PRIORITY_AUDIO = -16 | |
62 // Process.THREAD_PRIORITY_BACKGROUND = 10 | |
63 // Process.THREAD_PRIORITY_DEFAULT = 0; | |
64 // Process.THREAD_PRIORITY_DISPLAY = -4; | |
65 // Process.THREAD_PRIORITY_FOREGROUND = -2; | |
66 // Process.THREAD_PRIORITY_LESS_FAVORABLE = 1; | |
67 // Process.THREAD_PRIORITY_LOWEST = 19; | |
68 // Process.THREAD_PRIORITY_MORE_FAVORABLE = -1; | |
69 // Process.THREAD_PRIORITY_URGENT_AUDIO = -19; | |
70 // Process.THREAD_PRIORITY_URGENT_DISPLAY = -8; | |
71 // We use -6 for display, but we may want to split this | |
jar (doing other things)
2013/04/24 01:04:57
This comment does not relate well to line 64 or 70
epenner
2013/04/30 04:37:08
Thanks! This was a typo. It should be -6 below.
D
| |
72 // into urgent (-8) and non-urgent (-4). | |
73 #if defined(OS_ANDROID) | |
74 static const int threadPriorityAudio = -16; | |
75 #else | |
76 // TODO(epenner): Can we just use -16 on linux as well? | |
77 static const int threadPriorityAudio = -10; | |
78 #endif | |
79 static const int threadPriorityBackground = 10; | |
80 static const int threadPriorityDefault = 0; | |
81 static const int threadPriorityDisplay = 6; | |
58 switch (priority) { | 82 switch (priority) { |
83 case kThreadPriority_RealtimeAudio: | |
84 return threadPriorityAudio; | |
85 case kThreadPriority_Background: | |
86 return threadPriorityBackground; | |
59 case kThreadPriority_Normal: | 87 case kThreadPriority_Normal: |
60 NOTREACHED() << "Don't reset priority as not all processes can."; | 88 return threadPriorityDefault; |
61 break; | 89 case kThreadPriority_Display: |
62 case kThreadPriority_RealtimeAudio: | 90 return threadPriorityDisplay; |
63 #if defined(OS_LINUX) | 91 default: |
64 const int kNiceSetting = -10; | 92 NOTREACHED() << "Unknown priority."; |
65 // Linux isn't posix compliant with setpriority(2), it will set a thread | 93 return 0; |
66 // priority if it is passed a tid, not affecting the rest of the threads | |
67 // in the process. Setting this priority will only succeed if the user | |
68 // has been granted permission to adjust nice values on the system. | |
69 if (setpriority(PRIO_PROCESS, PlatformThread::CurrentId(), kNiceSetting)) | |
70 DVLOG(1) << "Failed to set nice value of thread to " << kNiceSetting; | |
71 #elif defined(OS_ANDROID) | |
72 JNIEnv* env = base::android::AttachCurrentThread(); | |
73 Java_ThreadUtils_setThreadPriorityAudio(env, PlatformThread::CurrentId()); | |
74 #endif // defined(OS_LINUX) | |
75 break; | |
76 } | 94 } |
77 #else // !defined(OS_LINUX) && !defined(OS_ANDROID) | |
78 PlatformThread::SetThreadPriority(pthread_self(), priority); | |
79 #endif | |
80 } | 95 } |
81 | 96 |
82 void* ThreadFunc(void* params) { | 97 void* ThreadFunc(void* params) { |
83 #if defined(OS_ANDROID) | |
84 // Threads on linux/android may inherit their priority from the thread | |
85 // where they were created. This sets all threads to the default. | |
86 // TODO(epenner): Move thread priorities to base. (crbug.com/170549) | |
87 if (setpriority(PRIO_PROCESS, PlatformThread::CurrentId(), 0)) | |
88 DVLOG(1) << "Failed to reset initial thread nice value to zero."; | |
89 #endif | |
90 ThreadParams* thread_params = static_cast<ThreadParams*>(params); | 98 ThreadParams* thread_params = static_cast<ThreadParams*>(params); |
91 PlatformThread::Delegate* delegate = thread_params->delegate; | 99 PlatformThread::Delegate* delegate = thread_params->delegate; |
92 if (!thread_params->joinable) | 100 if (!thread_params->joinable) |
93 base::ThreadRestrictions::SetSingletonAllowed(false); | 101 base::ThreadRestrictions::SetSingletonAllowed(false); |
94 | 102 |
95 // If there is a non-default priority for this thread, set it now. | 103 #if defined(OS_ANDROID) || defined(OS_LINUX) |
96 if (thread_params->priority != kThreadPriority_Normal) | 104 // Threads on linux/android may inherit their priority from the thread |
97 SetCurrentThreadPriority(thread_params->priority); | 105 // where they were created. We may also not be allowed to set the |
106 // priority on some processes, so we query it first and only | |
107 // change it if needed. | |
108 errno = 0; // getpriority may return -1 so we need to use errno. | |
109 int prio = getpriority(PRIO_PROCESS, PlatformThread::CurrentId()); | |
110 bool error = prio == -1 && errno != 0; | |
111 if (error) | |
112 LOG(ERROR) << "Failed to get thread nice value"; | |
113 // Set the priority if needed | |
114 if (!error && prio != NiceValue(thread_params->priority)) { | |
jar (doing other things)
2013/04/24 01:04:57
nit: Given the up-front-comment, I'd rather see an
epenner
2013/04/30 04:37:08
This has moved into SetThreadPriority now, I think
| |
115 PlatformThread::SetThreadPriority(pthread_self(), | |
116 PlatformThread::CurrentId(), | |
117 thread_params->priority); | |
118 } | |
119 #else | |
120 PlatformThread::SetThreadPriority(pthread_self(), | |
121 PlatformThread::CurrentId(), | |
122 thread_params->priority); | |
123 #endif | |
98 | 124 |
99 delete thread_params; | 125 delete thread_params; |
100 delegate->ThreadMain(); | 126 delegate->ThreadMain(); |
101 #if defined(OS_ANDROID) | 127 #if defined(OS_ANDROID) |
102 base::android::DetachFromVM(); | 128 base::android::DetachFromVM(); |
103 #endif | 129 #endif |
104 return NULL; | 130 return NULL; |
105 } | 131 } |
106 | 132 |
107 bool CreateThread(size_t stack_size, bool joinable, | 133 bool CreateThread(size_t stack_size, bool joinable, |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
285 | 311 |
286 // static | 312 // static |
287 void PlatformThread::Join(PlatformThreadHandle thread_handle) { | 313 void PlatformThread::Join(PlatformThreadHandle thread_handle) { |
288 // Joining another thread may block the current thread for a long time, since | 314 // Joining another thread may block the current thread for a long time, since |
289 // the thread referred to by |thread_handle| may still be running long-lived / | 315 // the thread referred to by |thread_handle| may still be running long-lived / |
290 // blocking tasks. | 316 // blocking tasks. |
291 base::ThreadRestrictions::AssertIOAllowed(); | 317 base::ThreadRestrictions::AssertIOAllowed(); |
292 pthread_join(thread_handle, NULL); | 318 pthread_join(thread_handle, NULL); |
293 } | 319 } |
294 | 320 |
295 #if !defined(OS_MACOSX) && !defined(OS_ANDROID) | 321 #if !defined(OS_MACOSX) |
296 // Mac OS X uses lower-level mach APIs and Android uses Java APIs. | 322 // Mac OS X uses lower-level mach APIs |
297 // static | 323 void PlatformThread::SetThreadPriority(PlatformThreadHandle, |
298 void PlatformThread::SetThreadPriority(PlatformThreadHandle, ThreadPriority) { | 324 PlatformThreadId id, |
299 // TODO(crogers): Implement, see http://crbug.com/116172 | 325 ThreadPriority priority) { |
326 // setpriority(2) will set a thread's priority if it is passed a tid as | |
327 // the 'process identifier', not affecting the rest of the threads in the | |
328 // process. Setting this priority will only succeed if the user has been | |
329 // granted permission to adjust nice values on the system. | |
330 #if defined(OS_ANDROID) | |
331 // On Android, we set the Audio priority through JNI as Audio priority | |
332 // will also allow the process to run while it is backgrounded. | |
333 if (priority == kThreadPriority_RealtimeAudio) { | |
334 JNIEnv* env = base::android::AttachCurrentThread(); | |
335 Java_ThreadUtils_setThreadPriorityAudio(env, PlatformThread::CurrentId()); | |
336 return; | |
337 } | |
338 #endif | |
339 #if !defined(OS_NACL) | |
340 DCHECK_NE(id, kInvalidThreadId); | |
341 int kNiceSetting = NiceValue(priority); | |
342 if (setpriority(PRIO_PROCESS, id, kNiceSetting)) | |
343 LOG(ERROR) << "Failed to set nice value of thread to " << kNiceSetting; | |
jar (doing other things)
2013/04/24 01:04:57
DLOG is generally preferred. No one will read thi
epenner
2013/04/30 04:37:08
Done.
| |
344 #endif | |
300 } | 345 } |
301 #endif | 346 #endif |
302 | 347 |
303 #if defined(OS_ANDROID) | 348 #if defined(OS_ANDROID) |
304 bool RegisterThreadUtils(JNIEnv* env) { | 349 bool RegisterThreadUtils(JNIEnv* env) { |
305 return RegisterNativesImpl(env); | 350 return RegisterNativesImpl(env); |
306 } | 351 } |
307 #endif // defined(OS_ANDROID) | 352 #endif // defined(OS_ANDROID) |
308 | 353 |
309 } // namespace base | 354 } // namespace base |
OLD | NEW |