Index: base/memory/discardable_memory_mac.cc |
diff --git a/base/memory/discardable_memory_mac.cc b/base/memory/discardable_memory_mac.cc |
index d7133f57c3d85e582cde4ea5e040ad3c11a75cf1..d8c0ada7e2405c4c5adb7ce2f9bdcde2c6c2ce87 100644 |
--- a/base/memory/discardable_memory_mac.cc |
+++ b/base/memory/discardable_memory_mac.cc |
@@ -5,12 +5,13 @@ |
#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/mac/mach_logging.h" |
+#include "base/mac/scoped_mach_vm.h" |
#include "base/memory/discardable_memory_emulated.h" |
#include "base/memory/discardable_memory_malloc.h" |
#include "base/memory/discardable_memory_manager.h" |
@@ -40,7 +41,9 @@ class DiscardableMemoryMac |
public internal::DiscardableMemoryManagerAllocation { |
public: |
explicit DiscardableMemoryMac(size_t bytes) |
- : buffer_(0), bytes_(bytes), is_locked_(false) { |
+ : memory_(0, 0), |
+ bytes_(mach_vm_round_page(bytes)), |
+ is_locked_(false) { |
g_shared_state.Pointer()->manager.Register(this, bytes); |
} |
@@ -50,8 +53,6 @@ class DiscardableMemoryMac |
if (is_locked_) |
Unlock(); |
g_shared_state.Pointer()->manager.Unregister(this); |
- if (buffer_) |
- vm_deallocate(mach_task_self(), buffer_, bytes_); |
} |
// Overridden from DiscardableMemory: |
@@ -66,64 +67,78 @@ class DiscardableMemoryMac |
return purged ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED |
: DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS; |
} |
+ |
virtual void Unlock() OVERRIDE { |
DCHECK(is_locked_); |
g_shared_state.Pointer()->manager.ReleaseLock(this); |
is_locked_ = false; |
} |
+ |
virtual void* Memory() const OVERRIDE { |
DCHECK(is_locked_); |
- return reinterpret_cast<void*>(buffer_); |
+ return reinterpret_cast<void*>(memory_.address()); |
} |
// Overridden from internal::DiscardableMemoryManagerAllocation: |
virtual bool AllocateAndAcquireLock() OVERRIDE { |
bool persistent = true; |
- if (!buffer_) { |
- kern_return_t ret = vm_allocate( |
+ kern_return_t ret; |
+ if (!memory_.size()) { |
+ vm_address_t address = 0; |
+ ret = vm_allocate( |
mach_task_self(), |
- &buffer_, |
+ &address, |
bytes_, |
- VM_FLAGS_PURGABLE | VM_FLAGS_ANYWHERE | kDiscardableMemoryTag); |
- CHECK_EQ(KERN_SUCCESS, ret) << "wm_allocate() failed."; |
+ VM_FLAGS_ANYWHERE | VM_FLAGS_PURGABLE | kDiscardableMemoryTag); |
+ MACH_CHECK(ret == KERN_SUCCESS, ret) << "vm_allocate"; |
+ memory_.reset(address, bytes_); |
persistent = false; |
} |
+ |
#if !defined(NDEBUG) |
- int status = mprotect( |
- reinterpret_cast<void*>(buffer_), bytes_, PROT_READ | PROT_WRITE); |
- DCHECK_EQ(0, status); |
+ ret = vm_protect(mach_task_self(), |
+ memory_.address(), |
+ memory_.size(), |
+ FALSE, |
+ VM_PROT_DEFAULT); |
+ MACH_DCHECK(ret == KERN_SUCCESS, ret) << "vm_protect"; |
#endif |
+ |
int state = VM_PURGABLE_NONVOLATILE; |
- kern_return_t ret = vm_purgable_control(mach_task_self(), |
- buffer_, |
- VM_PURGABLE_SET_STATE, |
- &state); |
- CHECK_EQ(KERN_SUCCESS, ret) << "Failed to lock memory."; |
+ ret = vm_purgable_control(mach_task_self(), |
+ memory_.address(), |
+ VM_PURGABLE_SET_STATE, |
+ &state); |
+ MACH_CHECK(ret == KERN_SUCCESS, ret) << "vm_purgable_control"; |
if (state & VM_PURGABLE_EMPTY) |
persistent = false; |
return persistent; |
} |
+ |
virtual void ReleaseLock() OVERRIDE { |
int state = VM_PURGABLE_VOLATILE | VM_VOLATILE_GROUP_DEFAULT; |
kern_return_t ret = vm_purgable_control(mach_task_self(), |
- buffer_, |
+ memory_.address(), |
VM_PURGABLE_SET_STATE, |
&state); |
- CHECK_EQ(KERN_SUCCESS, ret) << "Failed to unlock memory."; |
+ MACH_CHECK(ret == KERN_SUCCESS, ret) << "vm_purgable_control"; |
+ |
#if !defined(NDEBUG) |
- int status = mprotect(reinterpret_cast<void*>(buffer_), bytes_, PROT_NONE); |
- DCHECK_EQ(0, status); |
+ ret = vm_protect(mach_task_self(), |
+ memory_.address(), |
+ memory_.size(), |
+ FALSE, |
+ VM_PROT_NONE); |
+ MACH_DCHECK(ret == KERN_SUCCESS, ret) << "vm_protect"; |
#endif |
} |
+ |
virtual void Purge() OVERRIDE { |
- if (buffer_) { |
- vm_deallocate(mach_task_self(), buffer_, bytes_); |
- buffer_ = 0; |
- } |
+ memory_.reset(); |
} |
private: |
- vm_address_t buffer_; |
+ mac::ScopedMachVM memory_; |
const size_t bytes_; |
bool is_locked_; |