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 |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include <sys/prctl.h> | 22 #include <sys/prctl.h> |
23 #include <sys/resource.h> | 23 #include <sys/resource.h> |
24 #include <sys/time.h> | 24 #include <sys/time.h> |
25 #include <sys/types.h> | 25 #include <sys/types.h> |
26 #include <unistd.h> | 26 #include <unistd.h> |
27 #endif | 27 #endif |
28 | 28 |
29 namespace base { | 29 namespace base { |
30 namespace { | 30 namespace { |
31 #if !defined(OS_NACL) | 31 #if !defined(OS_NACL) |
32 const FilePath::CharType kCpusetDirectory[] = | 32 const FilePath::CharType kCgroupDirectory[] = |
33 FILE_PATH_LITERAL("/sys/fs/cgroup/cpuset/chrome"); | 33 FILE_PATH_LITERAL("/sys/fs/cgroup"); |
34 | 34 |
35 FilePath ThreadPriorityToCpusetDirectory(ThreadPriority priority) { | 35 FilePath ThreadPriorityToCgroupDirectory(const FilePath& cgroup_filepath, |
36 FilePath cpuset_filepath(kCpusetDirectory); | 36 ThreadPriority priority) { |
37 switch (priority) { | 37 switch (priority) { |
38 case ThreadPriority::NORMAL: | 38 case ThreadPriority::NORMAL: |
39 return cpuset_filepath; | 39 return cgroup_filepath; |
40 case ThreadPriority::BACKGROUND: | 40 case ThreadPriority::BACKGROUND: |
41 return cpuset_filepath.Append(FILE_PATH_LITERAL("non-urgent")); | 41 return cgroup_filepath.Append(FILE_PATH_LITERAL("non-urgent")); |
42 case ThreadPriority::DISPLAY: | 42 case ThreadPriority::DISPLAY: |
43 case ThreadPriority::REALTIME_AUDIO: | 43 case ThreadPriority::REALTIME_AUDIO: |
44 return cpuset_filepath.Append(FILE_PATH_LITERAL("urgent")); | 44 return cgroup_filepath.Append(FILE_PATH_LITERAL("urgent")); |
45 } | 45 } |
46 NOTREACHED(); | 46 NOTREACHED(); |
47 return FilePath(); | 47 return FilePath(); |
48 } | 48 } |
49 | 49 |
50 void SetThreadCpuset(PlatformThreadId thread_id, | 50 void SetThreadCgroup(PlatformThreadId thread_id, |
51 const FilePath& cpuset_directory) { | 51 const FilePath& cgroup_directory) { |
52 // Silently ignore request if cpuset directory doesn't exist. | 52 FilePath tasks_filepath = cgroup_directory.Append(FILE_PATH_LITERAL("tasks")); |
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); | 53 std::string tid = IntToString(thread_id); |
57 int bytes_written = WriteFile(tasks_filepath, tid.c_str(), tid.size()); | 54 int bytes_written = WriteFile(tasks_filepath, tid.c_str(), tid.size()); |
58 if (bytes_written != static_cast<int>(tid.size())) { | 55 if (bytes_written != static_cast<int>(tid.size())) { |
59 DVLOG(1) << "Failed to add " << tid << " to " << tasks_filepath.value(); | 56 DVLOG(1) << "Failed to add " << tid << " to " << tasks_filepath.value(); |
60 } | 57 } |
61 } | 58 } |
| 59 |
| 60 void SetThreadCgroupForThreadPriority(PlatformThreadId thread_id, |
| 61 const FilePath& cgroup_filepath, |
| 62 ThreadPriority priority) { |
| 63 // Append "chrome" suffix. |
| 64 FilePath cgroup_directory = ThreadPriorityToCgroupDirectory( |
| 65 cgroup_filepath.Append(FILE_PATH_LITERAL("chrome")), priority); |
| 66 |
| 67 // Silently ignore request if cgroup directory doesn't exist. |
| 68 if (!DirectoryExists(cgroup_directory)) |
| 69 return; |
| 70 |
| 71 SetThreadCgroup(thread_id, cgroup_directory); |
| 72 } |
| 73 |
| 74 void SetThreadCgroupsForThreadPriority(PlatformThreadId thread_id, |
| 75 ThreadPriority priority) { |
| 76 FilePath cgroup_filepath(kCgroupDirectory); |
| 77 SetThreadCgroupForThreadPriority( |
| 78 thread_id, cgroup_filepath.Append(FILE_PATH_LITERAL("cpuset")), priority); |
| 79 SetThreadCgroupForThreadPriority( |
| 80 thread_id, cgroup_filepath.Append(FILE_PATH_LITERAL("schedtune")), |
| 81 priority); |
| 82 } |
62 #endif | 83 #endif |
63 } // namespace | 84 } // namespace |
64 | 85 |
65 namespace internal { | 86 namespace internal { |
66 | 87 |
67 namespace { | 88 namespace { |
68 #if !defined(OS_NACL) | 89 #if !defined(OS_NACL) |
69 const struct sched_param kRealTimePrio = {8}; | 90 const struct sched_param kRealTimePrio = {8}; |
70 #endif | 91 #endif |
71 } // namespace | 92 } // namespace |
72 | 93 |
73 const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = { | 94 const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = { |
74 {ThreadPriority::BACKGROUND, 10}, | 95 {ThreadPriority::BACKGROUND, 10}, |
75 {ThreadPriority::NORMAL, 0}, | 96 {ThreadPriority::NORMAL, 0}, |
76 {ThreadPriority::DISPLAY, -8}, | 97 {ThreadPriority::DISPLAY, -8}, |
77 {ThreadPriority::REALTIME_AUDIO, -10}, | 98 {ThreadPriority::REALTIME_AUDIO, -10}, |
78 }; | 99 }; |
79 | 100 |
80 bool SetCurrentThreadPriorityForPlatform(ThreadPriority priority) { | 101 bool SetCurrentThreadPriorityForPlatform(ThreadPriority priority) { |
81 #if !defined(OS_NACL) | 102 #if !defined(OS_NACL) |
82 FilePath cpuset_directory = ThreadPriorityToCpusetDirectory(priority); | 103 SetThreadCgroupsForThreadPriority(PlatformThread::CurrentId(), priority); |
83 SetThreadCpuset(PlatformThread::CurrentId(), cpuset_directory); | |
84 return priority == ThreadPriority::REALTIME_AUDIO && | 104 return priority == ThreadPriority::REALTIME_AUDIO && |
85 pthread_setschedparam(pthread_self(), SCHED_RR, &kRealTimePrio) == 0; | 105 pthread_setschedparam(pthread_self(), SCHED_RR, &kRealTimePrio) == 0; |
86 #else | 106 #else |
87 return false; | 107 return false; |
88 #endif | 108 #endif |
89 } | 109 } |
90 | 110 |
91 bool GetCurrentThreadPriorityForPlatform(ThreadPriority* priority) { | 111 bool GetCurrentThreadPriorityForPlatform(ThreadPriority* priority) { |
92 #if !defined(OS_NACL) | 112 #if !defined(OS_NACL) |
93 int maybe_sched_rr = 0; | 113 int maybe_sched_rr = 0; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 | 152 |
133 #if !defined(OS_NACL) | 153 #if !defined(OS_NACL) |
134 // static | 154 // static |
135 void PlatformThread::SetThreadPriority(PlatformThreadId thread_id, | 155 void PlatformThread::SetThreadPriority(PlatformThreadId thread_id, |
136 ThreadPriority priority) { | 156 ThreadPriority priority) { |
137 // Changing current main threads' priority is not permitted in favor of | 157 // Changing current main threads' priority is not permitted in favor of |
138 // security, this interface is restricted to change only non-main thread | 158 // security, this interface is restricted to change only non-main thread |
139 // priority. | 159 // priority. |
140 CHECK_NE(thread_id, getpid()); | 160 CHECK_NE(thread_id, getpid()); |
141 | 161 |
142 FilePath cpuset_directory = ThreadPriorityToCpusetDirectory(priority); | 162 SetThreadCgroupsForThreadPriority(thread_id, priority); |
143 SetThreadCpuset(thread_id, cpuset_directory); | |
144 | 163 |
145 const int nice_setting = internal::ThreadPriorityToNiceValue(priority); | 164 const int nice_setting = internal::ThreadPriorityToNiceValue(priority); |
146 if (setpriority(PRIO_PROCESS, thread_id, nice_setting)) { | 165 if (setpriority(PRIO_PROCESS, thread_id, nice_setting)) { |
147 DVPLOG(1) << "Failed to set nice value of thread (" << thread_id << ") to " | 166 DVPLOG(1) << "Failed to set nice value of thread (" << thread_id << ") to " |
148 << nice_setting; | 167 << nice_setting; |
149 } | 168 } |
150 } | 169 } |
151 #endif // !defined(OS_NACL) | 170 #endif // !defined(OS_NACL) |
152 | 171 |
153 void InitThreading() {} | 172 void InitThreading() {} |
154 | 173 |
155 void TerminateOnThread() {} | 174 void TerminateOnThread() {} |
156 | 175 |
157 size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) { | 176 size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) { |
158 #if !defined(THREAD_SANITIZER) | 177 #if !defined(THREAD_SANITIZER) |
159 return 0; | 178 return 0; |
160 #else | 179 #else |
161 // ThreadSanitizer bloats the stack heavily. Evidence has been that the | 180 // ThreadSanitizer bloats the stack heavily. Evidence has been that the |
162 // default stack size isn't enough for some browser tests. | 181 // default stack size isn't enough for some browser tests. |
163 return 2 * (1 << 23); // 2 times 8192K (the default stack size on Linux). | 182 return 2 * (1 << 23); // 2 times 8192K (the default stack size on Linux). |
164 #endif | 183 #endif |
165 } | 184 } |
166 | 185 |
167 } // namespace base | 186 } // namespace base |
OLD | NEW |