Chromium Code Reviews| 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 |