1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/memory/mozalloc/VolatileBufferWindows.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,157 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#if defined(XP_WIN) 1.9 +# define MOZALLOC_EXPORT __declspec(dllexport) 1.10 +#endif 1.11 + 1.12 +#include "VolatileBuffer.h" 1.13 +#include "mozilla/Assertions.h" 1.14 +#include "mozilla/mozalloc.h" 1.15 +#include "mozilla/WindowsVersion.h" 1.16 + 1.17 +#include <windows.h> 1.18 + 1.19 +#ifdef MOZ_MEMORY 1.20 +extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size); 1.21 +#endif 1.22 + 1.23 +#ifndef MEM_RESET_UNDO 1.24 +#define MEM_RESET_UNDO 0x1000000 1.25 +#endif 1.26 + 1.27 +#define MIN_VOLATILE_ALLOC_SIZE 8192 1.28 + 1.29 +namespace mozilla { 1.30 + 1.31 +VolatileBuffer::VolatileBuffer() 1.32 + : mBuf(nullptr) 1.33 + , mSize(0) 1.34 + , mLockCount(0) 1.35 + , mHeap(false) 1.36 + , mFirstLock(true) 1.37 +{ 1.38 +} 1.39 + 1.40 +bool 1.41 +VolatileBuffer::Init(size_t aSize, size_t aAlignment) 1.42 +{ 1.43 + MOZ_ASSERT(!mSize && !mBuf, "Init called twice"); 1.44 + MOZ_ASSERT(!(aAlignment % sizeof(void *)), 1.45 + "Alignment must be multiple of pointer size"); 1.46 + 1.47 + mSize = aSize; 1.48 + if (aSize < MIN_VOLATILE_ALLOC_SIZE) { 1.49 + goto heap_alloc; 1.50 + } 1.51 + 1.52 + static bool sUndoSupported = IsWin8OrLater(); 1.53 + if (!sUndoSupported) { 1.54 + goto heap_alloc; 1.55 + } 1.56 + 1.57 + mBuf = VirtualAllocEx(GetCurrentProcess(), 1.58 + nullptr, 1.59 + mSize, 1.60 + MEM_COMMIT | MEM_RESERVE, 1.61 + PAGE_READWRITE); 1.62 + if (mBuf) { 1.63 + return true; 1.64 + } 1.65 + 1.66 +heap_alloc: 1.67 +#ifdef MOZ_MEMORY 1.68 + posix_memalign(&mBuf, aAlignment, aSize); 1.69 +#else 1.70 + mBuf = _aligned_malloc(aSize, aAlignment); 1.71 +#endif 1.72 + mHeap = true; 1.73 + return !!mBuf; 1.74 +} 1.75 + 1.76 +VolatileBuffer::~VolatileBuffer() 1.77 +{ 1.78 + if (OnHeap()) { 1.79 +#ifdef MOZ_MEMORY 1.80 + free(mBuf); 1.81 +#else 1.82 + _aligned_free(mBuf); 1.83 +#endif 1.84 + } else { 1.85 + VirtualFreeEx(GetCurrentProcess(), mBuf, 0, MEM_RELEASE); 1.86 + } 1.87 +} 1.88 + 1.89 +bool 1.90 +VolatileBuffer::Lock(void** aBuf) 1.91 +{ 1.92 + MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer"); 1.93 + 1.94 + *aBuf = mBuf; 1.95 + if (++mLockCount > 1 || OnHeap()) { 1.96 + return true; 1.97 + } 1.98 + 1.99 + // MEM_RESET_UNDO's behavior is undefined when called on memory that 1.100 + // hasn't been MEM_RESET. 1.101 + if (mFirstLock) { 1.102 + mFirstLock = false; 1.103 + return true; 1.104 + } 1.105 + 1.106 + void* addr = VirtualAllocEx(GetCurrentProcess(), 1.107 + mBuf, 1.108 + mSize, 1.109 + MEM_RESET_UNDO, 1.110 + PAGE_READWRITE); 1.111 + return !!addr; 1.112 +} 1.113 + 1.114 +void 1.115 +VolatileBuffer::Unlock() 1.116 +{ 1.117 + MOZ_ASSERT(mLockCount > 0, "VolatileBuffer unlocked too many times!"); 1.118 + if (--mLockCount || OnHeap()) { 1.119 + return; 1.120 + } 1.121 + 1.122 + void* addr = VirtualAllocEx(GetCurrentProcess(), 1.123 + mBuf, 1.124 + mSize, 1.125 + MEM_RESET, 1.126 + PAGE_READWRITE); 1.127 + MOZ_ASSERT(addr, "Failed to MEM_RESET"); 1.128 +} 1.129 + 1.130 +bool 1.131 +VolatileBuffer::OnHeap() const 1.132 +{ 1.133 + return mHeap; 1.134 +} 1.135 + 1.136 +size_t 1.137 +VolatileBuffer::HeapSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const 1.138 +{ 1.139 + if (OnHeap()) { 1.140 +#ifdef MOZ_MEMORY 1.141 + return aMallocSizeOf(mBuf); 1.142 +#else 1.143 + return mSize; 1.144 +#endif 1.145 + } 1.146 + 1.147 + return 0; 1.148 +} 1.149 + 1.150 +size_t 1.151 +VolatileBuffer::NonHeapSizeOfExcludingThis() const 1.152 +{ 1.153 + if (OnHeap()) { 1.154 + return 0; 1.155 + } 1.156 + 1.157 + return (mSize + 4095) & ~4095; 1.158 +} 1.159 + 1.160 +} // namespace mozilla