Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(107)

Side by Side Diff: base/memory/discardable_memory_mac.cc

Issue 114923005: base: Discardable memory types. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add missing include Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 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.h"
willchan no longer on Chromium 2013/12/24 01:21:06 I'd keep this first.
reveman 2013/12/26 11:46:08 Done.
6
7 #include <mach/mach.h> 5 #include <mach/mach.h>
8 #include <sys/mman.h> 6 #include <sys/mman.h>
9 7
10 #include "base/basictypes.h" 8 #include "base/basictypes.h"
11 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
12 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/memory/discardable_memory.h"
12 #include "base/memory/discardable_memory_emulated.h"
13 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/scoped_ptr.h"
14 14
15 namespace base { 15 namespace base {
16 namespace { 16 namespace {
17 17
18 // The VM subsystem allows tagging of memory and 240-255 is reserved for 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 19 // application use (see mach/vm_statistics.h). Pick 252 (after chromium's atomic
20 // weight of ~52). 20 // weight of ~52).
21 const int kDiscardableMemoryTag = VM_MAKE_TAG(252); 21 const int kDiscardableMemoryTag = VM_MAKE_TAG(252);
22 22
23 class DiscardableMemoryMac : public DiscardableMemory { 23 class DiscardableMemoryMac : public DiscardableMemory {
24 public: 24 public:
25 DiscardableMemoryMac(void* memory, size_t size) 25 explicit DiscardableMemoryMac(size_t size)
26 : memory_(memory), 26 : buffer_(0),
27 size_(size) { 27 size_(size) {
28 DCHECK(memory_); 28 }
29
30 bool Initialize() {
31 kern_return_t ret = vm_allocate(mach_task_self(),
32 &buffer_,
33 size_,
34 VM_FLAGS_PURGABLE |
35 VM_FLAGS_ANYWHERE |
36 kDiscardableMemoryTag);
37 if (ret != KERN_SUCCESS) {
38 DLOG(ERROR) << "vm_allocate() failed";
39 return false;
40 }
41
42 return true;
29 } 43 }
30 44
31 virtual ~DiscardableMemoryMac() { 45 virtual ~DiscardableMemoryMac() {
32 vm_deallocate(mach_task_self(), 46 if (buffer_)
33 reinterpret_cast<vm_address_t>(memory_), 47 vm_deallocate(mach_task_self(), buffer_, size_);
34 size_);
35 } 48 }
36 49
37 virtual LockDiscardableMemoryStatus Lock() OVERRIDE { 50 virtual DiscardableMemoryLockStatus Lock() OVERRIDE {
38 DCHECK_EQ(0, mprotect(memory_, size_, PROT_READ | PROT_WRITE)); 51 DCHECK_EQ(0, mprotect(buffer_, size_, PROT_READ | PROT_WRITE));
39 int state = VM_PURGABLE_NONVOLATILE; 52 int state = VM_PURGABLE_NONVOLATILE;
40 kern_return_t ret = vm_purgable_control( 53 kern_return_t ret = vm_purgable_control(mach_task_self(),
41 mach_task_self(), 54 buffer_,
42 reinterpret_cast<vm_address_t>(memory_), 55 VM_PURGABLE_SET_STATE,
43 VM_PURGABLE_SET_STATE, 56 &state);
44 &state);
45 if (ret != KERN_SUCCESS) 57 if (ret != KERN_SUCCESS)
46 return DISCARDABLE_MEMORY_FAILED; 58 return DISCARDABLE_MEMORY_FAILED;
47 59
48 return state & VM_PURGABLE_EMPTY ? DISCARDABLE_MEMORY_PURGED 60 return state & VM_PURGABLE_EMPTY ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED
49 : DISCARDABLE_MEMORY_SUCCESS; 61 : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS;
50 } 62 }
51 63
52 virtual void Unlock() OVERRIDE { 64 virtual void Unlock() OVERRIDE {
53 int state = VM_PURGABLE_VOLATILE | VM_VOLATILE_GROUP_DEFAULT; 65 int state = VM_PURGABLE_VOLATILE | VM_VOLATILE_GROUP_DEFAULT;
54 kern_return_t ret = vm_purgable_control( 66 kern_return_t ret = vm_purgable_control(mach_task_self(),
55 mach_task_self(), 67 buffer_,
56 reinterpret_cast<vm_address_t>(memory_), 68 VM_PURGABLE_SET_STATE,
57 VM_PURGABLE_SET_STATE, 69 &state);
58 &state); 70 DCHECK_EQ(0, mprotect(buffer_, size_, PROT_NONE));
59 DCHECK_EQ(0, mprotect(memory_, size_, PROT_NONE));
60 if (ret != KERN_SUCCESS) 71 if (ret != KERN_SUCCESS)
61 DLOG(ERROR) << "Failed to unlock memory."; 72 DLOG(ERROR) << "Failed to unlock memory.";
62 } 73 }
63 74
64 virtual void* Memory() const OVERRIDE { 75 virtual void* Memory() const OVERRIDE {
65 return memory_; 76 return buffer_;
66 } 77 }
67 78
68 private: 79 private:
69 void* const memory_; 80 vm_address_t buffer_;
70 const size_t size_; 81 const size_t size_;
71 82
72 DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryMac); 83 DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryMac);
73 }; 84 };
74 85
75 } // namespace 86 } // namespace
76 87
77 // static 88 // static
78 bool DiscardableMemory::SupportedNatively() { 89 void DiscardableMemory::GetSupportedTypes(
79 return true; 90 std::vector<DiscardableMemoryType>* types) {
91 types->push_back(DISCARDABLE_MEMORY_TYPE_MAC);
92 types->push_back(DISCARDABLE_MEMORY_TYPE_EMULATED);
80 } 93 }
81 94
82 // static 95 // static
83 scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemory( 96 scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemory(
84 size_t size) { 97 size_t size) {
85 vm_address_t buffer = 0; 98 switch (GetType()) {
86 kern_return_t ret = vm_allocate(mach_task_self(), 99 case DISCARDABLE_MEMORY_TYPE_NONE:
87 &buffer, 100 case DISCARDABLE_MEMORY_TYPE_ANDROID:
88 size, 101 return scoped_ptr<DiscardableMemory>();
89 VM_FLAGS_PURGABLE | 102 case DISCARDABLE_MEMORY_TYPE_MAC: {
90 VM_FLAGS_ANYWHERE | 103 scoped_ptr<DiscardableMemoryMac> memory(new DiscardableMemoryMac(size));
91 kDiscardableMemoryTag); 104 if (!memory->Initialize())
92 if (ret != KERN_SUCCESS) { 105 return scoped_ptr<DiscardableMemory>();
93 DLOG(ERROR) << "vm_allocate() failed"; 106
94 return scoped_ptr<DiscardableMemory>(); 107 return memory.PassAs<DiscardableMemory>();
108 }
109 case DISCARDABLE_MEMORY_TYPE_EMULATED: {
110 scoped_ptr<internal::DiscardableMemoryEmulated> memory(
111 new internal::DiscardableMemoryEmulated(size));
112 if (!memory->Initialize())
113 return scoped_ptr<DiscardableMemory>();
114
115 return memory.PassAs<DiscardableMemory>();
116 }
95 } 117 }
96 return scoped_ptr<DiscardableMemory>( 118
97 new DiscardableMemoryMac(reinterpret_cast<void*>(buffer), size)); 119 NOTREACHED();
120 return scoped_ptr<DiscardableMemory>();
98 } 121 }
99 122
100 // static 123 // static
101 bool DiscardableMemory::PurgeForTestingSupported() { 124 bool DiscardableMemory::PurgeForTestingSupported() {
102 return true; 125 return true;
103 } 126 }
104 127
105 // static 128 // static
106 void DiscardableMemory::PurgeForTesting() { 129 void DiscardableMemory::PurgeForTesting() {
107 int state = 0; 130 int state = 0;
108 vm_purgable_control(mach_task_self(), 0, VM_PURGABLE_PURGE_ALL, &state); 131 vm_purgable_control(mach_task_self(), 0, VM_PURGABLE_PURGE_ALL, &state);
132 internal::DiscardableMemoryEmulated::PurgeForTesting();
109 } 133 }
110 134
111 } // namespace base 135 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698