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 "chrome/browser/chromeos/memory/low_memory_observer.h" | 5 #include "chrome/browser/chromeos/memory/low_memory_observer.h" |
6 | 6 |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/chromeos/chromeos_version.h" | 10 #include "base/chromeos/chromeos_version.h" |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 StopObservingOnFileThread(); | 66 StopObservingOnFileThread(); |
67 } | 67 } |
68 | 68 |
69 // Start a timer to resume watching the low memory file descriptor. | 69 // Start a timer to resume watching the low memory file descriptor. |
70 void ScheduleNextObservation(); | 70 void ScheduleNextObservation(); |
71 | 71 |
72 // Actually start watching the file descriptor. | 72 // Actually start watching the file descriptor. |
73 void StartWatchingDescriptor(); | 73 void StartWatchingDescriptor(); |
74 | 74 |
75 // Delegate to receive events from WatchFileDescriptor. | 75 // Delegate to receive events from WatchFileDescriptor. |
76 class FileWatcherDelegate : public MessageLoopForIO::Watcher { | 76 class FileWatcherDelegate : public base::MessageLoopForIO::Watcher { |
77 public: | 77 public: |
78 explicit FileWatcherDelegate(LowMemoryObserverImpl* owner) | 78 explicit FileWatcherDelegate(LowMemoryObserverImpl* owner) |
79 : owner_(owner) {} | 79 : owner_(owner) {} |
80 virtual ~FileWatcherDelegate() {} | 80 virtual ~FileWatcherDelegate() {} |
81 | 81 |
82 // Overrides for MessageLoopForIO::Watcher | 82 // Overrides for MessageLoopForIO::Watcher |
83 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {} | 83 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {} |
84 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE { | 84 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE { |
85 LOG(WARNING) << "Low memory condition detected. Discarding a tab."; | 85 LOG(WARNING) << "Low memory condition detected. Discarding a tab."; |
86 // We can only discard tabs on the UI thread. | 86 // We can only discard tabs on the UI thread. |
87 base::Callback<void(void)> callback = base::Bind(&DiscardTab); | 87 base::Callback<void(void)> callback = base::Bind(&DiscardTab); |
88 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); | 88 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); |
89 owner_->ScheduleNextObservation(); | 89 owner_->ScheduleNextObservation(); |
90 } | 90 } |
91 | 91 |
92 // Sends off a discard request to the OomPriorityManager. Must be run on | 92 // Sends off a discard request to the OomPriorityManager. Must be run on |
93 // the UI thread. | 93 // the UI thread. |
94 static void DiscardTab() { | 94 static void DiscardTab() { |
95 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 95 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
96 if (g_browser_process && g_browser_process->oom_priority_manager()) | 96 if (g_browser_process && g_browser_process->oom_priority_manager()) |
97 g_browser_process->oom_priority_manager()->LogMemoryAndDiscardTab(); | 97 g_browser_process->oom_priority_manager()->LogMemoryAndDiscardTab(); |
98 } | 98 } |
99 | 99 |
100 private: | 100 private: |
101 LowMemoryObserverImpl* owner_; | 101 LowMemoryObserverImpl* owner_; |
102 DISALLOW_COPY_AND_ASSIGN(FileWatcherDelegate); | 102 DISALLOW_COPY_AND_ASSIGN(FileWatcherDelegate); |
103 }; | 103 }; |
104 | 104 |
105 scoped_ptr<MessageLoopForIO::FileDescriptorWatcher> watcher_; | 105 scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> watcher_; |
106 FileWatcherDelegate watcher_delegate_; | 106 FileWatcherDelegate watcher_delegate_; |
107 int file_descriptor_; | 107 int file_descriptor_; |
108 base::OneShotTimer<LowMemoryObserverImpl> timer_; | 108 base::OneShotTimer<LowMemoryObserverImpl> timer_; |
109 | 109 |
110 DISALLOW_COPY_AND_ASSIGN(LowMemoryObserverImpl); | 110 DISALLOW_COPY_AND_ASSIGN(LowMemoryObserverImpl); |
111 }; | 111 }; |
112 | 112 |
113 void LowMemoryObserverImpl::StartObservingOnFileThread() { | 113 void LowMemoryObserverImpl::StartObservingOnFileThread() { |
114 DCHECK_LE(file_descriptor_, 0) | 114 DCHECK_LE(file_descriptor_, 0) |
115 << "Attempted to start observation when it was already started."; | 115 << "Attempted to start observation when it was already started."; |
116 DCHECK(watcher_.get() == NULL); | 116 DCHECK(watcher_.get() == NULL); |
117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
118 DCHECK(MessageLoopForIO::current()); | 118 DCHECK(base::MessageLoopForIO::current()); |
119 | 119 |
120 file_descriptor_ = ::open(kLowMemFile, O_RDONLY); | 120 file_descriptor_ = ::open(kLowMemFile, O_RDONLY); |
121 // Don't report this error unless we're really running on ChromeOS | 121 // Don't report this error unless we're really running on ChromeOS |
122 // to avoid testing spam. | 122 // to avoid testing spam. |
123 if (file_descriptor_ < 0 && base::chromeos::IsRunningOnChromeOS()) { | 123 if (file_descriptor_ < 0 && base::chromeos::IsRunningOnChromeOS()) { |
124 PLOG(ERROR) << "Unable to open " << kLowMemFile; | 124 PLOG(ERROR) << "Unable to open " << kLowMemFile; |
125 return; | 125 return; |
126 } | 126 } |
127 watcher_.reset(new MessageLoopForIO::FileDescriptorWatcher); | 127 watcher_.reset(new base::MessageLoopForIO::FileDescriptorWatcher); |
128 StartWatchingDescriptor(); | 128 StartWatchingDescriptor(); |
129 } | 129 } |
130 | 130 |
131 void LowMemoryObserverImpl::StopObservingOnFileThread() { | 131 void LowMemoryObserverImpl::StopObservingOnFileThread() { |
132 // If StartObserving failed, StopObserving will still get called. | 132 // If StartObserving failed, StopObserving will still get called. |
133 timer_.Stop(); | 133 timer_.Stop(); |
134 if (file_descriptor_ >= 0) { | 134 if (file_descriptor_ >= 0) { |
135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
136 watcher_.reset(NULL); | 136 watcher_.reset(NULL); |
137 ::close(file_descriptor_); | 137 ::close(file_descriptor_); |
138 file_descriptor_ = -1; | 138 file_descriptor_ = -1; |
139 } | 139 } |
140 } | 140 } |
141 | 141 |
142 void LowMemoryObserverImpl::ScheduleNextObservation() { | 142 void LowMemoryObserverImpl::ScheduleNextObservation() { |
143 timer_.Start(FROM_HERE, | 143 timer_.Start(FROM_HERE, |
144 base::TimeDelta::FromMilliseconds(kLowMemoryCheckTimeoutMs), | 144 base::TimeDelta::FromMilliseconds(kLowMemoryCheckTimeoutMs), |
145 this, | 145 this, |
146 &LowMemoryObserverImpl::StartWatchingDescriptor); | 146 &LowMemoryObserverImpl::StartWatchingDescriptor); |
147 } | 147 } |
148 | 148 |
149 void LowMemoryObserverImpl::StartWatchingDescriptor() { | 149 void LowMemoryObserverImpl::StartWatchingDescriptor() { |
150 DCHECK(watcher_.get()); | 150 DCHECK(watcher_.get()); |
151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
152 DCHECK(MessageLoopForIO::current()); | 152 DCHECK(base::MessageLoopForIO::current()); |
153 if (file_descriptor_ < 0) | 153 if (file_descriptor_ < 0) |
154 return; | 154 return; |
155 if (!MessageLoopForIO::current()->WatchFileDescriptor( | 155 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( |
156 file_descriptor_, | 156 file_descriptor_, |
157 false, // persistent=false: We want it to fire once and reschedule. | 157 false, // persistent=false: We want it to fire once and reschedule. |
158 MessageLoopForIO::WATCH_READ, | 158 base::MessageLoopForIO::WATCH_READ, |
159 watcher_.get(), | 159 watcher_.get(), |
160 &watcher_delegate_)) { | 160 &watcher_delegate_)) { |
161 LOG(ERROR) << "Unable to watch " << kLowMemFile; | 161 LOG(ERROR) << "Unable to watch " << kLowMemFile; |
162 } | 162 } |
163 } | 163 } |
164 | 164 |
165 //////////////////////////////////////////////////////////////////////////////// | 165 //////////////////////////////////////////////////////////////////////////////// |
166 // LowMemoryObserver | 166 // LowMemoryObserver |
167 | 167 |
168 LowMemoryObserver::LowMemoryObserver() : observer_(new LowMemoryObserverImpl) {} | 168 LowMemoryObserver::LowMemoryObserver() : observer_(new LowMemoryObserverImpl) {} |
(...skipping 15 matching lines...) Expand all Loading... |
184 base::Bind(&LowMemoryObserverImpl::StopObservingOnFileThread, | 184 base::Bind(&LowMemoryObserverImpl::StopObservingOnFileThread, |
185 observer_.get())); | 185 observer_.get())); |
186 } | 186 } |
187 | 187 |
188 // static | 188 // static |
189 void LowMemoryObserver::SetLowMemoryMargin(int64 margin_mb) { | 189 void LowMemoryObserver::SetLowMemoryMargin(int64 margin_mb) { |
190 content::ZygoteHost::GetInstance()->AdjustLowMemoryMargin(margin_mb); | 190 content::ZygoteHost::GetInstance()->AdjustLowMemoryMargin(margin_mb); |
191 } | 191 } |
192 | 192 |
193 } // namespace chromeos | 193 } // namespace chromeos |
OLD | NEW |