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 #include <stddef.h> | 9 #include <stddef.h> |
10 | 10 |
| 11 #include "base/files/file_util.h" |
11 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
12 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/strings/string_number_conversions.h" |
13 #include "base/threading/platform_thread_internal_posix.h" | 15 #include "base/threading/platform_thread_internal_posix.h" |
14 #include "base/threading/thread_id_name_manager.h" | 16 #include "base/threading/thread_id_name_manager.h" |
15 #include "base/tracked_objects.h" | 17 #include "base/tracked_objects.h" |
16 #include "build/build_config.h" | 18 #include "build/build_config.h" |
17 | 19 |
18 #if !defined(OS_NACL) | 20 #if !defined(OS_NACL) |
19 #include <pthread.h> | 21 #include <pthread.h> |
20 #include <sys/prctl.h> | 22 #include <sys/prctl.h> |
| 23 #include <sys/resource.h> |
| 24 #include <sys/time.h> |
21 #include <sys/types.h> | 25 #include <sys/types.h> |
22 #include <unistd.h> | 26 #include <unistd.h> |
23 #endif | 27 #endif |
24 | 28 |
25 namespace base { | 29 namespace base { |
| 30 namespace { |
| 31 #if !defined(OS_NACL) |
| 32 const FilePath::CharType kCpusetDirectory[] = |
| 33 FILE_PATH_LITERAL("/sys/fs/cgroup/cpuset/chrome"); |
| 34 |
| 35 FilePath ThreadPriorityToCpusetDirectory(ThreadPriority priority) { |
| 36 FilePath cpuset_filepath(kCpusetDirectory); |
| 37 switch (priority) { |
| 38 case ThreadPriority::NORMAL: |
| 39 return cpuset_filepath; |
| 40 case ThreadPriority::BACKGROUND: |
| 41 return cpuset_filepath.Append(FILE_PATH_LITERAL("non-urgent")); |
| 42 case ThreadPriority::DISPLAY: |
| 43 case ThreadPriority::REALTIME_AUDIO: |
| 44 return cpuset_filepath.Append(FILE_PATH_LITERAL("urgent")); |
| 45 } |
| 46 NOTREACHED(); |
| 47 return FilePath(); |
| 48 } |
| 49 |
| 50 void SetThreadCpuset(PlatformThreadId thread_id, |
| 51 const FilePath& cpuset_directory) { |
| 52 // Silently ignore request if cpuset directory doesn't exist. |
| 53 if (!DirectoryExists(cpuset_directory)) |
| 54 return; |
| 55 FilePath tasks_filepath = cpuset_directory.Append(FILE_PATH_LITERAL("tasks")); |
| 56 std::string tid = IntToString(thread_id); |
| 57 int bytes_written = WriteFile(tasks_filepath, tid.c_str(), tid.size()); |
| 58 if (bytes_written != static_cast<int>(tid.size())) { |
| 59 DVLOG(1) << "Failed to add " << tid << " to " << tasks_filepath.value(); |
| 60 } |
| 61 } |
| 62 #endif |
| 63 } // namespace |
26 | 64 |
27 namespace internal { | 65 namespace internal { |
28 | 66 |
29 namespace { | 67 namespace { |
30 #if !defined(OS_NACL) | 68 #if !defined(OS_NACL) |
31 const struct sched_param kRealTimePrio = {8}; | 69 const struct sched_param kRealTimePrio = {8}; |
32 #endif | 70 #endif |
33 } // namespace | 71 } // namespace |
34 | 72 |
35 const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = { | 73 const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = { |
36 {ThreadPriority::BACKGROUND, 10}, | 74 {ThreadPriority::BACKGROUND, 10}, |
37 {ThreadPriority::NORMAL, 0}, | 75 {ThreadPriority::NORMAL, 0}, |
38 {ThreadPriority::DISPLAY, -8}, | 76 {ThreadPriority::DISPLAY, -8}, |
39 {ThreadPriority::REALTIME_AUDIO, -10}, | 77 {ThreadPriority::REALTIME_AUDIO, -10}, |
40 }; | 78 }; |
41 | 79 |
42 bool SetCurrentThreadPriorityForPlatform(ThreadPriority priority) { | 80 bool SetCurrentThreadPriorityForPlatform(ThreadPriority priority) { |
43 #if !defined(OS_NACL) | 81 #if !defined(OS_NACL) |
| 82 FilePath cpuset_directory = ThreadPriorityToCpusetDirectory(priority); |
| 83 SetThreadCpuset(PlatformThread::CurrentId(), cpuset_directory); |
44 return priority == ThreadPriority::REALTIME_AUDIO && | 84 return priority == ThreadPriority::REALTIME_AUDIO && |
45 pthread_setschedparam(pthread_self(), SCHED_RR, &kRealTimePrio) == 0; | 85 pthread_setschedparam(pthread_self(), SCHED_RR, &kRealTimePrio) == 0; |
46 #else | 86 #else |
47 return false; | 87 return false; |
48 #endif | 88 #endif |
49 } | 89 } |
50 | 90 |
51 bool GetCurrentThreadPriorityForPlatform(ThreadPriority* priority) { | 91 bool GetCurrentThreadPriorityForPlatform(ThreadPriority* priority) { |
52 #if !defined(OS_NACL) | 92 #if !defined(OS_NACL) |
53 int maybe_sched_rr = 0; | 93 int maybe_sched_rr = 0; |
(...skipping 29 matching lines...) Expand all Loading... |
83 // Note that glibc also has a 'pthread_setname_np' api, but it may not be | 123 // Note that glibc also has a 'pthread_setname_np' api, but it may not be |
84 // available everywhere and it's only benefit over using prctl directly is | 124 // available everywhere and it's only benefit over using prctl directly is |
85 // that it can set the name of threads other than the current thread. | 125 // that it can set the name of threads other than the current thread. |
86 int err = prctl(PR_SET_NAME, name.c_str()); | 126 int err = prctl(PR_SET_NAME, name.c_str()); |
87 // We expect EPERM failures in sandboxed processes, just ignore those. | 127 // We expect EPERM failures in sandboxed processes, just ignore those. |
88 if (err < 0 && errno != EPERM) | 128 if (err < 0 && errno != EPERM) |
89 DPLOG(ERROR) << "prctl(PR_SET_NAME)"; | 129 DPLOG(ERROR) << "prctl(PR_SET_NAME)"; |
90 #endif // !defined(OS_NACL) | 130 #endif // !defined(OS_NACL) |
91 } | 131 } |
92 | 132 |
| 133 #if !defined(OS_NACL) |
| 134 // static |
| 135 void PlatformThread::SetThreadPriority(PlatformThreadId thread_id, |
| 136 ThreadPriority priority) { |
| 137 // Changing current main threads' priority is not permitted in favor of |
| 138 // security, this interface is restricted to change only non-main thread |
| 139 // priority. |
| 140 CHECK_NE(thread_id, getpid()); |
| 141 |
| 142 FilePath cpuset_directory = ThreadPriorityToCpusetDirectory(priority); |
| 143 SetThreadCpuset(thread_id, cpuset_directory); |
| 144 |
| 145 const int nice_setting = internal::ThreadPriorityToNiceValue(priority); |
| 146 if (setpriority(PRIO_PROCESS, thread_id, nice_setting)) { |
| 147 DVPLOG(1) << "Failed to set nice value of thread (" << thread_id << ") to " |
| 148 << nice_setting; |
| 149 } |
| 150 } |
| 151 #endif // !defined(OS_NACL) |
| 152 |
93 void InitThreading() {} | 153 void InitThreading() {} |
94 | 154 |
95 void TerminateOnThread() {} | 155 void TerminateOnThread() {} |
96 | 156 |
97 size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) { | 157 size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) { |
98 #if !defined(THREAD_SANITIZER) | 158 #if !defined(THREAD_SANITIZER) |
99 return 0; | 159 return 0; |
100 #else | 160 #else |
101 // ThreadSanitizer bloats the stack heavily. Evidence has been that the | 161 // ThreadSanitizer bloats the stack heavily. Evidence has been that the |
102 // default stack size isn't enough for some browser tests. | 162 // default stack size isn't enough for some browser tests. |
103 return 2 * (1 << 23); // 2 times 8192K (the default stack size on Linux). | 163 return 2 * (1 << 23); // 2 times 8192K (the default stack size on Linux). |
104 #endif | 164 #endif |
105 } | 165 } |
106 | 166 |
107 } // namespace base | 167 } // namespace base |
OLD | NEW |