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 <sched.h> 9 #include <stddef.h> 10 11 #include "base/lazy_instance.h" 12 #include "base/logging.h" 13 #include "base/threading/platform_thread_internal_posix.h" 14 #include "base/threading/thread_id_name_manager.h" 15 #include "base/tracked_objects.h" 16 #include "build/build_config.h" 17 18 #if !defined(OS_NACL) 19 #include <pthread.h> 20 #include <sys/prctl.h> 21 #include <sys/types.h> 22 #include <unistd.h> 23 #endif 24 25 namespace base { 26 27 namespace internal { 28 29 namespace { 30 #if !defined(OS_NACL) 31 const struct sched_param kRealTimePrio = {8}; 32 const struct sched_param kResetPrio = {0}; 33 #endif 34 } // namespace 35 36 const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = { 37 {ThreadPriority::BACKGROUND, 10}, 38 {ThreadPriority::NORMAL, 0}, 39 {ThreadPriority::DISPLAY, -6}, 40 {ThreadPriority::REALTIME_AUDIO, -10}, 41 }; 42 43 bool SetCurrentThreadPriorityForPlatform(ThreadPriority priority) { 44 #if !defined(OS_NACL) 45 ThreadPriority current_priority; 46 if (priority != ThreadPriority::REALTIME_AUDIO && 47 GetCurrentThreadPriorityForPlatform(¤t_priority) && 48 current_priority == ThreadPriority::REALTIME_AUDIO) { 49 // If the pthread's round-robin scheduler is already enabled, and the new 50 // priority will use setpriority() instead, the pthread scheduler should be 51 // reset to use SCHED_OTHER so that setpriority() just works. 52 pthread_setschedparam(pthread_self(), SCHED_OTHER, &kResetPrio); 53 return false; 54 } 55 return priority == ThreadPriority::REALTIME_AUDIO && 56 pthread_setschedparam(pthread_self(), SCHED_RR, &kRealTimePrio) == 0; 57 #else 58 return false; 59 #endif 60 } 61 62 bool GetCurrentThreadPriorityForPlatform(ThreadPriority* priority) { 63 #if !defined(OS_NACL) 64 int maybe_sched_rr = 0; 65 struct sched_param maybe_realtime_prio = {0}; 66 if (pthread_getschedparam(pthread_self(), &maybe_sched_rr, 67 &maybe_realtime_prio) == 0 && 68 maybe_sched_rr == SCHED_RR && 69 maybe_realtime_prio.sched_priority == kRealTimePrio.sched_priority) { 70 *priority = ThreadPriority::REALTIME_AUDIO; 71 return true; 72 } 73 #endif 74 return false; 75 } 76 77 } // namespace internal 78 79 // static 80 void PlatformThread::SetName(const std::string& name) { 81 ThreadIdNameManager::GetInstance()->SetName(CurrentId(), name); 82 tracked_objects::ThreadData::InitializeThreadContext(name); 83 84 #if !defined(OS_NACL) 85 // On linux we can get the thread names to show up in the debugger by setting 86 // the process name for the LWP. We don't want to do this for the main 87 // thread because that would rename the process, causing tools like killall 88 // to stop working. 89 if (PlatformThread::CurrentId() == getpid()) 90 return; 91 92 // http://0pointer.de/blog/projects/name-your-threads.html 93 // Set the name for the LWP (which gets truncated to 15 characters). 94 // Note that glibc also has a 'pthread_setname_np' api, but it may not be 95 // available everywhere and it's only benefit over using prctl directly is 96 // that it can set the name of threads other than the current thread. 97 int err = prctl(PR_SET_NAME, name.c_str()); 98 // We expect EPERM failures in sandboxed processes, just ignore those. 99 if (err < 0 && errno != EPERM) 100 DPLOG(ERROR) << "prctl(PR_SET_NAME)"; 101 #endif // !defined(OS_NACL) 102 } 103 104 void InitThreading() {} 105 106 void InitOnThread() {} 107 108 void TerminateOnThread() {} 109 110 size_t GetDefaultThreadStackSize(const pthread_attr_t& /* attributes */) { 111 #if !defined(THREAD_SANITIZER) 112 return 0; 113 #else 114 // ThreadSanitizer bloats the stack heavily. Evidence has been that the 115 // default stack size isn't enough for some browser tests. 116 return 2 * (1 << 23); // 2 times 8192K (the default stack size on Linux). 117 #endif 118 } 119 120 } // namespace base 121