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

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: Left in extra include 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
« no previous file with comments | « base/process.h ('k') | base/process_posix.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/lazy_instance.h"
11 #include "base/logging.h" 12 #include "base/logging.h"
12 #include "base/stringprintf.h" 13 #include "base/stringprintf.h"
14 #include "base/string_split.h"
15 #include "base/synchronization/lock.h"
13 16
14 namespace base { 17 namespace {
18 const int kForegroundPriority = 0;
15 19
16 #if defined(OS_CHROMEOS) 20 #if defined(OS_CHROMEOS)
17 // We are more aggressive in our lowering of background process priority 21 // We are more aggressive in our lowering of background process priority
18 // for chromeos as we have much more control over other processes running 22 // for chromeos as we have much more control over other processes running
19 // on the machine. 23 // on the machine.
20 const int kPriorityAdjustment = 19; 24 //
25 // TODO(davemoore) Refactor this by adding support for higher levels to set
26 // the foregrounding / backgrounding process so we don't have to keep
27 // chrome / chromeos specific logic here.
28 const int kBackgroundPriority = 19;
29 const char kControlPath[] = "/tmp/cgroup/cpu%s/cgroup.procs";
30 const char kForeground[] = "/chrome_renderers/foreground";
31 const char kBackground[] = "/chrome_renderers/background";
32 const char kProcPath[] = "/proc/%d/cgroup";
33
34 base::LazyInstance<FilePath> foreground_file = LAZY_INSTANCE_INITIALIZER;
35 base::LazyInstance<FilePath> background_file = LAZY_INSTANCE_INITIALIZER;
36
37 // Check for cgroups files. ChromeOS supports these by default. It creates
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 bool UseCGroups() {
43 base::Lock lock;
willchan no longer on Chromium 2011/12/01 06:26:32 Is this lock used?
DaveMoore 2011/12/01 22:14:17 I meant AutoLock, but it's gone now On 2011/12/01
44 static bool use_cgroups = false;
45 static bool cgroups_inited = false;
46 if (!cgroups_inited) {
47 cgroups_inited = true;
willchan no longer on Chromium 2011/12/01 06:26:32 This cgroups_inited is still racy. I think you sho
DaveMoore 2011/12/01 22:14:17 Done.
48 *foreground_file.Pointer() =
49 FilePath(StringPrintf(kControlPath, kForeground));
50 *background_file.Pointer() =
51 FilePath(StringPrintf(kControlPath, kBackground));
52 file_util::FileSystemType foreground_type;
53 file_util::FileSystemType background_type;
54 use_cgroups =
55 file_util::GetFileSystemType(foreground_file.Get(), &foreground_type) &&
56 file_util::GetFileSystemType(background_file.Get(), &background_type) &&
57 foreground_type == file_util::FILE_SYSTEM_CGROUP &&
58 background_type == file_util::FILE_SYSTEM_CGROUP;
59 }
60 return use_cgroups;
61 }
62
21 #else 63 #else
22 const int kPriorityAdjustment = 5; 64 const int kBackgroundPriority = 5;
23 #endif 65 #endif
66 }
67
68 namespace base {
24 69
25 bool Process::IsProcessBackgrounded() const { 70 bool Process::IsProcessBackgrounded() const {
26 DCHECK(process_); 71 DCHECK(process_);
27 return saved_priority_ == kUnsetProcessPriority; 72
73 #if defined(OS_CHROMEOS)
74 if (UseCGroups()) {
75 std::string proc;
76 if (file_util::ReadFileToString(
77 FilePath(StringPrintf(kProcPath, process_)),
78 &proc)) {
79 std::vector<std::string> proc_parts;
80 base::SplitString(proc, ':', &proc_parts);
81 DCHECK(proc_parts.size() == 3);
82 bool ret = proc_parts[2] == std::string(kBackground);
83 return ret;
84 } else {
85 return false;
86 }
87 }
88 #endif
89 return GetPriority() == kBackgroundPriority;
28 } 90 }
29 91
30 bool Process::SetProcessBackgrounded(bool background) { 92 bool Process::SetProcessBackgrounded(bool background) {
31 DCHECK(process_); 93 DCHECK(process_);
32 94
33 #if defined(OS_CHROMEOS) 95 #if defined(OS_CHROMEOS)
34 static bool cgroups_inited = false; 96 if (UseCGroups()) {
35 static bool use_cgroups = false; 97 std::string pid = StringPrintf("%d", process_);
36 98 const FilePath file =
37 // Check for cgroups files. ChromeOS supports these by default. It creates 99 background ? background_file.Get() : foreground_file.Get();
38 // a cgroup mount in /tmp/cgroup and then configures two cpu task groups, 100 return file_util::WriteFile(file, pid.c_str(), pid.size()) > 0;
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 } 101 }
83 #endif // OS_CHROMEOS 102 #endif // OS_CHROMEOS
84 103
85 if (background) { 104 if (!CanBackgroundProcesses())
105 return false;
106
107 int priority = background ? kBackgroundPriority : kForegroundPriority;
108 int result = setpriority(PRIO_PROCESS, process_, priority);
109 DPCHECK(result == 0);
110 return result == 0;
111 }
112
113 // static
114 bool Process::CanBackgroundProcesses() {
115 return false;
willchan no longer on Chromium 2011/12/01 06:26:32 What's going on here? Always returning false? The
DaveMoore 2011/12/01 22:14:17 Accidentally left this in when I was testing. Chan
116 base::Lock lock;
117 static bool checked_for_permission = false;
118 static bool can_reraise_priority = false;
119
120 if (!checked_for_permission) {
121 checked_for_permission = true;
86 // We won't be able to raise the priority if we don't have the right rlimit. 122 // 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. 123 // The limit may be adjusted in /etc/security/limits.conf for PAM systems.
88 struct rlimit rlim; 124 struct rlimit rlim;
89 if (getrlimit(RLIMIT_NICE, &rlim) != 0) { 125 if ((getrlimit(RLIMIT_NICE, &rlim) == 0) &&
90 // Call to getrlimit failed, don't background. 126 (20 - kForegroundPriority) <= static_cast<int>(rlim.rlim_cur)) {
91 return false; 127 can_reraise_priority = true;
92 } 128 }
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 } 129 }
130 return can_reraise_priority;
126 } 131 }
127 132
128 } // namespace base 133 } // namespace base
OLDNEW
« no previous file with comments | « base/process.h ('k') | base/process_posix.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698