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

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: address review feedback Created 6 years, 12 months 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" 5 #include "base/memory/discardable_memory.h"
6 6
7 #include <mach/mach.h> 7 #include <mach/mach.h>
8 #include <sys/mman.h> 8 #include <sys/mman.h>
9 9
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
11 #include "base/compiler_specific.h" 11 #include "base/compiler_specific.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/discardable_memory_emulated.h"
13 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/scoped_ptr.h"
14 15
15 namespace base { 16 namespace base {
16 namespace { 17 namespace {
17 18
18 // The VM subsystem allows tagging of memory and 240-255 is reserved for 19 // 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 20 // application use (see mach/vm_statistics.h). Pick 252 (after chromium's atomic
20 // weight of ~52). 21 // weight of ~52).
21 const int kDiscardableMemoryTag = VM_MAKE_TAG(252); 22 const int kDiscardableMemoryTag = VM_MAKE_TAG(252);
22 23
23 class DiscardableMemoryMac : public DiscardableMemory { 24 class DiscardableMemoryMac : public DiscardableMemory {
24 public: 25 public:
25 DiscardableMemoryMac(void* memory, size_t size) 26 explicit DiscardableMemoryMac(size_t size)
26 : memory_(memory), 27 : buffer_(0),
27 size_(size) { 28 size_(size) {
28 DCHECK(memory_); 29 }
30
31 bool Initialize() {
32 kern_return_t ret = vm_allocate(mach_task_self(),
33 &buffer_,
34 size_,
35 VM_FLAGS_PURGABLE |
36 VM_FLAGS_ANYWHERE |
37 kDiscardableMemoryTag);
38 if (ret != KERN_SUCCESS) {
39 DLOG(ERROR) << "vm_allocate() failed";
40 return false;
41 }
42
43 return true;
29 } 44 }
30 45
31 virtual ~DiscardableMemoryMac() { 46 virtual ~DiscardableMemoryMac() {
32 vm_deallocate(mach_task_self(), 47 if (buffer_)
33 reinterpret_cast<vm_address_t>(memory_), 48 vm_deallocate(mach_task_self(), buffer_, size_);
34 size_);
35 } 49 }
36 50
37 virtual LockDiscardableMemoryStatus Lock() OVERRIDE { 51 virtual DiscardableMemoryLockStatus Lock() OVERRIDE {
38 DCHECK_EQ(0, mprotect(memory_, size_, PROT_READ | PROT_WRITE)); 52 DCHECK_EQ(0, mprotect(buffer_, size_, PROT_READ | PROT_WRITE));
39 int state = VM_PURGABLE_NONVOLATILE; 53 int state = VM_PURGABLE_NONVOLATILE;
40 kern_return_t ret = vm_purgable_control( 54 kern_return_t ret = vm_purgable_control(mach_task_self(),
41 mach_task_self(), 55 buffer_,
42 reinterpret_cast<vm_address_t>(memory_), 56 VM_PURGABLE_SET_STATE,
43 VM_PURGABLE_SET_STATE, 57 &state);
44 &state);
45 if (ret != KERN_SUCCESS) 58 if (ret != KERN_SUCCESS)
46 return DISCARDABLE_MEMORY_FAILED; 59 return DISCARDABLE_MEMORY_FAILED;
47 60
48 return state & VM_PURGABLE_EMPTY ? DISCARDABLE_MEMORY_PURGED 61 return state & VM_PURGABLE_EMPTY ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED
49 : DISCARDABLE_MEMORY_SUCCESS; 62 : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS;
50 } 63 }
51 64
52 virtual void Unlock() OVERRIDE { 65 virtual void Unlock() OVERRIDE {
53 int state = VM_PURGABLE_VOLATILE | VM_VOLATILE_GROUP_DEFAULT; 66 int state = VM_PURGABLE_VOLATILE | VM_VOLATILE_GROUP_DEFAULT;
54 kern_return_t ret = vm_purgable_control( 67 kern_return_t ret = vm_purgable_control(mach_task_self(),
55 mach_task_self(), 68 buffer_,
56 reinterpret_cast<vm_address_t>(memory_), 69 VM_PURGABLE_SET_STATE,
57 VM_PURGABLE_SET_STATE, 70 &state);
58 &state); 71 DCHECK_EQ(0, mprotect(buffer_, size_, PROT_NONE));
59 DCHECK_EQ(0, mprotect(memory_, size_, PROT_NONE));
60 if (ret != KERN_SUCCESS) 72 if (ret != KERN_SUCCESS)
61 DLOG(ERROR) << "Failed to unlock memory."; 73 DLOG(ERROR) << "Failed to unlock memory.";
62 } 74 }
63 75
64 virtual void* Memory() const OVERRIDE { 76 virtual void* Memory() const OVERRIDE {
65 return memory_; 77 return buffer_;
66 } 78 }
67 79
68 private: 80 private:
69 void* const memory_; 81 vm_address_t buffer_;
70 const size_t size_; 82 const size_t size_;
71 83
72 DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryMac); 84 DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryMac);
73 }; 85 };
74 86
75 } // namespace 87 } // namespace
76 88
77 // static 89 // static
78 bool DiscardableMemory::SupportedNatively() { 90 void DiscardableMemory::GetSupportedTypes(
79 return true; 91 std::vector<DiscardableMemoryType>* types) {
92 const DiscardableMemoryType supported_types[] = {
93 DISCARDABLE_MEMORY_TYPE_MAC,
94 DISCARDABLE_MEMORY_TYPE_EMULATED
95 };
96 types->assign(supported_types, supported_types + arraysize(supported_types));
80 } 97 }
81 98
82 // static 99 // static
83 scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemory( 100 scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemory(
84 size_t size) { 101 DiscardableMemoryType type, size_t size) {
85 vm_address_t buffer = 0; 102 switch (type) {
86 kern_return_t ret = vm_allocate(mach_task_self(), 103 case DISCARDABLE_MEMORY_TYPE_NONE:
87 &buffer, 104 case DISCARDABLE_MEMORY_TYPE_ANDROID:
88 size, 105 return scoped_ptr<DiscardableMemory>();
89 VM_FLAGS_PURGABLE | 106 case DISCARDABLE_MEMORY_TYPE_MAC: {
90 VM_FLAGS_ANYWHERE | 107 scoped_ptr<DiscardableMemoryMac> memory(new DiscardableMemoryMac(size));
91 kDiscardableMemoryTag); 108 if (!memory->Initialize())
92 if (ret != KERN_SUCCESS) { 109 return scoped_ptr<DiscardableMemory>();
93 DLOG(ERROR) << "vm_allocate() failed"; 110
94 return scoped_ptr<DiscardableMemory>(); 111 return memory.PassAs<DiscardableMemory>();
112 }
113 case DISCARDABLE_MEMORY_TYPE_EMULATED: {
114 scoped_ptr<internal::DiscardableMemoryEmulated> memory(
115 new internal::DiscardableMemoryEmulated(size));
116 if (!memory->Initialize())
117 return scoped_ptr<DiscardableMemory>();
118
119 return memory.PassAs<DiscardableMemory>();
120 }
95 } 121 }
96 return scoped_ptr<DiscardableMemory>( 122
97 new DiscardableMemoryMac(reinterpret_cast<void*>(buffer), size)); 123 NOTREACHED();
124 return scoped_ptr<DiscardableMemory>();
98 } 125 }
99 126
100 // static 127 // static
101 bool DiscardableMemory::PurgeForTestingSupported() { 128 bool DiscardableMemory::PurgeForTestingSupported() {
102 return true; 129 return true;
103 } 130 }
104 131
105 // static 132 // static
106 void DiscardableMemory::PurgeForTesting() { 133 void DiscardableMemory::PurgeForTesting() {
107 int state = 0; 134 int state = 0;
108 vm_purgable_control(mach_task_self(), 0, VM_PURGABLE_PURGE_ALL, &state); 135 vm_purgable_control(mach_task_self(), 0, VM_PURGABLE_PURGE_ALL, &state);
136 internal::DiscardableMemoryEmulated::PurgeForTesting();
109 } 137 }
110 138
111 } // namespace base 139 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698