| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 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/process/process.h" | |
| 6 | |
| 7 #include <errno.h> | |
| 8 #include <sys/resource.h> | |
| 9 | |
| 10 #include "base/files/file_util.h" | |
| 11 #include "base/lazy_instance.h" | |
| 12 #include "base/logging.h" | |
| 13 #include "base/strings/string_number_conversions.h" | |
| 14 #include "base/strings/string_split.h" | |
| 15 #include "base/strings/stringprintf.h" | |
| 16 #include "base/synchronization/lock.h" | |
| 17 | |
| 18 namespace base { | |
| 19 | |
| 20 namespace { | |
| 21 | |
| 22 const int kForegroundPriority = 0; | |
| 23 | |
| 24 #if defined(OS_CHROMEOS) | |
| 25 // We are more aggressive in our lowering of background process priority | |
| 26 // for chromeos as we have much more control over other processes running | |
| 27 // on the machine. | |
| 28 // | |
| 29 // TODO(davemoore) Refactor this by adding support for higher levels to set | |
| 30 // the foregrounding / backgrounding process so we don't have to keep | |
| 31 // chrome / chromeos specific logic here. | |
| 32 const int kBackgroundPriority = 19; | |
| 33 const char kControlPath[] = "/sys/fs/cgroup/cpu%s/cgroup.procs"; | |
| 34 const char kForeground[] = "/chrome_renderers/foreground"; | |
| 35 const char kBackground[] = "/chrome_renderers/background"; | |
| 36 const char kProcPath[] = "/proc/%d/cgroup"; | |
| 37 | |
| 38 struct CGroups { | |
| 39 // Check for cgroups files. ChromeOS supports these by default. It creates | |
| 40 // a cgroup mount in /sys/fs/cgroup and then configures two cpu task groups, | |
| 41 // one contains at most a single foreground renderer and the other contains | |
| 42 // all background renderers. This allows us to limit the impact of background | |
| 43 // renderers on foreground ones to a greater level than simple renicing. | |
| 44 bool enabled; | |
| 45 base::FilePath foreground_file; | |
| 46 base::FilePath background_file; | |
| 47 | |
| 48 CGroups() { | |
| 49 foreground_file = | |
| 50 base::FilePath(base::StringPrintf(kControlPath, kForeground)); | |
| 51 background_file = | |
| 52 base::FilePath(base::StringPrintf(kControlPath, kBackground)); | |
| 53 base::FileSystemType foreground_type; | |
| 54 base::FileSystemType background_type; | |
| 55 enabled = | |
| 56 base::GetFileSystemType(foreground_file, &foreground_type) && | |
| 57 base::GetFileSystemType(background_file, &background_type) && | |
| 58 foreground_type == FILE_SYSTEM_CGROUP && | |
| 59 background_type == FILE_SYSTEM_CGROUP; | |
| 60 } | |
| 61 }; | |
| 62 | |
| 63 base::LazyInstance<CGroups> cgroups = LAZY_INSTANCE_INITIALIZER; | |
| 64 #else | |
| 65 const int kBackgroundPriority = 5; | |
| 66 #endif | |
| 67 | |
| 68 struct CheckForNicePermission { | |
| 69 CheckForNicePermission() : can_reraise_priority(false) { | |
| 70 // We won't be able to raise the priority if we don't have the right rlimit. | |
| 71 // The limit may be adjusted in /etc/security/limits.conf for PAM systems. | |
| 72 struct rlimit rlim; | |
| 73 if ((getrlimit(RLIMIT_NICE, &rlim) == 0) && | |
| 74 (20 - kForegroundPriority) <= static_cast<int>(rlim.rlim_cur)) { | |
| 75 can_reraise_priority = true; | |
| 76 } | |
| 77 }; | |
| 78 | |
| 79 bool can_reraise_priority; | |
| 80 }; | |
| 81 | |
| 82 } // namespace | |
| 83 | |
| 84 // static | |
| 85 bool Process::CanBackgroundProcesses() { | |
| 86 #if defined(OS_CHROMEOS) | |
| 87 if (cgroups.Get().enabled) | |
| 88 return true; | |
| 89 #endif | |
| 90 | |
| 91 static LazyInstance<CheckForNicePermission> check_for_nice_permission = | |
| 92 LAZY_INSTANCE_INITIALIZER; | |
| 93 return check_for_nice_permission.Get().can_reraise_priority; | |
| 94 } | |
| 95 | |
| 96 bool Process::IsProcessBackgrounded() const { | |
| 97 DCHECK(IsValid()); | |
| 98 | |
| 99 #if defined(OS_CHROMEOS) | |
| 100 if (cgroups.Get().enabled) { | |
| 101 std::string proc; | |
| 102 if (base::ReadFileToString( | |
| 103 base::FilePath(StringPrintf(kProcPath, process_)), | |
| 104 &proc)) { | |
| 105 std::vector<std::string> proc_parts; | |
| 106 base::SplitString(proc, ':', &proc_parts); | |
| 107 DCHECK_EQ(proc_parts.size(), 3u); | |
| 108 bool ret = proc_parts[2] == std::string(kBackground); | |
| 109 return ret; | |
| 110 } else { | |
| 111 return false; | |
| 112 } | |
| 113 } | |
| 114 #endif | |
| 115 return GetPriority() == kBackgroundPriority; | |
| 116 } | |
| 117 | |
| 118 bool Process::SetProcessBackgrounded(bool background) { | |
| 119 DCHECK(IsValid()); | |
| 120 | |
| 121 #if defined(OS_CHROMEOS) | |
| 122 if (cgroups.Get().enabled) { | |
| 123 std::string pid = IntToString(process_); | |
| 124 const base::FilePath file = | |
| 125 background ? | |
| 126 cgroups.Get().background_file : cgroups.Get().foreground_file; | |
| 127 return base::WriteFile(file, pid.c_str(), pid.size()) > 0; | |
| 128 } | |
| 129 #endif // OS_CHROMEOS | |
| 130 | |
| 131 if (!CanBackgroundProcesses()) | |
| 132 return false; | |
| 133 | |
| 134 int priority = background ? kBackgroundPriority : kForegroundPriority; | |
| 135 int result = setpriority(PRIO_PROCESS, process_, priority); | |
| 136 DPCHECK(result == 0); | |
| 137 return result == 0; | |
| 138 } | |
| 139 | |
| 140 } // namespace base | |
| OLD | NEW |