/work/obj-fuzz/dist/include/mozilla/VolatileBuffer.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | | |
5 | | #ifndef mozalloc_VolatileBuffer_h |
6 | | #define mozalloc_VolatileBuffer_h |
7 | | |
8 | | #include "mozilla/mozalloc.h" |
9 | | #include "mozilla/Mutex.h" |
10 | | #include "mozilla/RefPtr.h" |
11 | | #include "mozilla/MemoryReporting.h" |
12 | | #include "mozilla/RefCounted.h" |
13 | | |
14 | | /* VolatileBuffer |
15 | | * |
16 | | * This class represents a piece of memory that can potentially be reclaimed |
17 | | * by the OS when not in use. As long as there are one or more |
18 | | * VolatileBufferPtrs holding on to a VolatileBuffer, the memory will remain |
19 | | * available. However, when there are no VolatileBufferPtrs holding a |
20 | | * VolatileBuffer, the OS can purge the pages if it wants to. The OS can make |
21 | | * better decisions about what pages to purge than we can. |
22 | | * |
23 | | * VolatileBuffers may not always be volatile - if the allocation is too small, |
24 | | * or if the OS doesn't support the feature, or if the OS doesn't want to, |
25 | | * the buffer will be allocated on heap. |
26 | | * |
27 | | * VolatileBuffer allocations are fallible. They are intended for uses where |
28 | | * one may allocate large buffers for caching data. Init() must be called |
29 | | * exactly once. |
30 | | * |
31 | | * After getting a reference to VolatileBuffer using VolatileBufferPtr, |
32 | | * WasPurged() can be used to check if the OS purged any pages in the buffer. |
33 | | * The OS cannot purge a buffer immediately after a VolatileBuffer is |
34 | | * initialized. At least one VolatileBufferPtr must be created before the |
35 | | * buffer can be purged, so the first use of VolatileBufferPtr does not need |
36 | | * to check WasPurged(). |
37 | | * |
38 | | * When a buffer is purged, some or all of the buffer is zeroed out. This |
39 | | * API cannot tell which parts of the buffer were lost. |
40 | | * |
41 | | * VolatileBuffer and VolatileBufferPtr are threadsafe. |
42 | | */ |
43 | | |
44 | | namespace mozilla { |
45 | | |
46 | | class VolatileBuffer |
47 | | { |
48 | | friend class VolatileBufferPtr_base; |
49 | | public: |
50 | | MOZ_DECLARE_REFCOUNTED_TYPENAME(VolatileBuffer) |
51 | | NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VolatileBuffer) |
52 | | |
53 | | VolatileBuffer(); |
54 | | |
55 | | /* aAlignment must be a multiple of the pointer size */ |
56 | | bool Init(size_t aSize, size_t aAlignment = sizeof(void*)); |
57 | | |
58 | | size_t HeapSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const; |
59 | | size_t NonHeapSizeOfExcludingThis() const; |
60 | | bool OnHeap() const; |
61 | | |
62 | | protected: |
63 | | bool Lock(void** aBuf); |
64 | | void Unlock(); |
65 | | |
66 | | private: |
67 | | ~VolatileBuffer(); |
68 | | |
69 | | /** |
70 | | * Protects mLockCount, mFirstLock, and changes to the volatility of our |
71 | | * buffer. Other member variables are read-only except in Init() and the |
72 | | * destructor. |
73 | | */ |
74 | | Mutex mMutex; |
75 | | |
76 | | void* mBuf; |
77 | | size_t mSize; |
78 | | int mLockCount; |
79 | | #if defined(ANDROID) |
80 | | int mFd; |
81 | | #elif defined(XP_DARWIN) |
82 | | bool mHeap; |
83 | | #elif defined(XP_WIN) |
84 | | bool mHeap; |
85 | | bool mFirstLock; |
86 | | #endif |
87 | | }; |
88 | | |
89 | | class VolatileBufferPtr_base { |
90 | | public: |
91 | | explicit VolatileBufferPtr_base(VolatileBuffer* vbuf) |
92 | | : mVBuf(vbuf) |
93 | | , mMapping(nullptr) |
94 | | , mPurged(false) |
95 | 0 | { |
96 | 0 | Lock(); |
97 | 0 | } |
98 | | |
99 | 0 | ~VolatileBufferPtr_base() { |
100 | 0 | Unlock(); |
101 | 0 | } |
102 | | |
103 | 0 | bool WasBufferPurged() const { |
104 | 0 | return mPurged; |
105 | 0 | } |
106 | | |
107 | | protected: |
108 | | RefPtr<VolatileBuffer> mVBuf; |
109 | | void* mMapping; |
110 | | |
111 | 0 | void Set(VolatileBuffer* vbuf) { |
112 | 0 | Unlock(); |
113 | 0 | mVBuf = vbuf; |
114 | 0 | Lock(); |
115 | 0 | } |
116 | | |
117 | | private: |
118 | | bool mPurged; |
119 | | |
120 | 0 | void Lock() { |
121 | 0 | if (mVBuf) { |
122 | 0 | mPurged = !mVBuf->Lock(&mMapping); |
123 | 0 | } else { |
124 | 0 | mMapping = nullptr; |
125 | 0 | mPurged = false; |
126 | 0 | } |
127 | 0 | } |
128 | | |
129 | 0 | void Unlock() { |
130 | 0 | if (mVBuf) { |
131 | 0 | mVBuf->Unlock(); |
132 | 0 | } |
133 | 0 | } |
134 | | }; |
135 | | |
136 | | template <class T> |
137 | | class VolatileBufferPtr : public VolatileBufferPtr_base |
138 | | { |
139 | | public: |
140 | 0 | explicit VolatileBufferPtr(VolatileBuffer* vbuf) : VolatileBufferPtr_base(vbuf) {} |
141 | 0 | VolatileBufferPtr() : VolatileBufferPtr_base(nullptr) {} |
142 | | |
143 | | VolatileBufferPtr(VolatileBufferPtr&& aOther) |
144 | | : VolatileBufferPtr_base(aOther.mVBuf) |
145 | | { |
146 | | aOther.Set(nullptr); |
147 | | } |
148 | | |
149 | 0 | operator T*() const { |
150 | 0 | return (T*) mMapping; |
151 | 0 | } Unexecuted instantiation: mozilla::VolatileBufferPtr<unsigned char>::operator unsigned char*() const Unexecuted instantiation: mozilla::VolatileBufferPtr<char>::operator char*() const |
152 | | |
153 | | VolatileBufferPtr& operator=(VolatileBuffer* aVBuf) |
154 | 0 | { |
155 | 0 | Set(aVBuf); |
156 | 0 | return *this; |
157 | 0 | } |
158 | | |
159 | | VolatileBufferPtr& operator=(VolatileBufferPtr&& aOther) |
160 | | { |
161 | | MOZ_ASSERT(this != &aOther, "Self-moves are prohibited"); |
162 | | Set(aOther.mVBuf); |
163 | | aOther.Set(nullptr); |
164 | | return *this; |
165 | | } |
166 | | |
167 | | private: |
168 | | VolatileBufferPtr(VolatileBufferPtr const& vbufptr) = delete; |
169 | | }; |
170 | | |
171 | | } // namespace mozilla |
172 | | |
173 | | #endif /* mozalloc_VolatileBuffer_h */ |