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