| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/memory/discardable_memory_shmem.h" | 5 #include "base/memory/discardable_memory_shmem.h" |
| 6 | 6 |
| 7 #include "base/lazy_instance.h" | 7 #include "base/lazy_instance.h" |
| 8 #include "base/memory/discardable_memory_shmem_allocator.h" | 8 #include "base/memory/discardable_memory_shmem_allocator.h" |
| 9 #include "base/memory/discardable_shared_memory.h" | |
| 10 | 9 |
| 11 namespace base { | 10 namespace base { |
| 12 namespace { | |
| 13 | |
| 14 // Have the DiscardableMemoryManager trigger in-process eviction | |
| 15 // when address space usage gets too high (e.g. 512 MBytes). | |
| 16 const size_t kMemoryLimit = 512 * 1024 * 1024; | |
| 17 | |
| 18 // internal::DiscardableMemoryManager has an explicit constructor that takes | |
| 19 // a number of memory limit parameters. The LeakyLazyInstanceTraits doesn't | |
| 20 // handle the case. Thus, we need our own class here. | |
| 21 struct DiscardableMemoryManagerLazyInstanceTraits { | |
| 22 // Leaky as discardable memory clients can use this after the exit handler | |
| 23 // has been called. | |
| 24 static const bool kRegisterOnExit = false; | |
| 25 #ifndef NDEBUG | |
| 26 static const bool kAllowedToAccessOnNonjoinableThread = true; | |
| 27 #endif | |
| 28 | |
| 29 static internal::DiscardableMemoryManager* New(void* instance) { | |
| 30 return new (instance) internal::DiscardableMemoryManager( | |
| 31 kMemoryLimit, kMemoryLimit, TimeDelta::Max()); | |
| 32 } | |
| 33 static void Delete(internal::DiscardableMemoryManager* instance) { | |
| 34 instance->~DiscardableMemoryManager(); | |
| 35 } | |
| 36 }; | |
| 37 | |
| 38 LazyInstance<internal::DiscardableMemoryManager, | |
| 39 DiscardableMemoryManagerLazyInstanceTraits> g_manager = | |
| 40 LAZY_INSTANCE_INITIALIZER; | |
| 41 | |
| 42 } // namespace | |
| 43 | |
| 44 namespace internal { | 11 namespace internal { |
| 45 | 12 |
| 46 DiscardableMemoryShmem::DiscardableMemoryShmem(size_t bytes) | 13 DiscardableMemoryShmem::DiscardableMemoryShmem(size_t bytes) |
| 47 : bytes_(bytes), is_locked_(false) { | 14 : bytes_(bytes), is_locked_(false) { |
| 48 g_manager.Pointer()->Register(this, bytes); | |
| 49 } | 15 } |
| 50 | 16 |
| 51 DiscardableMemoryShmem::~DiscardableMemoryShmem() { | 17 DiscardableMemoryShmem::~DiscardableMemoryShmem() { |
| 52 if (is_locked_) | 18 if (is_locked_) |
| 53 Unlock(); | 19 Unlock(); |
| 54 g_manager.Pointer()->Unregister(this); | |
| 55 } | |
| 56 | |
| 57 // static | |
| 58 void DiscardableMemoryShmem::ReleaseFreeMemory() { | |
| 59 g_manager.Pointer()->ReleaseFreeMemory(); | |
| 60 } | |
| 61 | |
| 62 // static | |
| 63 void DiscardableMemoryShmem::PurgeForTesting() { | |
| 64 g_manager.Pointer()->PurgeAll(); | |
| 65 } | 20 } |
| 66 | 21 |
| 67 bool DiscardableMemoryShmem::Initialize() { | 22 bool DiscardableMemoryShmem::Initialize() { |
| 68 return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED; | 23 return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED; |
| 69 } | 24 } |
| 70 | 25 |
| 71 DiscardableMemoryLockStatus DiscardableMemoryShmem::Lock() { | 26 DiscardableMemoryLockStatus DiscardableMemoryShmem::Lock() { |
| 72 DCHECK(!is_locked_); | 27 DCHECK(!is_locked_); |
| 73 | 28 |
| 74 bool purged = false; | 29 if (chunk_ && chunk_->Lock()) { |
| 75 if (!g_manager.Pointer()->AcquireLock(this, &purged)) | 30 is_locked_ = true; |
| 31 return DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS; |
| 32 } |
| 33 |
| 34 chunk_ = DiscardableMemoryShmemAllocator::GetInstance() |
| 35 ->AllocateLockedDiscardableMemory(bytes_); |
| 36 if (!chunk_) |
| 76 return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED; | 37 return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED; |
| 77 | 38 |
| 78 is_locked_ = true; | 39 is_locked_ = true; |
| 79 return purged ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED | 40 return DISCARDABLE_MEMORY_LOCK_STATUS_PURGED; |
| 80 : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS; | |
| 81 } | 41 } |
| 82 | 42 |
| 83 void DiscardableMemoryShmem::Unlock() { | 43 void DiscardableMemoryShmem::Unlock() { |
| 84 DCHECK(is_locked_); | 44 DCHECK(is_locked_); |
| 85 g_manager.Pointer()->ReleaseLock(this); | 45 DCHECK(chunk_); |
| 46 chunk_->Unlock(); |
| 86 is_locked_ = false; | 47 is_locked_ = false; |
| 87 } | 48 } |
| 88 | 49 |
| 89 void* DiscardableMemoryShmem::Memory() const { | 50 void* DiscardableMemoryShmem::Memory() const { |
| 90 DCHECK(is_locked_); | 51 DCHECK(is_locked_); |
| 91 DCHECK(chunk_); | 52 DCHECK(chunk_); |
| 92 return chunk_->Memory(); | 53 return chunk_->Memory(); |
| 93 } | 54 } |
| 94 | 55 |
| 95 bool DiscardableMemoryShmem::AllocateAndAcquireLock() { | |
| 96 if (chunk_ && chunk_->Lock()) | |
| 97 return true; | |
| 98 | |
| 99 chunk_ = DiscardableMemoryShmemAllocator::GetInstance() | |
| 100 ->AllocateLockedDiscardableMemory(bytes_); | |
| 101 DCHECK(chunk_); | |
| 102 return false; | |
| 103 } | |
| 104 | |
| 105 void DiscardableMemoryShmem::ReleaseLock() { | |
| 106 chunk_->Unlock(); | |
| 107 } | |
| 108 | |
| 109 void DiscardableMemoryShmem::Purge() { | |
| 110 DCHECK(!is_locked_); | |
| 111 chunk_.reset(); | |
| 112 } | |
| 113 | |
| 114 bool DiscardableMemoryShmem::IsMemoryResident() const { | |
| 115 return chunk_->IsMemoryResident(); | |
| 116 } | |
| 117 | |
| 118 } // namespace internal | 56 } // namespace internal |
| 119 } // namespace base | 57 } // namespace base |
| OLD | NEW |