Index: base/memory/discardable_memory_mac.cc |
diff --git a/base/memory/discardable_memory_mac.cc b/base/memory/discardable_memory_mac.cc |
index aa6823509d50f701ff6f07e6d3981e0df7226516..399eb86ef0be9649bb9ed077747e070d5aef15bb 100644 |
--- a/base/memory/discardable_memory_mac.cc |
+++ b/base/memory/discardable_memory_mac.cc |
@@ -2,14 +2,15 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "base/memory/discardable_memory.h" |
- |
#include <mach/mach.h> |
#include <sys/mman.h> |
#include "base/basictypes.h" |
#include "base/compiler_specific.h" |
+#include "base/lazy_instance.h" |
#include "base/logging.h" |
+#include "base/memory/discardable_memory.h" |
+#include "base/memory/discardable_memory_emulated.h" |
#include "base/memory/scoped_ptr.h" |
namespace base { |
@@ -22,26 +23,38 @@ const int kDiscardableMemoryTag = VM_MAKE_TAG(252); |
class DiscardableMemoryMac : public DiscardableMemory { |
public: |
- DiscardableMemoryMac(void* memory, size_t size) |
- : memory_(memory), |
+ explicit DiscardableMemoryMac(size_t size) |
+ : buffer_(0), |
size_(size) { |
- DCHECK(memory_); |
+ } |
+ |
+ bool Initialize() { |
Philippe
2013/12/17 14:28:21
Are you making this change for consistency with th
reveman
2013/12/18 08:12:38
This is for consistency. I might also move this im
|
+ kern_return_t ret = vm_allocate(mach_task_self(), |
+ &buffer_, |
+ size_, |
+ VM_FLAGS_PURGABLE | |
+ VM_FLAGS_ANYWHERE | |
+ kDiscardableMemoryTag); |
+ if (ret != KERN_SUCCESS) { |
+ DLOG(ERROR) << "vm_allocate() failed"; |
+ return false; |
+ } |
+ |
+ return true; |
} |
virtual ~DiscardableMemoryMac() { |
- vm_deallocate(mach_task_self(), |
- reinterpret_cast<vm_address_t>(memory_), |
- size_); |
+ if (buffer_) |
+ vm_deallocate(mach_task_self(), buffer_, size_); |
} |
virtual LockDiscardableMemoryStatus Lock() OVERRIDE { |
- DCHECK_EQ(0, mprotect(memory_, size_, PROT_READ | PROT_WRITE)); |
+ DCHECK_EQ(0, mprotect(buffer_, size_, PROT_READ | PROT_WRITE)); |
int state = VM_PURGABLE_NONVOLATILE; |
- kern_return_t ret = vm_purgable_control( |
- mach_task_self(), |
- reinterpret_cast<vm_address_t>(memory_), |
- VM_PURGABLE_SET_STATE, |
- &state); |
+ kern_return_t ret = vm_purgable_control(mach_task_self(), |
+ buffer_, |
+ VM_PURGABLE_SET_STATE, |
+ &state); |
if (ret != KERN_SUCCESS) |
return DISCARDABLE_MEMORY_FAILED; |
@@ -51,50 +64,70 @@ class DiscardableMemoryMac : public DiscardableMemory { |
virtual void Unlock() OVERRIDE { |
int state = VM_PURGABLE_VOLATILE | VM_VOLATILE_GROUP_DEFAULT; |
- kern_return_t ret = vm_purgable_control( |
- mach_task_self(), |
- reinterpret_cast<vm_address_t>(memory_), |
- VM_PURGABLE_SET_STATE, |
- &state); |
- DCHECK_EQ(0, mprotect(memory_, size_, PROT_NONE)); |
+ kern_return_t ret = vm_purgable_control(mach_task_self(), |
+ buffer_, |
+ VM_PURGABLE_SET_STATE, |
+ &state); |
+ DCHECK_EQ(0, mprotect(buffer_, size_, PROT_NONE)); |
if (ret != KERN_SUCCESS) |
DLOG(ERROR) << "Failed to unlock memory."; |
} |
virtual void* Memory() const OVERRIDE { |
- return memory_; |
+ return buffer_; |
} |
private: |
- void* const memory_; |
+ vm_address_t buffer_; |
const size_t size_; |
DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryMac); |
}; |
+struct SupportedTypeVector { |
+ SupportedTypeVector() { |
+ v.push_back(DISCARDABLE_MEMORY_MAC); |
+ v.push_back(DISCARDABLE_MEMORY_EMULATED); |
+ } |
+ std::vector<DiscardableMemoryType> v; |
+}; |
+LazyInstance<SupportedTypeVector>::Leaky g_supported_types = |
+ LAZY_INSTANCE_INITIALIZER; |
+ |
} // namespace |
// static |
-bool DiscardableMemory::SupportedNatively() { |
- return true; |
+const std::vector<DiscardableMemoryType>& |
+ DiscardableMemory::GetSupportedTypes() { |
+ return g_supported_types.Get().v; |
} |
// static |
scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemory( |
size_t size) { |
- vm_address_t buffer = 0; |
- kern_return_t ret = vm_allocate(mach_task_self(), |
- &buffer, |
- size, |
- VM_FLAGS_PURGABLE | |
- VM_FLAGS_ANYWHERE | |
- kDiscardableMemoryTag); |
- if (ret != KERN_SUCCESS) { |
- DLOG(ERROR) << "vm_allocate() failed"; |
- return scoped_ptr<DiscardableMemory>(); |
+ switch (GetType()) { |
+ case DISCARDABLE_MEMORY_NONE: |
+ case DISCARDABLE_MEMORY_ANDROID: |
+ return scoped_ptr<DiscardableMemory>(); |
+ case DISCARDABLE_MEMORY_MAC: { |
+ scoped_ptr<DiscardableMemoryMac> memory(new DiscardableMemoryMac(size)); |
+ if (!memory->Initialize()) |
+ return scoped_ptr<DiscardableMemory>(); |
+ |
+ return memory.PassAs<DiscardableMemory>(); |
+ } |
+ case DISCARDABLE_MEMORY_EMULATED: { |
+ scoped_ptr<internal::DiscardableMemoryEmulated> memory( |
+ new internal::DiscardableMemoryEmulated(size)); |
+ if (!memory->Initialize()) |
+ return scoped_ptr<DiscardableMemory>(); |
+ |
+ return memory.PassAs<DiscardableMemory>(); |
+ } |
} |
- return scoped_ptr<DiscardableMemory>( |
- new DiscardableMemoryMac(reinterpret_cast<void*>(buffer), size)); |
+ |
+ NOTREACHED(); |
+ return scoped_ptr<DiscardableMemory>(); |
} |
// static |
@@ -106,6 +139,7 @@ bool DiscardableMemory::PurgeForTestingSupported() { |
void DiscardableMemory::PurgeForTesting() { |
int state = 0; |
vm_purgable_control(mach_task_self(), 0, VM_PURGABLE_PURGE_ALL, &state); |
+ internal::DiscardableMemoryEmulated::PurgeForTesting(); |
} |
} // namespace base |