| 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 |