1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/memory/discardable_memory.h"
10 #include "base/basictypes.h"
11 #include "base/compiler_specific.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
18 // The VM subsystem allows tagging of memory and 240-255 is reserved for
19 // application use (see mach/vm_statistics.h). Pick 252 (after chromium's atomic
21 const int kDiscardableMemoryTag
= VM_MAKE_TAG(252);
23 class DiscardableMemoryMac
: public DiscardableMemory
{
25 DiscardableMemoryMac(void* memory
, size_t size
)
31 virtual ~DiscardableMemoryMac() {
32 vm_deallocate(mach_task_self(),
33 reinterpret_cast<vm_address_t
>(memory_
),
37 virtual LockDiscardableMemoryStatus
Lock() OVERRIDE
{
38 DCHECK_EQ(0, mprotect(memory_
, size_
, PROT_READ
| PROT_WRITE
));
39 int state
= VM_PURGABLE_NONVOLATILE
;
40 kern_return_t ret
= vm_purgable_control(
42 reinterpret_cast<vm_address_t
>(memory_
),
43 VM_PURGABLE_SET_STATE
,
45 if (ret
!= KERN_SUCCESS
)
46 return DISCARDABLE_MEMORY_FAILED
;
48 return state
& VM_PURGABLE_EMPTY
? DISCARDABLE_MEMORY_PURGED
49 : DISCARDABLE_MEMORY_SUCCESS
;
52 virtual void Unlock() OVERRIDE
{
53 int state
= VM_PURGABLE_VOLATILE
| VM_VOLATILE_GROUP_DEFAULT
;
54 kern_return_t ret
= vm_purgable_control(
56 reinterpret_cast<vm_address_t
>(memory_
),
57 VM_PURGABLE_SET_STATE
,
59 DCHECK_EQ(0, mprotect(memory_
, size_
, PROT_NONE
));
60 if (ret
!= KERN_SUCCESS
)
61 DLOG(ERROR
) << "Failed to unlock memory.";
64 virtual void* Memory() const OVERRIDE
{
72 DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryMac
);
78 bool DiscardableMemory::SupportedNatively() {
83 scoped_ptr
<DiscardableMemory
> DiscardableMemory::CreateLockedMemory(
85 vm_address_t buffer
= 0;
86 kern_return_t ret
= vm_allocate(mach_task_self(),
91 kDiscardableMemoryTag
);
92 if (ret
!= KERN_SUCCESS
) {
93 DLOG(ERROR
) << "vm_allocate() failed";
94 return scoped_ptr
<DiscardableMemory
>();
96 return scoped_ptr
<DiscardableMemory
>(
97 new DiscardableMemoryMac(reinterpret_cast<void*>(buffer
), size
));
101 bool DiscardableMemory::PurgeForTestingSupported() {
106 void DiscardableMemory::PurgeForTesting() {
108 vm_purgable_control(mach_task_self(), 0, VM_PURGABLE_PURGE_ALL
, &state
);