| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 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_SHARED_MEMORY_H_ | |
| 6 #define BASE_MEMORY_DISCARDABLE_SHARED_MEMORY_H_ | |
| 7 | |
| 8 #include "base/base_export.h" | |
| 9 #include "base/logging.h" | |
| 10 #include "base/memory/shared_memory.h" | |
| 11 #include "base/threading/thread_collision_warner.h" | |
| 12 #include "base/time/time.h" | |
| 13 | |
| 14 #if DCHECK_IS_ON() | |
| 15 #include <set> | |
| 16 #endif | |
| 17 | |
| 18 // Define DISCARDABLE_SHARED_MEMORY_SHRINKING if platform supports shrinking | |
| 19 // of discardable shared memory segments. | |
| 20 #if defined(OS_POSIX) && !defined(OS_ANDROID) | |
| 21 #define DISCARDABLE_SHARED_MEMORY_SHRINKING | |
| 22 #endif | |
| 23 | |
| 24 namespace base { | |
| 25 | |
| 26 // Platform abstraction for discardable shared memory. | |
| 27 // | |
| 28 // This class is not thread-safe. Clients are responsible for synchronizing | |
| 29 // access to an instance of this class. | |
| 30 class BASE_EXPORT DiscardableSharedMemory { | |
| 31 public: | |
| 32 enum LockResult { SUCCESS, PURGED, FAILED }; | |
| 33 | |
| 34 DiscardableSharedMemory(); | |
| 35 | |
| 36 // Create a new DiscardableSharedMemory object from an existing, open shared | |
| 37 // memory file. Memory must be locked. | |
| 38 explicit DiscardableSharedMemory(SharedMemoryHandle handle); | |
| 39 | |
| 40 // Closes any open files. | |
| 41 virtual ~DiscardableSharedMemory(); | |
| 42 | |
| 43 // Creates and maps a locked DiscardableSharedMemory object with |size|. | |
| 44 // Returns true on success and false on failure. | |
| 45 bool CreateAndMap(size_t size); | |
| 46 | |
| 47 // Maps the locked discardable memory into the caller's address space. | |
| 48 // Returns true on success, false otherwise. | |
| 49 bool Map(size_t size); | |
| 50 | |
| 51 // Unmaps the discardable shared memory from the caller's address space. | |
| 52 // Returns true if successful; returns false on error or if the memory is | |
| 53 // not mapped. | |
| 54 bool Unmap(); | |
| 55 | |
| 56 // The actual size of the mapped memory (may be larger than requested). | |
| 57 size_t mapped_size() const { return mapped_size_; } | |
| 58 | |
| 59 // Returns a shared memory handle for this DiscardableSharedMemory object. | |
| 60 SharedMemoryHandle handle() const { return shared_memory_.handle(); } | |
| 61 | |
| 62 // Locks a range of memory so that it will not be purged by the system. | |
| 63 // The range of memory must be unlocked. The result of trying to lock an | |
| 64 // already locked range is undefined. |offset| and |length| must both be | |
| 65 // a multiple of the page size as returned by GetPageSize(). | |
| 66 // Passing 0 for |length| means "everything onward". | |
| 67 // Returns SUCCESS if range was successfully locked and the memory is still | |
| 68 // resident, PURGED if range was successfully locked but has been purged | |
| 69 // since last time it was locked and FAILED if range could not be locked. | |
| 70 // Locking can fail for two reasons; object might have been purged, our | |
| 71 // last known usage timestamp might be out of date. Last known usage time | |
| 72 // is updated to the actual last usage timestamp if memory is still resident | |
| 73 // or 0 if not. | |
| 74 LockResult Lock(size_t offset, size_t length); | |
| 75 | |
| 76 // Unlock a previously successfully locked range of memory. The range of | |
| 77 // memory must be locked. The result of trying to unlock a not | |
| 78 // previously locked range is undefined. | |
| 79 // |offset| and |length| must both be a multiple of the page size as returned | |
| 80 // by GetPageSize(). | |
| 81 // Passing 0 for |length| means "everything onward". | |
| 82 void Unlock(size_t offset, size_t length); | |
| 83 | |
| 84 // Gets a pointer to the opened discardable memory space. Discardable memory | |
| 85 // must have been mapped via Map(). | |
| 86 void* memory() const; | |
| 87 | |
| 88 // Returns the last known usage time for DiscardableSharedMemory object. This | |
| 89 // may be earlier than the "true" usage time when memory has been used by a | |
| 90 // different process. Returns NULL time if purged. | |
| 91 Time last_known_usage() const { return last_known_usage_; } | |
| 92 | |
| 93 // This returns true and sets |last_known_usage_| to 0 if | |
| 94 // DiscardableSharedMemory object was successfully purged. Purging can fail | |
| 95 // for two reasons; object might be locked or our last known usage timestamp | |
| 96 // might be out of date. Last known usage time is updated to |current_time| | |
| 97 // if locked or the actual last usage timestamp if unlocked. It is often | |
| 98 // necessary to call this function twice for the object to successfully be | |
| 99 // purged. First call, updates |last_known_usage_|. Second call, successfully | |
| 100 // purges the object using the updated |last_known_usage_|. | |
| 101 // Note: there is no guarantee that multiple calls to this function will | |
| 102 // successfully purge object. DiscardableSharedMemory object might be locked | |
| 103 // or another thread/process might be able to lock and unlock it in between | |
| 104 // each call. | |
| 105 bool Purge(Time current_time); | |
| 106 | |
| 107 // Returns true if memory is still resident. | |
| 108 bool IsMemoryResident() const; | |
| 109 | |
| 110 // Closes the open discardable memory segment. | |
| 111 // It is safe to call Close repeatedly. | |
| 112 void Close(); | |
| 113 | |
| 114 // Shares the discardable memory segment to another process. Attempts to | |
| 115 // create a platform-specific |new_handle| which can be used in a remote | |
| 116 // process to access the discardable memory segment. |new_handle| is an | |
| 117 // output parameter to receive the handle for use in the remote process. | |
| 118 // Returns true on success, false otherwise. | |
| 119 bool ShareToProcess(ProcessHandle process_handle, | |
| 120 SharedMemoryHandle* new_handle) { | |
| 121 return shared_memory_.ShareToProcess(process_handle, new_handle); | |
| 122 } | |
| 123 | |
| 124 #if defined(DISCARDABLE_SHARED_MEMORY_SHRINKING) | |
| 125 // Release as much memory as possible to the OS. The change in size will | |
| 126 // be reflected by the return value of mapped_size(). | |
| 127 void Shrink(); | |
| 128 #endif | |
| 129 | |
| 130 private: | |
| 131 // Virtual for tests. | |
| 132 virtual Time Now() const; | |
| 133 | |
| 134 SharedMemory shared_memory_; | |
| 135 size_t mapped_size_; | |
| 136 size_t locked_page_count_; | |
| 137 #if DCHECK_IS_ON() | |
| 138 std::set<size_t> locked_pages_; | |
| 139 #endif | |
| 140 // Implementation is not thread-safe but still usable if clients are | |
| 141 // synchronized somehow. Use a collision warner to detect incorrect usage. | |
| 142 DFAKE_MUTEX(thread_collision_warner_); | |
| 143 Time last_known_usage_; | |
| 144 | |
| 145 DISALLOW_COPY_AND_ASSIGN(DiscardableSharedMemory); | |
| 146 }; | |
| 147 | |
| 148 } // namespace base | |
| 149 | |
| 150 #endif // BASE_MEMORY_DISCARDABLE_SHARED_MEMORY_H_ | |
| OLD | NEW |