| Index: base/chromeos/memory_pressure_observer_chromeos.cc
 | 
| diff --git a/base/chromeos/memory_pressure_observer_chromeos.cc b/base/chromeos/memory_pressure_observer_chromeos.cc
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..d991e3f16b10fa0709bf7141aaed7ac61e6d6c38
 | 
| --- /dev/null
 | 
| +++ b/base/chromeos/memory_pressure_observer_chromeos.cc
 | 
| @@ -0,0 +1,116 @@
 | 
| +// Copyright 2014 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/chromeos/memory_pressure_observer_chromeos.h"
 | 
| +
 | 
| +#include "base/process/process_metrics.h"
 | 
| +#include "base/time/time.h"
 | 
| +
 | 
| +namespace base {
 | 
| +
 | 
| +namespace {
 | 
| +
 | 
| +// The time between memory pressure checks.
 | 
| +const int kMemoryPressureIntervalInMS = 1000;
 | 
| +
 | 
| +// Converts free percent of memory into a memory pressure value.
 | 
| +MemoryPressureObserverChromeOS::MemoryPressureLevel
 | 
| +GetMemoryPressureLevelFromFillLevel(
 | 
| +    int memory_fill_level) {
 | 
| +  if (memory_fill_level < 50)
 | 
| +    return MemoryPressureObserverChromeOS::MEMORY_PRESSURE_LEVEL_LOW;
 | 
| +  if (memory_fill_level < 75)
 | 
| +    return MemoryPressureObserverChromeOS::MEMORY_PRESSURE_LEVEL_MODERATE;
 | 
| +  if (memory_fill_level < 90)
 | 
| +    return MemoryPressureObserverChromeOS::MEMORY_PRESSURE_LEVEL_HIGH;
 | 
| +  return MemoryPressureObserverChromeOS::MEMORY_PRESSURE_LEVEL_CRITICAL;
 | 
| +}
 | 
| +
 | 
| +// Gets the used ChromeOS memory in percent.
 | 
| +int GetUsedMemoryInPercent() {
 | 
| +  base::SystemMemoryInfoKB info;
 | 
| +  if (!base::GetSystemMemoryInfo(&info)) {
 | 
| +    VLOG(1) << "Cannot determine the free memory of the system.";
 | 
| +    return 0;
 | 
| +  }
 | 
| +  // TODO(skuhne): Instead of adding the kernel memory pressure calculation
 | 
| +  // logic here, we should have a kernel mechanism similar to the low memory
 | 
| +  // notifier in ChromeOS which offers multiple pressure states.
 | 
| +  // To track this, we have crbug.com/381196.
 | 
| +
 | 
| +  // The available memory consists of "real" and virtual (z)ram memory.
 | 
| +  // Since swappable memory uses a non pre-deterministic compression and
 | 
| +  // the compression creates its own "dynamic" in the system, it gets
 | 
| +  // de-emphasized by the |kSwapWeight| factor.
 | 
| +  const int kSwapWeight = 4;
 | 
| +
 | 
| +  // The total memory we have is the "real memory" plus the virtual (z)ram.
 | 
| +  int total_memory = info.total + info.swap_total / kSwapWeight;
 | 
| +
 | 
| +  // The kernel internally uses 50MB.
 | 
| +  const int kMinFileMemory = 50 * 1024;
 | 
| +
 | 
| +  // Most file memory can be easily reclaimed.
 | 
| +  int file_memory = info.active_file + info.inactive_file;
 | 
| +  // unless it is dirty or it's a minimal portion which is required.
 | 
| +  file_memory -= info.dirty + kMinFileMemory;
 | 
| +
 | 
| +  // Available memory is the sum of free, swap and easy reclaimable memory.
 | 
| +  int available_memory =
 | 
| +      info.free + info.swap_free / kSwapWeight + file_memory;
 | 
| +
 | 
| +  DCHECK(available_memory < total_memory);
 | 
| +  int percentage = ((total_memory - available_memory) * 100) / total_memory;
 | 
| +  return percentage;
 | 
| +}
 | 
| +
 | 
| +}  // namespace
 | 
| +
 | 
| +MemoryPressureObserverChromeOS::MemoryPressureObserverChromeOS()
 | 
| +    : current_memory_pressure_level_(MEMORY_PRESSURE_LEVEL_LOW) {
 | 
| +  StartObserving();
 | 
| +}
 | 
| +
 | 
| +MemoryPressureObserverChromeOS::~MemoryPressureObserverChromeOS() {
 | 
| +  StopObserving();
 | 
| +}
 | 
| +
 | 
| +void MemoryPressureObserverChromeOS::StartObserving() {
 | 
| +  timer_.Start(FROM_HERE,
 | 
| +               base::TimeDelta::FromMilliseconds(kMemoryPressureIntervalInMS),
 | 
| +               base::Bind(&MemoryPressureObserverChromeOS::CheckMemoryPressure,
 | 
| +                          base::Unretained(this)));
 | 
| +}
 | 
| +
 | 
| +void MemoryPressureObserverChromeOS::StopObserving() {
 | 
| +  // If StartObserving failed, StopObserving will still get called.
 | 
| +  timer_.Stop();
 | 
| +}
 | 
| +
 | 
| +void MemoryPressureObserverChromeOS::CheckMemoryPressure() {
 | 
| +  MemoryPressureLevel old_pressure = current_memory_pressure_level_;
 | 
| +  MemoryPressureLevel new_pressure =
 | 
| +      GetMemoryPressureLevelFromFillLevel(GetUsedMemoryInPercent());
 | 
| +  if (old_pressure != new_pressure) {
 | 
| +    current_memory_pressure_level_ = new_pressure;
 | 
| +    switch (new_pressure) {
 | 
| +      case MEMORY_PRESSURE_LEVEL_LOW:
 | 
| +        // The |MemoryPressureListener| does currently not support this.
 | 
| +        break;
 | 
| +      case MEMORY_PRESSURE_LEVEL_MODERATE:
 | 
| +        MemoryPressureListener::NotifyMemoryPressure(
 | 
| +            MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
 | 
| +        break;
 | 
| +      case MEMORY_PRESSURE_LEVEL_HIGH:
 | 
| +        // The |MemoryPressureListener| does currently not support this.
 | 
| +        break;
 | 
| +      case MEMORY_PRESSURE_LEVEL_CRITICAL:
 | 
| +        MemoryPressureListener::NotifyMemoryPressure(
 | 
| +            MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
 | 
| +        break;
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +}  // namespace base
 | 
| 
 |