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 12namespace base { 13 14enum 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 46class 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