| 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 |