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

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

Issue 261993003: base: Use DiscardableMemoryManager on MacOSX. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 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/lazy_instance.h"
12 #include "base/logging.h" 13 #include "base/logging.h"
13 #include "base/memory/discardable_memory_emulated.h" 14 #include "base/memory/discardable_memory_emulated.h"
14 #include "base/memory/discardable_memory_malloc.h" 15 #include "base/memory/discardable_memory_malloc.h"
16 #include "base/memory/discardable_memory_manager.h"
15 #include "base/memory/scoped_ptr.h" 17 #include "base/memory/scoped_ptr.h"
16 18
17 namespace base { 19 namespace base {
18 namespace { 20 namespace {
19 21
22 // For Mac, have the DiscardableMemoryManager trigger userspace eviction when
23 // address space usage gets too high (e.g. 512 MBytes).
24 const size_t kMacMemoryLimit = 512 * 1024 * 1024;
25
26 struct SharedState {
27 SharedState() : manager(kMacMemoryLimit, kMacMemoryLimit) {}
28
29 internal::DiscardableMemoryManager manager;
30 };
31 LazyInstance<SharedState>::Leaky g_shared_state = LAZY_INSTANCE_INITIALIZER;
32
20 // The VM subsystem allows tagging of memory and 240-255 is reserved for 33 // The VM subsystem allows tagging of memory and 240-255 is reserved for
21 // application use (see mach/vm_statistics.h). Pick 252 (after chromium's atomic 34 // application use (see mach/vm_statistics.h). Pick 252 (after chromium's atomic
22 // weight of ~52). 35 // weight of ~52).
23 const int kDiscardableMemoryTag = VM_MAKE_TAG(252); 36 const int kDiscardableMemoryTag = VM_MAKE_TAG(252);
24 37
25 class DiscardableMemoryMac : public DiscardableMemory { 38 class DiscardableMemoryMac
39 : public DiscardableMemory,
40 public internal::DiscardableMemoryManagerAllocation {
26 public: 41 public:
27 explicit DiscardableMemoryMac(size_t size) 42 explicit DiscardableMemoryMac(size_t bytes)
28 : buffer_(0), 43 : buffer_(0), bytes_(bytes), is_locked_(false) {
29 size_(size) { 44 g_shared_state.Pointer()->manager.Register(this, bytes);
30 } 45 }
31 46
32 bool Initialize() { 47 bool Initialize() { return Lock() == DISCARDABLE_MEMORY_LOCK_STATUS_PURGED; }
33 kern_return_t ret = vm_allocate(mach_task_self(),
34 &buffer_,
35 size_,
36 VM_FLAGS_PURGABLE |
37 VM_FLAGS_ANYWHERE |
38 kDiscardableMemoryTag);
39 if (ret != KERN_SUCCESS) {
40 DLOG(ERROR) << "vm_allocate() failed";
41 return false;
42 }
43 48
44 return true; 49 virtual ~DiscardableMemoryMac() {
50 if (is_locked_)
51 Unlock();
52 g_shared_state.Pointer()->manager.Unregister(this);
53 if (buffer_)
54 vm_deallocate(mach_task_self(), buffer_, bytes_);
45 } 55 }
46 56
47 virtual ~DiscardableMemoryMac() { 57 // Overridden from DiscardableMemory:
48 if (buffer_) 58 virtual DiscardableMemoryLockStatus Lock() OVERRIDE {
49 vm_deallocate(mach_task_self(), buffer_, size_); 59 DCHECK(!is_locked_);
60
61 bool purged = false;
62 if (!g_shared_state.Pointer()->manager.AcquireLock(this, &purged))
63 return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
64
65 is_locked_ = true;
66 return purged ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED
67 : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS;
68 }
69 virtual void Unlock() OVERRIDE {
70 DCHECK(is_locked_);
71 g_shared_state.Pointer()->manager.ReleaseLock(this);
72 is_locked_ = false;
73 }
74 virtual void* Memory() const OVERRIDE {
75 DCHECK(is_locked_);
76 return reinterpret_cast<void*>(buffer_);
50 } 77 }
51 78
52 virtual DiscardableMemoryLockStatus Lock() OVERRIDE { 79 // Overridden from internal::DiscardableMemoryManagerAllocation:
53 DCHECK_EQ(0, mprotect(reinterpret_cast<void*>(buffer_), 80 virtual bool AllocateAndAcquireLock() OVERRIDE {
54 size_, 81 if (!buffer_) {
55 PROT_READ | PROT_WRITE)); 82 kern_return_t ret = vm_allocate(
83 mach_task_self(),
84 &buffer_,
85 bytes_,
86 VM_FLAGS_PURGABLE | VM_FLAGS_ANYWHERE | kDiscardableMemoryTag);
87 if (ret != KERN_SUCCESS) {
88 DLOG(ERROR) << "vm_allocate() failed";
89 return false;
90 }
91 }
92 #if !defined(NDEBUG)
93 int status = mprotect(
94 reinterpret_cast<void*>(buffer_), bytes_, PROT_READ | PROT_WRITE);
95 DCHECK_EQ(0, status);
96 #endif
56 int state = VM_PURGABLE_NONVOLATILE; 97 int state = VM_PURGABLE_NONVOLATILE;
57 kern_return_t ret = vm_purgable_control(mach_task_self(), 98 kern_return_t ret = vm_purgable_control(mach_task_self(),
58 buffer_, 99 buffer_,
59 VM_PURGABLE_SET_STATE, 100 VM_PURGABLE_SET_STATE,
60 &state); 101 &state);
61 if (ret != KERN_SUCCESS) 102 if (ret != KERN_SUCCESS)
62 return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED; 103 return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
63 104
64 return state & VM_PURGABLE_EMPTY ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED 105 return state & VM_PURGABLE_EMPTY ? false : true;
65 : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS;
66 } 106 }
67 107 virtual void ReleaseLock() OVERRIDE {
68 virtual void Unlock() OVERRIDE {
69 int state = VM_PURGABLE_VOLATILE | VM_VOLATILE_GROUP_DEFAULT; 108 int state = VM_PURGABLE_VOLATILE | VM_VOLATILE_GROUP_DEFAULT;
70 kern_return_t ret = vm_purgable_control(mach_task_self(), 109 kern_return_t ret = vm_purgable_control(mach_task_self(),
71 buffer_, 110 buffer_,
72 VM_PURGABLE_SET_STATE, 111 VM_PURGABLE_SET_STATE,
73 &state); 112 &state);
74 DCHECK_EQ(0, mprotect(reinterpret_cast<void*>(buffer_), size_, PROT_NONE));
75 if (ret != KERN_SUCCESS) 113 if (ret != KERN_SUCCESS)
76 DLOG(ERROR) << "Failed to unlock memory."; 114 DLOG(ERROR) << "Failed to unlock memory.";
115 #if !defined(NDEBUG)
116 int status = mprotect(reinterpret_cast<void*>(buffer_), bytes_, PROT_NONE);
117 DCHECK_EQ(0, status);
118 #endif
77 } 119 }
78 120 virtual void Purge() OVERRIDE {
79 virtual void* Memory() const OVERRIDE { 121 if (buffer_) {
80 return reinterpret_cast<void*>(buffer_); 122 vm_deallocate(mach_task_self(), buffer_, bytes_);
123 buffer_ = 0;
124 }
81 } 125 }
82 126
83 private: 127 private:
84 vm_address_t buffer_; 128 vm_address_t buffer_;
85 const size_t size_; 129 const size_t bytes_;
130 bool is_locked_;
86 131
87 DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryMac); 132 DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryMac);
88 }; 133 };
89 134
90 } // namespace 135 } // namespace
91 136
92 // static 137 // static
93 void DiscardableMemory::RegisterMemoryPressureListeners() { 138 void DiscardableMemory::RegisterMemoryPressureListeners() {
94 internal::DiscardableMemoryEmulated::RegisterMemoryPressureListeners(); 139 internal::DiscardableMemoryEmulated::RegisterMemoryPressureListeners();
95 } 140 }
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 } 192 }
148 193
149 // static 194 // static
150 void DiscardableMemory::PurgeForTesting() { 195 void DiscardableMemory::PurgeForTesting() {
151 int state = 0; 196 int state = 0;
152 vm_purgable_control(mach_task_self(), 0, VM_PURGABLE_PURGE_ALL, &state); 197 vm_purgable_control(mach_task_self(), 0, VM_PURGABLE_PURGE_ALL, &state);
153 internal::DiscardableMemoryEmulated::PurgeForTesting(); 198 internal::DiscardableMemoryEmulated::PurgeForTesting();
154 } 199 }
155 200
156 } // namespace base 201 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698