1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/memory/mozalloc/VolatileBufferOSX.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,122 @@ 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 +#include "VolatileBuffer.h" 1.9 +#include "mozilla/Assertions.h" 1.10 +#include "mozilla/DebugOnly.h" 1.11 +#include "mozilla/mozalloc.h" 1.12 + 1.13 +#include <mach/mach.h> 1.14 +#include <sys/mman.h> 1.15 +#include <unistd.h> 1.16 + 1.17 +#define MIN_VOLATILE_ALLOC_SIZE 8192 1.18 + 1.19 +namespace mozilla { 1.20 + 1.21 +VolatileBuffer::VolatileBuffer() 1.22 + : mBuf(nullptr) 1.23 + , mSize(0) 1.24 + , mLockCount(0) 1.25 + , mHeap(false) 1.26 +{ 1.27 +} 1.28 + 1.29 +bool 1.30 +VolatileBuffer::Init(size_t aSize, size_t aAlignment) 1.31 +{ 1.32 + MOZ_ASSERT(!mSize && !mBuf, "Init called twice"); 1.33 + MOZ_ASSERT(!(aAlignment % sizeof(void *)), 1.34 + "Alignment must be multiple of pointer size"); 1.35 + 1.36 + mSize = aSize; 1.37 + 1.38 + kern_return_t ret = 0; 1.39 + if (aSize < MIN_VOLATILE_ALLOC_SIZE) { 1.40 + goto heap_alloc; 1.41 + } 1.42 + 1.43 + ret = vm_allocate(mach_task_self(), 1.44 + (vm_address_t*)&mBuf, 1.45 + mSize, 1.46 + VM_FLAGS_PURGABLE | VM_FLAGS_ANYWHERE); 1.47 + if (ret == KERN_SUCCESS) { 1.48 + return true; 1.49 + } 1.50 + 1.51 +heap_alloc: 1.52 + (void)moz_posix_memalign(&mBuf, aAlignment, aSize); 1.53 + mHeap = true; 1.54 + return !!mBuf; 1.55 +} 1.56 + 1.57 +VolatileBuffer::~VolatileBuffer() 1.58 +{ 1.59 + if (OnHeap()) { 1.60 + free(mBuf); 1.61 + } else { 1.62 + vm_deallocate(mach_task_self(), (vm_address_t)mBuf, mSize); 1.63 + } 1.64 +} 1.65 + 1.66 +bool 1.67 +VolatileBuffer::Lock(void** aBuf) 1.68 +{ 1.69 + MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer"); 1.70 + 1.71 + *aBuf = mBuf; 1.72 + if (++mLockCount > 1 || OnHeap()) { 1.73 + return true; 1.74 + } 1.75 + 1.76 + int state = VM_PURGABLE_NONVOLATILE; 1.77 + kern_return_t ret = 1.78 + vm_purgable_control(mach_task_self(), 1.79 + (vm_address_t)mBuf, 1.80 + VM_PURGABLE_SET_STATE, 1.81 + &state); 1.82 + return ret == KERN_SUCCESS && !(state & VM_PURGABLE_EMPTY); 1.83 +} 1.84 + 1.85 +void 1.86 +VolatileBuffer::Unlock() 1.87 +{ 1.88 + MOZ_ASSERT(mLockCount > 0, "VolatileBuffer unlocked too many times!"); 1.89 + if (--mLockCount || OnHeap()) { 1.90 + return; 1.91 + } 1.92 + 1.93 + int state = VM_PURGABLE_VOLATILE | VM_VOLATILE_GROUP_DEFAULT; 1.94 + DebugOnly<kern_return_t> ret = 1.95 + vm_purgable_control(mach_task_self(), 1.96 + (vm_address_t)mBuf, 1.97 + VM_PURGABLE_SET_STATE, 1.98 + &state); 1.99 + MOZ_ASSERT(ret == KERN_SUCCESS, "Failed to set buffer as purgable"); 1.100 +} 1.101 + 1.102 +bool 1.103 +VolatileBuffer::OnHeap() const 1.104 +{ 1.105 + return mHeap; 1.106 +} 1.107 + 1.108 +size_t 1.109 +VolatileBuffer::HeapSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const 1.110 +{ 1.111 + return OnHeap() ? aMallocSizeOf(mBuf) : 0; 1.112 +} 1.113 + 1.114 +size_t 1.115 +VolatileBuffer::NonHeapSizeOfExcludingThis() const 1.116 +{ 1.117 + if (OnHeap()) { 1.118 + return 0; 1.119 + } 1.120 + 1.121 + unsigned long pagemask = getpagesize() - 1; 1.122 + return (mSize + pagemask) & ~pagemask; 1.123 +} 1.124 + 1.125 +} // namespace mozilla