Index: base/memory/discardable_memory_mac.cc |
diff --git a/base/memory/discardable_memory_mac.cc b/base/memory/discardable_memory_mac.cc |
index 1dbb6ad1fd2cf67002ddab891e5fd80bb5d6d884..a7f47bbffabd683dde2a767dd6c66216bbc43430 100644 |
--- a/base/memory/discardable_memory_mac.cc |
+++ b/base/memory/discardable_memory_mac.cc |
@@ -5,11 +5,14 @@ |
#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/logging.h" |
+#include "base/memory/scoped_ptr.h" |
namespace base { |
- |
namespace { |
// The VM subsystem allows tagging of memory and 240-255 is reserved for |
@@ -17,25 +20,68 @@ namespace { |
// weight of ~52). |
const int kDiscardableMemoryTag = VM_MAKE_TAG(252); |
-} // namespace |
- |
-// static |
-bool DiscardableMemory::Supported() { |
- return true; |
-} |
+class DiscardableMemoryMac : public DiscardableMemory { |
+ public: |
+ DiscardableMemoryMac(void* memory, size_t size) |
+ : memory_(memory), |
+ size_(size) { |
+ DCHECK(memory_); |
+ } |
-DiscardableMemory::~DiscardableMemory() { |
- if (memory_) { |
+ virtual ~DiscardableMemoryMac() { |
vm_deallocate(mach_task_self(), |
reinterpret_cast<vm_address_t>(memory_), |
size_); |
} |
-} |
-bool DiscardableMemory::InitializeAndLock(size_t size) { |
- DCHECK(!memory_); |
- size_ = size; |
+ virtual LockDiscardableMemoryStatus Lock() OVERRIDE { |
+ DCHECK_EQ(0, mprotect(memory_, 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); |
+ if (ret != KERN_SUCCESS) |
+ return DISCARDABLE_MEMORY_FAILED; |
+ |
+ return state & VM_PURGABLE_EMPTY ? DISCARDABLE_MEMORY_PURGED |
+ : DISCARDABLE_MEMORY_SUCCESS; |
+ } |
+ 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)); |
+ if (ret != KERN_SUCCESS) |
+ DLOG(ERROR) << "Failed to unlock memory."; |
+ } |
+ |
+ virtual void* Memory() const OVERRIDE { |
+ return memory_; |
+ } |
+ |
+ private: |
+ void* const memory_; |
+ const size_t size_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryMac); |
+}; |
+ |
+} // namespace |
+ |
+// static |
+bool DiscardableMemory::Supported() { |
+ return true; |
+} |
+ |
+// static |
+scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemory( |
+ size_t size) { |
vm_address_t buffer = 0; |
kern_return_t ret = vm_allocate(mach_task_self(), |
&buffer, |
@@ -43,49 +89,12 @@ bool DiscardableMemory::InitializeAndLock(size_t size) { |
VM_FLAGS_PURGABLE | |
VM_FLAGS_ANYWHERE | |
kDiscardableMemoryTag); |
- |
if (ret != KERN_SUCCESS) { |
DLOG(ERROR) << "vm_allocate() failed"; |
- return false; |
+ return scoped_ptr<DiscardableMemory>(); |
} |
- |
- is_locked_ = true; |
- memory_ = reinterpret_cast<void*>(buffer); |
- return true; |
-} |
- |
-LockDiscardableMemoryStatus DiscardableMemory::Lock() { |
- DCHECK(!is_locked_); |
- |
- 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); |
- |
- if (ret != KERN_SUCCESS) |
- return DISCARDABLE_MEMORY_FAILED; |
- |
- is_locked_ = true; |
- return state & VM_PURGABLE_EMPTY ? DISCARDABLE_MEMORY_PURGED |
- : DISCARDABLE_MEMORY_SUCCESS; |
-} |
- |
-void DiscardableMemory::Unlock() { |
- DCHECK(is_locked_); |
- |
- 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); |
- |
- if (ret != KERN_SUCCESS) |
- DLOG(ERROR) << "Failed to unlock memory."; |
- |
- is_locked_ = false; |
+ return scoped_ptr<DiscardableMemory>( |
+ new DiscardableMemoryMac(reinterpret_cast<void*>(buffer), size)); |
} |
// static |