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