discardable_memory_android.cc revision 08fd22434aed8d58d4e04bbbc0df2a942440bcc5
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/memory/discardable_memory.h" 6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/android/sys_utils.h" 88bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/basictypes.h" 98bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/compiler_specific.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/lazy_instance.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/memory/discardable_memory_ashmem.h" 135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/memory/discardable_memory_ashmem_allocator.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/discardable_memory_emulated.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/discardable_memory_malloc.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)namespace base { 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kAshmemAllocatorName[] = "DiscardableMemoryAshmemAllocator"; 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// For Ashmem, have the DiscardableMemoryManager trigger userspace eviction 23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// when address space usage gets too high (e.g. 512 MBytes). 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const size_t kAshmemMemoryLimit = 512 * 1024 * 1024; 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)size_t GetOptimalAshmemRegionSizeForAllocator() { 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Note that this may do some I/O (without hitting the disk though) so it 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // should not be called on the critical path. 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return base::android::SysUtils::AmountOfPhysicalMemoryKB() * 1024 / 8; 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Holds the shared state used for allocations. 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)struct SharedState { 34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SharedState() 3508fd22434aed8d58d4e04bbbc0df2a942440bcc5Bo Liu : manager(kAshmemMemoryLimit, 3608fd22434aed8d58d4e04bbbc0df2a942440bcc5Bo Liu kAshmemMemoryLimit, 3708fd22434aed8d58d4e04bbbc0df2a942440bcc5Bo Liu kAshmemMemoryLimit, 3808fd22434aed8d58d4e04bbbc0df2a942440bcc5Bo Liu TimeDelta::Max()), 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) allocator(kAshmemAllocatorName, 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetOptimalAshmemRegionSizeForAllocator()) {} 41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) internal::DiscardableMemoryManager manager; 43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) internal::DiscardableMemoryAshmemAllocator allocator; 44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)LazyInstance<SharedState>::Leaky g_shared_state = LAZY_INSTANCE_INITIALIZER; 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace 48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// static 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DiscardableMemory::RegisterMemoryPressureListeners() { 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) internal::DiscardableMemoryEmulated::RegisterMemoryPressureListeners(); 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DiscardableMemory::UnregisterMemoryPressureListeners() { 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) internal::DiscardableMemoryEmulated::UnregisterMemoryPressureListeners(); 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 6008fd22434aed8d58d4e04bbbc0df2a942440bcc5Bo Liubool DiscardableMemory::ReduceMemoryUsage() { 6108fd22434aed8d58d4e04bbbc0df2a942440bcc5Bo Liu return internal::DiscardableMemoryEmulated::ReduceMemoryUsage(); 6208fd22434aed8d58d4e04bbbc0df2a942440bcc5Bo Liu} 6308fd22434aed8d58d4e04bbbc0df2a942440bcc5Bo Liu 6408fd22434aed8d58d4e04bbbc0df2a942440bcc5Bo Liu// static 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DiscardableMemory::GetSupportedTypes( 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<DiscardableMemoryType>* types) { 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const DiscardableMemoryType supported_types[] = { 685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DISCARDABLE_MEMORY_TYPE_ASHMEM, 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISCARDABLE_MEMORY_TYPE_EMULATED, 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISCARDABLE_MEMORY_TYPE_MALLOC 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }; 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) types->assign(supported_types, supported_types + arraysize(supported_types)); 738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// static 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemoryWithType( 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DiscardableMemoryType type, size_t size) { 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) switch (type) { 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case DISCARDABLE_MEMORY_TYPE_NONE: 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case DISCARDABLE_MEMORY_TYPE_MAC: 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return scoped_ptr<DiscardableMemory>(); 825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case DISCARDABLE_MEMORY_TYPE_ASHMEM: { 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SharedState* const shared_state = g_shared_state.Pointer(); 845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_ptr<internal::DiscardableMemoryAshmem> memory( 855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu new internal::DiscardableMemoryAshmem( 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size, &shared_state->allocator, &shared_state->manager)); 875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!memory->Initialize()) 885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return scoped_ptr<DiscardableMemory>(); 895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return memory.PassAs<DiscardableMemory>(); 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case DISCARDABLE_MEMORY_TYPE_EMULATED: { 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<internal::DiscardableMemoryEmulated> memory( 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new internal::DiscardableMemoryEmulated(size)); 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!memory->Initialize()) 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return scoped_ptr<DiscardableMemory>(); 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return memory.PassAs<DiscardableMemory>(); 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case DISCARDABLE_MEMORY_TYPE_MALLOC: { 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<internal::DiscardableMemoryMalloc> memory( 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new internal::DiscardableMemoryMalloc(size)); 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!memory->Initialize()) 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return scoped_ptr<DiscardableMemory>(); 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return memory.PassAs<DiscardableMemory>(); 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return scoped_ptr<DiscardableMemory>(); 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DiscardableMemory::PurgeForTesting() { 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) g_shared_state.Pointer()->manager.PurgeAll(); 1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu internal::DiscardableMemoryEmulated::PurgeForTesting(); 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace base 121