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 if (thread_id == getpid()) | |
Nico
2016/09/19 20:49:30
This should probably be a CHECK()
reveman
2016/09/19 21:43:39
Done.
| |
141 return; | |
142 | |
143 FilePath cpuset_directory = ThreadPriorityToCpusetDirectory(priority); | |
144 SetThreadCpuset(thread_id, cpuset_directory); | |
145 | |
146 const int nice_setting = internal::ThreadPriorityToNiceValue(priority); | |
147 if (setpriority(PRIO_PROCESS, thread_id, nice_setting)) { | |
148 DVPLOG(1) << "Failed to set nice value of thread (" << thread_id << ") to " | |
149 << nice_setting; | |
150 } | |
151 } | |
152 #endif // !defined(OS_NACL) | |
153 | |
93 void InitThreading() {} | 154 void InitThreading() {} |
94 | 155 |
95 void TerminateOnThread() {} | 156 void TerminateOnThread() {} |
96 | 157 |
97 size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) { | 158 size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) { |
98 #if !defined(THREAD_SANITIZER) | 159 #if !defined(THREAD_SANITIZER) |
99 return 0; | 160 return 0; |
100 #else | 161 #else |
101 // ThreadSanitizer bloats the stack heavily. Evidence has been that the | 162 // ThreadSanitizer bloats the stack heavily. Evidence has been that the |
102 // default stack size isn't enough for some browser tests. | 163 // default stack size isn't enough for some browser tests. |
103 return 2 * (1 << 23); // 2 times 8192K (the default stack size on Linux). | 164 return 2 * (1 << 23); // 2 times 8192K (the default stack size on Linux). |
104 #endif | 165 #endif |
105 } | 166 } |
106 | 167 |
107 } // namespace base | 168 } // namespace base |
OLD | NEW |