chromeos: Set a least score to the currently focused tab so that it is not selected

by the OOM killer to get killed.

BUG=chromium-os:18421
TEST=Verify that "He's dead JIM tab doesn't come on the currently focused tab in OOM
cases. It can still happen only if there is one tab present and it eats up all the
available system memory."

Patch by amruthraj@motorola.com, rosen.dash@motorola.com

Review URL: http://codereview.chromium.org/7930022

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@102134 0039d316-1c4b-4281-b951-d872f2087c98
parent 6777043d
......@@ -20,6 +20,7 @@
#include "chrome/common/chrome_constants.h"
#include "content/browser/browser_thread.h"
#include "content/browser/renderer_host/render_process_host.h"
#include "content/browser/renderer_host/render_widget_host.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/browser/zygote_host_linux.h"
#include "content/common/notification_service.h"
......@@ -43,6 +44,10 @@ namespace browser {
// "equal".
#define BUCKET_INTERVAL_MINUTES 10
// The default interval in milliseconds to wait before setting the score of
// currently focused tab.
#define FOCUSED_TAB_SCORE_ADJUST_INTERVAL_MS 500
OomPriorityManager::RendererStats::RendererStats()
: is_pinned(false),
is_selected(false),
......@@ -53,7 +58,8 @@ OomPriorityManager::RendererStats::RendererStats()
OomPriorityManager::RendererStats::~RendererStats() {
}
OomPriorityManager::OomPriorityManager() {
OomPriorityManager::OomPriorityManager()
: focused_tab_pid_(0) {
renderer_stats_.reserve(32); // 99% of users have < 30 tabs open
registrar_.Add(this,
content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
......@@ -61,6 +67,9 @@ OomPriorityManager::OomPriorityManager() {
registrar_.Add(this,
content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
NotificationService::AllSources());
registrar_.Add(this,
content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
NotificationService::AllSources());
}
OomPriorityManager::~OomPriorityManager() {
......@@ -119,6 +128,19 @@ bool OomPriorityManager::CompareRendererStats(RendererStats first,
return first.memory_used < second.memory_used;
}
void OomPriorityManager::AdjustFocusedTabScore() {
base::AutoLock pid_to_oom_score_autolock(pid_to_oom_score_lock_);
ZygoteHost::GetInstance()->AdjustRendererOOMScore(
focused_tab_pid_, chrome::kLowestRendererOomScore);
pid_to_oom_score_[focused_tab_pid_] = chrome::kLowestRendererOomScore;
}
void OomPriorityManager::OnFocusTabScoreAdjustmentTimeout() {
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
NewRunnableMethod(this, &OomPriorityManager::AdjustFocusedTabScore));
}
void OomPriorityManager::Observe(int type, const NotificationSource& source,
const NotificationDetails& details) {
base::ProcessHandle handle = 0;
......@@ -130,6 +152,32 @@ void OomPriorityManager::Observe(int type, const NotificationSource& source,
pid_to_oom_score_.erase(handle);
break;
}
case content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED: {
bool visible = *Details<bool>(details).ptr();
if (visible) {
focused_tab_pid_ =
Source<RenderWidgetHost>(source).ptr()->process()->GetHandle();
// If the currently focused tab already has a lower score, do not
// set it. This can happen in case the newly focused tab is script
// connected to the previous tab.
ProcessScoreMap::iterator it;
it = pid_to_oom_score_.find(focused_tab_pid_);
if (it == pid_to_oom_score_.end()
|| it->second != chrome::kLowestRendererOomScore) {
// By starting a timer we guarantee that the tab is focused for
// certain amount of time. Secondly, it also does not add overhead
// to the tab switching time.
if (focus_tab_score_adjust_timer_.IsRunning())
focus_tab_score_adjust_timer_.Reset();
else
focus_tab_score_adjust_timer_.Start(FROM_HERE,
TimeDelta::FromMilliseconds(FOCUSED_TAB_SCORE_ADJUST_INTERVAL_MS),
this, &OomPriorityManager::OnFocusTabScoreAdjustmentTimeout);
}
}
break;
}
default:
NOTREACHED() << L"Received unexpected notification";
break;
......
......@@ -61,9 +61,16 @@ class OomPriorityManager : public NotificationObserver {
// the timer fires.
void AdjustOomPriorities();
// Posts AdjustFocusedTabScore task to the file thread.
void OnFocusTabScoreAdjustmentTimeout();
// Called by AdjustOomPriorities. Runs on the file thread.
void DoAdjustOomPriorities();
// Called when a tab comes into focus. Runs on the file thread.
// Sets the score of only the currently focused tab to the least value.
void AdjustFocusedTabScore();
static bool CompareRendererStats(RendererStats first, RendererStats second);
virtual void Observe(int type,
......@@ -71,13 +78,16 @@ class OomPriorityManager : public NotificationObserver {
const NotificationDetails& details);
base::RepeatingTimer<OomPriorityManager> timer_;
base::OneShotTimer<OomPriorityManager> focus_tab_score_adjust_timer_;
// renderer_stats_ is used on both UI and file threads.
base::Lock renderer_stats_lock_;
StatsList renderer_stats_;
// map maintaining the process - oom_score map.
// This lock is for pid_to_oom_score_ and focus_tab_pid_.
base::Lock pid_to_oom_score_lock_;
// map maintaining the process - oom_score mapping.
ProcessScoreMap pid_to_oom_score_;
NotificationRegistrar registrar_;
base::ProcessHandle focused_tab_pid_;
DISALLOW_COPY_AND_ASSIGN(OomPriorityManager);
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment