Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Side by Side Diff: base/process_linux.cc

Issue 8506036: Fix tab backgrounding on Linux / ChromeOS (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix the DPCHECK Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 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/process.h" 5 #include "base/process.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <sys/resource.h> 8 #include <sys/resource.h>
9 9
10 #include "base/file_util.h" 10 #include "base/file_util.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/stringprintf.h" 12 #include "base/stringprintf.h"
13 #include "base/string_split.h"
13 14
14 namespace base { 15 namespace {
16 const int kForegroundPriority = 0;
15 17
16 #if defined(OS_CHROMEOS) 18 #if defined(OS_CHROMEOS)
17 // We are more aggressive in our lowering of background process priority 19 // We are more aggressive in our lowering of background process priority
18 // for chromeos as we have much more control over other processes running 20 // for chromeos as we have much more control over other processes running
19 // on the machine. 21 // on the machine.
20 const int kPriorityAdjustment = 19; 22 const int kBackgroundPriority = 19;
23 const char kControlPath[] = "/tmp/cgroup/cpu%s/cgroup.procs";
24 const char kForeground[] = "/chrome_renderers/foreground";
willchan no longer on Chromium 2011/11/29 22:23:35 I'm not particularly happy about this renderer spe
DaveMoore 2011/11/30 19:01:18 Added todo() to refactor On 2011/11/29 22:23:35, w
25 const char kBackground[] = "/chrome_renderers/background";
26 const char kProcPath[] = "/proc/%d/cgroup";
27
28 FilePath foreground_file;
willchan no longer on Chromium 2011/11/29 22:23:35 These are static initializers. Are you sure you wa
DaveMoore 2011/11/30 19:01:18 Changed to LazyInstance<> On 2011/11/29 22:23:35,
29 FilePath background_file;
30
31 // Check for cgroups files. ChromeOS supports these by default. It creates
32 // a cgroup mount in /tmp/cgroup and then configures two cpu task groups,
33 // one contains at most a single foreground renderer and the other contains
34 // all background renderers. This allows us to limit the impact of background
35 // renderers on foreground ones to a greater level than simple renicing.
36 bool UseCGroups() {
37 static bool use_cgroups = false;
willchan no longer on Chromium 2011/11/29 22:23:35 This code is racy, right?
DaveMoore 2011/11/30 19:01:18 Added Lock. On 2011/11/29 22:23:35, willchan wrote
38 static bool cgroups_inited = false;
39 if (!cgroups_inited) {
40 cgroups_inited = true;
41 foreground_file = FilePath(StringPrintf(kControlPath, kForeground));
42 background_file = FilePath(StringPrintf(kControlPath, kBackground));
43 file_util::FileSystemType foreground_type;
44 file_util::FileSystemType background_type;
45 use_cgroups =
46 file_util::GetFileSystemType(foreground_file, &foreground_type) &&
47 file_util::GetFileSystemType(background_file, &background_type) &&
48 foreground_type == file_util::FILE_SYSTEM_CGROUP &&
49 background_type == file_util::FILE_SYSTEM_CGROUP;
50 }
51 return use_cgroups;
52 }
53
21 #else 54 #else
22 const int kPriorityAdjustment = 5; 55 const int kBackgroundPriority = 5;
23 #endif 56 #endif
57 }
58
59 namespace base {
24 60
25 bool Process::IsProcessBackgrounded() const { 61 bool Process::IsProcessBackgrounded() const {
26 DCHECK(process_); 62 DCHECK(process_);
27 return saved_priority_ == kUnsetProcessPriority; 63
64 #if defined(OS_CHROMEOS)
65 if (UseCGroups()) {
66 std::string proc;
67 if (file_util::ReadFileToString(
68 FilePath(StringPrintf(kProcPath, process_)),
69 &proc)) {
70 std::vector<std::string> proc_parts;
71 base::SplitString(proc, ':', &proc_parts);
72 DCHECK(proc_parts.size() == 3);
73 bool ret = proc_parts[2] == std::string(kBackground);
74 return ret;
75 } else {
76 return false;
77 }
78 }
79 #endif
80 return GetPriority() == kBackgroundPriority;
28 } 81 }
29 82
30 bool Process::SetProcessBackgrounded(bool background) { 83 bool Process::SetProcessBackgrounded(bool background) {
31 DCHECK(process_); 84 DCHECK(process_);
32 85
33 #if defined(OS_CHROMEOS) 86 #if defined(OS_CHROMEOS)
34 static bool cgroups_inited = false; 87 if (UseCGroups()) {
35 static bool use_cgroups = false; 88 std::string pid = StringPrintf("%d", process_);
36 89 const FilePath file = background ? background_file : foreground_file;
37 // Check for cgroups files. ChromeOS supports these by default. It creates 90 return file_util::WriteFile(file, pid.c_str(), pid.size()) > 0;
38 // a cgroup mount in /tmp/cgroup and then configures two cpu task groups,
39 // one contains at most a single foreground renderer and the other contains
40 // all background renderers. This allows us to limit the impact of background
41 // renderers on foreground ones to a greater level than simple renicing.
42 FilePath foreground_tasks(
43 "/tmp/cgroup/cpu/chrome_renderers/foreground/tasks");
44 FilePath background_tasks(
45 "/tmp/cgroup/cpu/chrome_renderers/background/tasks");
46 if (!cgroups_inited) {
47 cgroups_inited = true;
48 file_util::FileSystemType foreground_type;
49 file_util::FileSystemType background_type;
50 use_cgroups =
51 file_util::GetFileSystemType(foreground_tasks, &foreground_type) &&
52 file_util::GetFileSystemType(background_tasks, &background_type) &&
53 foreground_type == file_util::FILE_SYSTEM_CGROUP &&
54 background_type == file_util::FILE_SYSTEM_CGROUP;
55 }
56
57 if (use_cgroups) {
58 if (background) {
59 std::string pid = StringPrintf("%d", process_);
60 if (file_util::WriteFile(background_tasks, pid.c_str(), pid.size()) > 0) {
61 // With cgroups there's no real notion of priority as an int, but this
62 // will ensure we only move renderers back to the foreground group
63 // if we've ever put them in the background one.
64 saved_priority_ = 0;
65 return true;
66 } else {
67 return false;
68 }
69 } else {
70 if (saved_priority_ == kUnsetProcessPriority) {
71 // Can't restore if we were never backgrounded.
72 return false;
73 }
74 std::string pid = StringPrintf("%d", process_);
75 if (file_util::WriteFile(foreground_tasks, pid.c_str(), pid.size()) > 0) {
76 saved_priority_ = kUnsetProcessPriority;
77 return true;
78 } else {
79 return false;
80 }
81 }
82 } 91 }
83 #endif // OS_CHROMEOS 92 #endif // OS_CHROMEOS
84 93
85 if (background) { 94 if (!CanBackgroundProcesses())
95 return false;
96
97 int priority = background ? kBackgroundPriority : kForegroundPriority;
98 int result = setpriority(PRIO_PROCESS, process_, priority);
99 DPCHECK(result == 0);
100 return result == 0;
101 }
102
103 // static
104 bool Process::CanBackgroundProcesses() {
105 static bool checked_for_permission = false;
willchan no longer on Chromium 2011/11/29 22:23:35 This is racy.
DaveMoore 2011/11/30 19:01:18 Added lock. On 2011/11/29 22:23:35, willchan wrote
106 static bool can_reraise_priority = false;
107
108 if (!checked_for_permission) {
109 checked_for_permission = true;
86 // We won't be able to raise the priority if we don't have the right rlimit. 110 // We won't be able to raise the priority if we don't have the right rlimit.
87 // The limit may be adjusted in /etc/security/limits.conf for PAM systems. 111 // The limit may be adjusted in /etc/security/limits.conf for PAM systems.
88 struct rlimit rlim; 112 struct rlimit rlim;
89 if (getrlimit(RLIMIT_NICE, &rlim) != 0) { 113 if ((getrlimit(RLIMIT_NICE, &rlim) == 0) &&
90 // Call to getrlimit failed, don't background. 114 (20 - kForegroundPriority) <= static_cast<int>(rlim.rlim_cur)) {
91 return false; 115 can_reraise_priority = true;
92 } 116 }
93 errno = 0;
94 int current_priority = GetPriority();
95 if (errno) {
96 // Couldn't get priority.
97 return false;
98 }
99 // {set,get}priority values are in the range -20 to 19, where -1 is higher
100 // priority than 0. But rlimit's are in the range from 0 to 39 where
101 // 1 is higher than 0.
102 if ((20 - current_priority) > static_cast<int>(rlim.rlim_cur)) {
103 // User is not allowed to raise the priority back to where it is now.
104 return false;
105 }
106 int result =
107 setpriority(
108 PRIO_PROCESS, process_, current_priority + kPriorityAdjustment);
109 if (result == -1) {
110 DLOG(ERROR) << "Failed to lower priority, errno: " << errno;
111 return false;
112 }
113 saved_priority_ = current_priority;
114 return true;
115 } else {
116 if (saved_priority_ == kUnsetProcessPriority) {
117 // Can't restore if we were never backgrounded.
118 return false;
119 }
120 int result = setpriority(PRIO_PROCESS, process_, saved_priority_);
121 // If we can't restore something has gone terribly wrong.
122 DPCHECK(result == 0);
123 saved_priority_ = kUnsetProcessPriority;
124 return true;
125 } 117 }
118 return can_reraise_priority;
126 } 119 }
127 120
128 } // namespace base 121 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698