diff options
Diffstat (limited to 'base/memory/memory_pressure_monitor_mac.cc')
-rw-r--r-- | base/memory/memory_pressure_monitor_mac.cc | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/base/memory/memory_pressure_monitor_mac.cc b/base/memory/memory_pressure_monitor_mac.cc new file mode 100644 index 0000000..f394935 --- /dev/null +++ b/base/memory/memory_pressure_monitor_mac.cc @@ -0,0 +1,78 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/memory_pressure_monitor_mac.h" + +#include <dlfcn.h> +#include <sys/sysctl.h> + +#include "base/mac/mac_util.h" + +namespace base { +namespace mac { + +MemoryPressureListener::MemoryPressureLevel +MemoryPressureMonitor::MemoryPressureLevelForMacMemoryPressure( + int mac_memory_pressure) { + switch (mac_memory_pressure) { + case DISPATCH_MEMORYPRESSURE_NORMAL: + return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; + case DISPATCH_MEMORYPRESSURE_WARN: + return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE; + case DISPATCH_MEMORYPRESSURE_CRITICAL: + return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; + } + return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; +} + +void MemoryPressureMonitor::NotifyMemoryPressureChanged( + dispatch_source_s* event_source) { + int mac_memory_pressure = dispatch_source_get_data(event_source); + MemoryPressureListener::MemoryPressureLevel memory_pressure_level = + MemoryPressureLevelForMacMemoryPressure(mac_memory_pressure); + MemoryPressureListener::NotifyMemoryPressure(memory_pressure_level); +} + +MemoryPressureMonitor::MemoryPressureMonitor() + : memory_level_event_source_(nullptr) { + // _dispatch_source_type_memorypressure is not available prior to 10.9. + dispatch_source_type_t dispatch_source_memorypressure = + static_cast<dispatch_source_type_t> + (dlsym(RTLD_NEXT, "_dispatch_source_type_memorypressure")); + if (dispatch_source_memorypressure) { + // The MemoryPressureListener doesn't want to know about transitions to + // MEMORY_PRESSURE_LEVEL_NONE so don't watch for + // DISPATCH_MEMORYPRESSURE_NORMAL notifications. + memory_level_event_source_.reset( + dispatch_source_create(dispatch_source_memorypressure, 0, + DISPATCH_MEMORYPRESSURE_WARN | + DISPATCH_MEMORYPRESSURE_CRITICAL, + dispatch_get_global_queue( + DISPATCH_QUEUE_PRIORITY_DEFAULT, 0))); + + dispatch_source_set_event_handler(memory_level_event_source_.get(), ^{ + NotifyMemoryPressureChanged(memory_level_event_source_.get()); + }); + dispatch_retain(memory_level_event_source_.get()); + dispatch_resume(memory_level_event_source_.get()); + } +} + +MemoryPressureMonitor::~MemoryPressureMonitor() { +} + +MemoryPressureListener::MemoryPressureLevel +MemoryPressureMonitor::GetCurrentPressureLevel() const { + if (base::mac::IsOSMountainLionOrEarlier()) { + return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; + } + int mac_memory_pressure; + size_t length = sizeof(int); + sysctlbyname("kern.memorystatus_vm_pressure_level", &mac_memory_pressure, + &length, nullptr, 0); + return MemoryPressureLevelForMacMemoryPressure(mac_memory_pressure); +} + +} // namespace mac +} // namespace base |