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) 78bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/basictypes.h" 88bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/compiler_specific.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/lazy_instance.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/memory/discardable_memory_ashmem.h" 125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/memory/discardable_memory_ashmem_allocator.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/discardable_memory_emulated.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/discardable_memory_malloc.h" 15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/sys_info.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. 29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return base::SysInfo::AmountOfPhysicalMemory() / 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() 356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) : manager(kAshmemMemoryLimit, kAshmemMemoryLimit, TimeDelta::Max()), 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) allocator(kAshmemAllocatorName, 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetOptimalAshmemRegionSizeForAllocator()) {} 38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) internal::DiscardableMemoryManager manager; 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) internal::DiscardableMemoryAshmemAllocator allocator; 41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)LazyInstance<SharedState>::Leaky g_shared_state = LAZY_INSTANCE_INITIALIZER; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace 45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// static 47116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool DiscardableMemory::ReduceMemoryUsage() { 48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return internal::DiscardableMemoryEmulated::ReduceMemoryUsage(); 49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DiscardableMemory::GetSupportedTypes( 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<DiscardableMemoryType>* types) { 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const DiscardableMemoryType supported_types[] = { 555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DISCARDABLE_MEMORY_TYPE_ASHMEM, 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISCARDABLE_MEMORY_TYPE_EMULATED, 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISCARDABLE_MEMORY_TYPE_MALLOC 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }; 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) types->assign(supported_types, supported_types + arraysize(supported_types)); 608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// static 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemoryWithType( 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DiscardableMemoryType type, size_t size) { 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) switch (type) { 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case DISCARDABLE_MEMORY_TYPE_NONE: 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case DISCARDABLE_MEMORY_TYPE_MAC: 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return scoped_ptr<DiscardableMemory>(); 695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case DISCARDABLE_MEMORY_TYPE_ASHMEM: { 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SharedState* const shared_state = g_shared_state.Pointer(); 715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_ptr<internal::DiscardableMemoryAshmem> memory( 725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu new internal::DiscardableMemoryAshmem( 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size, &shared_state->allocator, &shared_state->manager)); 745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!memory->Initialize()) 755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return scoped_ptr<DiscardableMemory>(); 765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return memory.PassAs<DiscardableMemory>(); 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case DISCARDABLE_MEMORY_TYPE_EMULATED: { 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<internal::DiscardableMemoryEmulated> memory( 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new internal::DiscardableMemoryEmulated(size)); 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!memory->Initialize()) 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return scoped_ptr<DiscardableMemory>(); 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return memory.PassAs<DiscardableMemory>(); 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case DISCARDABLE_MEMORY_TYPE_MALLOC: { 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<internal::DiscardableMemoryMalloc> memory( 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new internal::DiscardableMemoryMalloc(size)); 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!memory->Initialize()) 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return scoped_ptr<DiscardableMemory>(); 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return memory.PassAs<DiscardableMemory>(); 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return scoped_ptr<DiscardableMemory>(); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DiscardableMemory::PurgeForTesting() { 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) g_shared_state.Pointer()->manager.PurgeAll(); 1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu internal::DiscardableMemoryEmulated::PurgeForTesting(); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace base 108