memory/mozalloc/VolatileBufferWindows.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:f5ae1962ae58
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 #if defined(XP_WIN)
6 # define MOZALLOC_EXPORT __declspec(dllexport)
7 #endif
8
9 #include "VolatileBuffer.h"
10 #include "mozilla/Assertions.h"
11 #include "mozilla/mozalloc.h"
12 #include "mozilla/WindowsVersion.h"
13
14 #include <windows.h>
15
16 #ifdef MOZ_MEMORY
17 extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size);
18 #endif
19
20 #ifndef MEM_RESET_UNDO
21 #define MEM_RESET_UNDO 0x1000000
22 #endif
23
24 #define MIN_VOLATILE_ALLOC_SIZE 8192
25
26 namespace mozilla {
27
28 VolatileBuffer::VolatileBuffer()
29 : mBuf(nullptr)
30 , mSize(0)
31 , mLockCount(0)
32 , mHeap(false)
33 , mFirstLock(true)
34 {
35 }
36
37 bool
38 VolatileBuffer::Init(size_t aSize, size_t aAlignment)
39 {
40 MOZ_ASSERT(!mSize && !mBuf, "Init called twice");
41 MOZ_ASSERT(!(aAlignment % sizeof(void *)),
42 "Alignment must be multiple of pointer size");
43
44 mSize = aSize;
45 if (aSize < MIN_VOLATILE_ALLOC_SIZE) {
46 goto heap_alloc;
47 }
48
49 static bool sUndoSupported = IsWin8OrLater();
50 if (!sUndoSupported) {
51 goto heap_alloc;
52 }
53
54 mBuf = VirtualAllocEx(GetCurrentProcess(),
55 nullptr,
56 mSize,
57 MEM_COMMIT | MEM_RESERVE,
58 PAGE_READWRITE);
59 if (mBuf) {
60 return true;
61 }
62
63 heap_alloc:
64 #ifdef MOZ_MEMORY
65 posix_memalign(&mBuf, aAlignment, aSize);
66 #else
67 mBuf = _aligned_malloc(aSize, aAlignment);
68 #endif
69 mHeap = true;
70 return !!mBuf;
71 }
72
73 VolatileBuffer::~VolatileBuffer()
74 {
75 if (OnHeap()) {
76 #ifdef MOZ_MEMORY
77 free(mBuf);
78 #else
79 _aligned_free(mBuf);
80 #endif
81 } else {
82 VirtualFreeEx(GetCurrentProcess(), mBuf, 0, MEM_RELEASE);
83 }
84 }
85
86 bool
87 VolatileBuffer::Lock(void** aBuf)
88 {
89 MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer");
90
91 *aBuf = mBuf;
92 if (++mLockCount > 1 || OnHeap()) {
93 return true;
94 }
95
96 // MEM_RESET_UNDO's behavior is undefined when called on memory that
97 // hasn't been MEM_RESET.
98 if (mFirstLock) {
99 mFirstLock = false;
100 return true;
101 }
102
103 void* addr = VirtualAllocEx(GetCurrentProcess(),
104 mBuf,
105 mSize,
106 MEM_RESET_UNDO,
107 PAGE_READWRITE);
108 return !!addr;
109 }
110
111 void
112 VolatileBuffer::Unlock()
113 {
114 MOZ_ASSERT(mLockCount > 0, "VolatileBuffer unlocked too many times!");
115 if (--mLockCount || OnHeap()) {
116 return;
117 }
118
119 void* addr = VirtualAllocEx(GetCurrentProcess(),
120 mBuf,
121 mSize,
122 MEM_RESET,
123 PAGE_READWRITE);
124 MOZ_ASSERT(addr, "Failed to MEM_RESET");
125 }
126
127 bool
128 VolatileBuffer::OnHeap() const
129 {
130 return mHeap;
131 }
132
133 size_t
134 VolatileBuffer::HeapSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
135 {
136 if (OnHeap()) {
137 #ifdef MOZ_MEMORY
138 return aMallocSizeOf(mBuf);
139 #else
140 return mSize;
141 #endif
142 }
143
144 return 0;
145 }
146
147 size_t
148 VolatileBuffer::NonHeapSizeOfExcludingThis() const
149 {
150 if (OnHeap()) {
151 return 0;
152 }
153
154 return (mSize + 4095) & ~4095;
155 }
156
157 } // namespace mozilla

mercurial