1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/memory/discardable_memory.h"
6
7#include "base/android/sys_utils.h"
8#include "base/basictypes.h"
9#include "base/compiler_specific.h"
10#include "base/lazy_instance.h"
11#include "base/logging.h"
12#include "base/memory/discardable_memory_ashmem.h"
13#include "base/memory/discardable_memory_ashmem_allocator.h"
14#include "base/memory/discardable_memory_emulated.h"
15#include "base/memory/discardable_memory_malloc.h"
16
17namespace base {
18namespace {
19
20const char kAshmemAllocatorName[] = "DiscardableMemoryAshmemAllocator";
21
22// For Ashmem, have the DiscardableMemoryManager trigger userspace eviction
23// when address space usage gets too high (e.g. 512 MBytes).
24const size_t kAshmemMemoryLimit = 512 * 1024 * 1024;
25
26size_t GetOptimalAshmemRegionSizeForAllocator() {
27  // Note that this may do some I/O (without hitting the disk though) so it
28  // should not be called on the critical path.
29  return base::android::SysUtils::AmountOfPhysicalMemoryKB() * 1024 / 8;
30}
31
32// Holds the shared state used for allocations.
33struct SharedState {
34  SharedState()
35      : manager(kAshmemMemoryLimit,
36                kAshmemMemoryLimit,
37                kAshmemMemoryLimit,
38                TimeDelta::Max()),
39        allocator(kAshmemAllocatorName,
40                  GetOptimalAshmemRegionSizeForAllocator()) {}
41
42  internal::DiscardableMemoryManager manager;
43  internal::DiscardableMemoryAshmemAllocator allocator;
44};
45LazyInstance<SharedState>::Leaky g_shared_state = LAZY_INSTANCE_INITIALIZER;
46
47}  // namespace
48
49// static
50void DiscardableMemory::RegisterMemoryPressureListeners() {
51  internal::DiscardableMemoryEmulated::RegisterMemoryPressureListeners();
52}
53
54// static
55void DiscardableMemory::UnregisterMemoryPressureListeners() {
56  internal::DiscardableMemoryEmulated::UnregisterMemoryPressureListeners();
57}
58
59// static
60bool DiscardableMemory::ReduceMemoryUsage() {
61  return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
62}
63
64// static
65void DiscardableMemory::GetSupportedTypes(
66    std::vector<DiscardableMemoryType>* types) {
67  const DiscardableMemoryType supported_types[] = {
68    DISCARDABLE_MEMORY_TYPE_ASHMEM,
69    DISCARDABLE_MEMORY_TYPE_EMULATED,
70    DISCARDABLE_MEMORY_TYPE_MALLOC
71  };
72  types->assign(supported_types, supported_types + arraysize(supported_types));
73}
74
75// static
76scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemoryWithType(
77    DiscardableMemoryType type, size_t size) {
78  switch (type) {
79    case DISCARDABLE_MEMORY_TYPE_NONE:
80    case DISCARDABLE_MEMORY_TYPE_MAC:
81      return scoped_ptr<DiscardableMemory>();
82    case DISCARDABLE_MEMORY_TYPE_ASHMEM: {
83      SharedState* const shared_state = g_shared_state.Pointer();
84      scoped_ptr<internal::DiscardableMemoryAshmem> memory(
85          new internal::DiscardableMemoryAshmem(
86              size, &shared_state->allocator, &shared_state->manager));
87      if (!memory->Initialize())
88        return scoped_ptr<DiscardableMemory>();
89
90      return memory.PassAs<DiscardableMemory>();
91    }
92    case DISCARDABLE_MEMORY_TYPE_EMULATED: {
93      scoped_ptr<internal::DiscardableMemoryEmulated> memory(
94          new internal::DiscardableMemoryEmulated(size));
95      if (!memory->Initialize())
96        return scoped_ptr<DiscardableMemory>();
97
98      return memory.PassAs<DiscardableMemory>();
99    }
100    case DISCARDABLE_MEMORY_TYPE_MALLOC: {
101      scoped_ptr<internal::DiscardableMemoryMalloc> memory(
102          new internal::DiscardableMemoryMalloc(size));
103      if (!memory->Initialize())
104        return scoped_ptr<DiscardableMemory>();
105
106      return memory.PassAs<DiscardableMemory>();
107    }
108  }
109
110  NOTREACHED();
111  return scoped_ptr<DiscardableMemory>();
112}
113
114// static
115void DiscardableMemory::PurgeForTesting() {
116  g_shared_state.Pointer()->manager.PurgeAll();
117  internal::DiscardableMemoryEmulated::PurgeForTesting();
118}
119
120}  // namespace base
121