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 3 // found in the LICENSE file. 4 5 #ifndef BASE_MEMORY_DISCARDABLE_MEMORY_H_ 6 #define BASE_MEMORY_DISCARDABLE_MEMORY_H_ 7 8 #include "base/base_export.h" 9 #include "base/basictypes.h" 10 #include "base/compiler_specific.h" 11 12 namespace base { 13 14 enum LockDiscardableMemoryStatus { 15 DISCARDABLE_MEMORY_FAILED = -1, 16 DISCARDABLE_MEMORY_PURGED = 0, 17 DISCARDABLE_MEMORY_SUCCESS = 1 18 }; 19 20 // Platform abstraction for discardable memory. DiscardableMemory is used to 21 // cache large objects without worrying about blowing out memory, both on mobile 22 // devices where there is no swap, and desktop devices where unused free memory 23 // should be used to help the user experience. This is preferable to releasing 24 // memory in response to an OOM signal because it is simpler, though it has less 25 // flexibility as to which objects get discarded. 26 // 27 // Discardable memory has two states: locked and unlocked. While the memory is 28 // locked, it will not be discarded. Unlocking the memory allows the OS to 29 // reclaim it if needed. Locks do not nest. 30 // 31 // Notes: 32 // - The paging behavior of memory while it is locked is not specified. While 33 // mobile platforms will not swap it out, it may qualify for swapping 34 // on desktop platforms. It is not expected that this will matter, as the 35 // preferred pattern of usage for DiscardableMemory is to lock down the 36 // memory, use it as quickly as possible, and then unlock it. 37 // - Because of memory alignment, the amount of memory allocated can be 38 // larger than the requested memory size. It is not very efficient for 39 // small allocations. 40 // 41 // References: 42 // - Linux: http://lwn.net/Articles/452035/ 43 // - Mac: http://trac.webkit.org/browser/trunk/Source/WebCore/platform/mac/PurgeableBufferMac.cpp 44 // the comment starting with "vm_object_purgable_control" at 45 // http://www.opensource.apple.com/source/xnu/xnu-792.13.8/osfmk/vm/vm_object.c 46 class BASE_EXPORT DiscardableMemory { 47 public: 48 DiscardableMemory(); 49 50 // If the discardable memory is locked, the destructor will unlock it. 51 // The opened file will also be closed after this. 52 ~DiscardableMemory(); 53 54 // Check whether the system supports discardable memory. 55 static bool Supported(); 56 57 // Initialize the DiscardableMemory object. On success, this function returns 58 // true and the memory is locked. This should only be called once. 59 // This call could fail because of platform-specific limitations and the user 60 // should stop using the DiscardableMemory afterwards. 61 bool InitializeAndLock(size_t size); 62 63 // Lock the memory so that it will not be purged by the system. Returns 64 // DISCARDABLE_MEMORY_SUCCESS on success. If the return value is 65 // DISCARDABLE_MEMORY_FAILED then this object should be discarded and 66 // a new one should be created. If the return value is 67 // DISCARDABLE_MEMORY_PURGED then the memory is present but any data that 68 // was in it is gone. 69 LockDiscardableMemoryStatus Lock() WARN_UNUSED_RESULT; 70 71 // Unlock the memory so that it can be purged by the system. Must be called 72 // after every successful lock call. 73 void Unlock(); 74 75 // Return the memory address held by this object. The object must be locked 76 // before calling this. Otherwise, this will cause a DCHECK error. 77 void* Memory() const; 78 79 // Testing utility calls. 80 81 // Check whether a purge of all discardable memory in the system is supported. 82 // Use only for testing! 83 static bool PurgeForTestingSupported(); 84 85 // Purge all discardable memory in the system. This call has global effects 86 // across all running processes, so it should only be used for testing! 87 static void PurgeForTesting(); 88 89 private: 90 #if defined(OS_ANDROID) 91 // Maps the discardable memory into the caller's address space. 92 // Returns true on success, false otherwise. 93 bool Map(); 94 95 // Unmaps the discardable memory from the caller's address space. 96 void Unmap(); 97 98 // Reserve a file descriptor. When reaching the fd limit, this call returns 99 // false and initialization should fail. 100 bool ReserveFileDescriptor(); 101 102 // Release a file descriptor so that others can reserve it. 103 void ReleaseFileDescriptor(); 104 #endif // OS_ANDROID 105 106 void* memory_; 107 size_t size_; 108 bool is_locked_; 109 #if defined(OS_ANDROID) 110 int fd_; 111 #endif // OS_ANDROID 112 113 DISALLOW_COPY_AND_ASSIGN(DiscardableMemory); 114 }; 115 116 } // namespace base 117 118 #endif // BASE_MEMORY_DISCARDABLE_MEMORY_H_ 119