memory/mozalloc/VolatileBufferWindows.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial