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

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 switches::kUseDiscardableMemory to kForwardSwitches Created 6 years, 11 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(reinterpret_cast<void*>(buffer_),
53 size_,
54 PROT_READ | PROT_WRITE));
39 int state = VM_PURGABLE_NONVOLATILE; 55 int state = VM_PURGABLE_NONVOLATILE;
40 kern_return_t ret = vm_purgable_control( 56 kern_return_t ret = vm_purgable_control(mach_task_self(),
41 mach_task_self(), 57 buffer_,
42 reinterpret_cast<vm_address_t>(memory_), 58 VM_PURGABLE_SET_STATE,
43 VM_PURGABLE_SET_STATE, 59 &state);
44 &state);
45 if (ret != KERN_SUCCESS) 60 if (ret != KERN_SUCCESS)
46 return DISCARDABLE_MEMORY_FAILED; 61 return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
47 62
48 return state & VM_PURGABLE_EMPTY ? DISCARDABLE_MEMORY_PURGED 63 return state & VM_PURGABLE_EMPTY ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED
49 : DISCARDABLE_MEMORY_SUCCESS; 64 : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS;
50 } 65 }
51 66
52 virtual void Unlock() OVERRIDE { 67 virtual void Unlock() OVERRIDE {
53 int state = VM_PURGABLE_VOLATILE | VM_VOLATILE_GROUP_DEFAULT; 68 int state = VM_PURGABLE_VOLATILE | VM_VOLATILE_GROUP_DEFAULT;
54 kern_return_t ret = vm_purgable_control( 69 kern_return_t ret = vm_purgable_control(mach_task_self(),
55 mach_task_self(), 70 buffer_,
56 reinterpret_cast<vm_address_t>(memory_), 71 VM_PURGABLE_SET_STATE,
57 VM_PURGABLE_SET_STATE, 72 &state);
58 &state); 73 DCHECK_EQ(0, mprotect(reinterpret_cast<void*>(buffer_), size_, PROT_NONE));
59 DCHECK_EQ(0, mprotect(memory_, size_, PROT_NONE));
60 if (ret != KERN_SUCCESS) 74 if (ret != KERN_SUCCESS)
61 DLOG(ERROR) << "Failed to unlock memory."; 75 DLOG(ERROR) << "Failed to unlock memory.";
62 } 76 }
63 77
64 virtual void* Memory() const OVERRIDE { 78 virtual void* Memory() const OVERRIDE {
65 return memory_; 79 return reinterpret_cast<void*>(buffer_);
66 } 80 }
67 81
68 private: 82 private:
69 void* const memory_; 83 vm_address_t buffer_;
70 const size_t size_; 84 const size_t size_;
71 85
72 DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryMac); 86 DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryMac);
73 }; 87 };
74 88
75 } // namespace 89 } // namespace
76 90
77 // static 91 // static
78 bool DiscardableMemory::SupportedNatively() { 92 void DiscardableMemory::GetSupportedTypes(
79 return true; 93 std::vector<DiscardableMemoryType>* types) {
94 const DiscardableMemoryType supported_types[] = {
95 DISCARDABLE_MEMORY_TYPE_MAC,
96 DISCARDABLE_MEMORY_TYPE_EMULATED
97 };
98 types->assign(supported_types, supported_types + arraysize(supported_types));
80 } 99 }
81 100
82 // static 101 // static
83 scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemory( 102 scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemoryWithType(
84 size_t size) { 103 DiscardableMemoryType type, size_t size) {
85 vm_address_t buffer = 0; 104 switch (type) {
86 kern_return_t ret = vm_allocate(mach_task_self(), 105 case DISCARDABLE_MEMORY_TYPE_NONE:
87 &buffer, 106 case DISCARDABLE_MEMORY_TYPE_ANDROID:
88 size, 107 return scoped_ptr<DiscardableMemory>();
89 VM_FLAGS_PURGABLE | 108 case DISCARDABLE_MEMORY_TYPE_MAC: {
90 VM_FLAGS_ANYWHERE | 109 scoped_ptr<DiscardableMemoryMac> memory(new DiscardableMemoryMac(size));
91 kDiscardableMemoryTag); 110 if (!memory->Initialize())
92 if (ret != KERN_SUCCESS) { 111 return scoped_ptr<DiscardableMemory>();
93 DLOG(ERROR) << "vm_allocate() failed"; 112
94 return scoped_ptr<DiscardableMemory>(); 113 return memory.PassAs<DiscardableMemory>();
114 }
115 case DISCARDABLE_MEMORY_TYPE_EMULATED: {
116 scoped_ptr<internal::DiscardableMemoryEmulated> memory(
117 new internal::DiscardableMemoryEmulated(size));
118 if (!memory->Initialize())
119 return scoped_ptr<DiscardableMemory>();
120
121 return memory.PassAs<DiscardableMemory>();
122 }
95 } 123 }
96 return scoped_ptr<DiscardableMemory>( 124
97 new DiscardableMemoryMac(reinterpret_cast<void*>(buffer), size)); 125 NOTREACHED();
126 return scoped_ptr<DiscardableMemory>();
98 } 127 }
99 128
100 // static 129 // static
101 bool DiscardableMemory::PurgeForTestingSupported() { 130 bool DiscardableMemory::PurgeForTestingSupported() {
102 return true; 131 return true;
103 } 132 }
104 133
105 // static 134 // static
106 void DiscardableMemory::PurgeForTesting() { 135 void DiscardableMemory::PurgeForTesting() {
107 int state = 0; 136 int state = 0;
108 vm_purgable_control(mach_task_self(), 0, VM_PURGABLE_PURGE_ALL, &state); 137 vm_purgable_control(mach_task_self(), 0, VM_PURGABLE_PURGE_ALL, &state);
138 internal::DiscardableMemoryEmulated::PurgeForTesting();
109 } 139 }
110 140
111 } // namespace base 141 } // namespace base
OLDNEW
« no previous file with comments | « base/memory/discardable_memory_linux.cc ('k') | base/memory/discardable_memory_provider_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698