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

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: 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"
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"
10 #include "base/lazy_instance.h"
12 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/discardable_memory.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() {
Philippe 2013/12/17 14:28:21 Are you making this change for consistency with th
reveman 2013/12/18 08:12:38 This is for consistency. I might also move this im
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 LockDiscardableMemoryStatus 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_PURGED
49 : DISCARDABLE_MEMORY_SUCCESS; 62 : DISCARDABLE_MEMORY_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
87 struct SupportedTypeVector {
88 SupportedTypeVector() {
89 v.push_back(DISCARDABLE_MEMORY_MAC);
90 v.push_back(DISCARDABLE_MEMORY_EMULATED);
91 }
92 std::vector<DiscardableMemoryType> v;
93 };
94 LazyInstance<SupportedTypeVector>::Leaky g_supported_types =
95 LAZY_INSTANCE_INITIALIZER;
96
75 } // namespace 97 } // namespace
76 98
77 // static 99 // static
78 bool DiscardableMemory::SupportedNatively() { 100 const std::vector<DiscardableMemoryType>&
79 return true; 101 DiscardableMemory::GetSupportedTypes() {
102 return g_supported_types.Get().v;
80 } 103 }
81 104
82 // static 105 // static
83 scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemory( 106 scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemory(
84 size_t size) { 107 size_t size) {
85 vm_address_t buffer = 0; 108 switch (GetType()) {
86 kern_return_t ret = vm_allocate(mach_task_self(), 109 case DISCARDABLE_MEMORY_NONE:
87 &buffer, 110 case DISCARDABLE_MEMORY_ANDROID:
88 size, 111 return scoped_ptr<DiscardableMemory>();
89 VM_FLAGS_PURGABLE | 112 case DISCARDABLE_MEMORY_MAC: {
90 VM_FLAGS_ANYWHERE | 113 scoped_ptr<DiscardableMemoryMac> memory(new DiscardableMemoryMac(size));
91 kDiscardableMemoryTag); 114 if (!memory->Initialize())
92 if (ret != KERN_SUCCESS) { 115 return scoped_ptr<DiscardableMemory>();
93 DLOG(ERROR) << "vm_allocate() failed"; 116
94 return scoped_ptr<DiscardableMemory>(); 117 return memory.PassAs<DiscardableMemory>();
118 }
119 case DISCARDABLE_MEMORY_EMULATED: {
120 scoped_ptr<internal::DiscardableMemoryEmulated> memory(
121 new internal::DiscardableMemoryEmulated(size));
122 if (!memory->Initialize())
123 return scoped_ptr<DiscardableMemory>();
124
125 return memory.PassAs<DiscardableMemory>();
126 }
95 } 127 }
96 return scoped_ptr<DiscardableMemory>( 128
97 new DiscardableMemoryMac(reinterpret_cast<void*>(buffer), size)); 129 NOTREACHED();
130 return scoped_ptr<DiscardableMemory>();
98 } 131 }
99 132
100 // static 133 // static
101 bool DiscardableMemory::PurgeForTestingSupported() { 134 bool DiscardableMemory::PurgeForTestingSupported() {
102 return true; 135 return true;
103 } 136 }
104 137
105 // static 138 // static
106 void DiscardableMemory::PurgeForTesting() { 139 void DiscardableMemory::PurgeForTesting() {
107 int state = 0; 140 int state = 0;
108 vm_purgable_control(mach_task_self(), 0, VM_PURGABLE_PURGE_ALL, &state); 141 vm_purgable_control(mach_task_self(), 0, VM_PURGABLE_PURGE_ALL, &state);
142 internal::DiscardableMemoryEmulated::PurgeForTesting();
109 } 143 }
110 144
111 } // namespace base 145 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698