Merge mozilla-central to autoland. a=merge CLOSED TREE
[gecko.git] / memory / volatile / VolatileBufferOSX.cpp
blobc6299d1db0637c934e27cf5f5ba3e25d3f04848d
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/. */
5 #include "VolatileBuffer.h"
6 #include "mozilla/Assertions.h"
7 #include "mozilla/DebugOnly.h"
8 #include "mozilla/mozalloc.h"
10 #include <mach/mach.h>
11 #include <sys/mman.h>
12 #include <unistd.h>
14 #define MIN_VOLATILE_ALLOC_SIZE 8192
16 namespace mozilla {
18 VolatileBuffer::VolatileBuffer()
19 : mMutex("VolatileBuffer"),
20 mBuf(nullptr),
21 mSize(0),
22 mLockCount(0),
23 mHeap(false) {}
25 bool VolatileBuffer::Init(size_t aSize, size_t aAlignment) {
26 MOZ_ASSERT(!mSize && !mBuf, "Init called twice");
27 MOZ_ASSERT(!(aAlignment % sizeof(void*)),
28 "Alignment must be multiple of pointer size");
30 mSize = aSize;
32 kern_return_t ret = 0;
33 if (aSize < MIN_VOLATILE_ALLOC_SIZE) {
34 goto heap_alloc;
37 ret = vm_allocate(mach_task_self(), (vm_address_t*)&mBuf, mSize,
38 VM_FLAGS_PURGABLE | VM_FLAGS_ANYWHERE);
39 if (ret == KERN_SUCCESS) {
40 return true;
43 heap_alloc:
44 (void)posix_memalign(&mBuf, aAlignment, aSize);
45 mHeap = true;
46 return !!mBuf;
49 VolatileBuffer::~VolatileBuffer() {
50 MOZ_ASSERT(mLockCount == 0, "Being destroyed with non-zero lock count?");
52 if (OnHeap()) {
53 free(mBuf);
54 } else {
55 vm_deallocate(mach_task_self(), (vm_address_t)mBuf, mSize);
59 bool VolatileBuffer::Lock(void** aBuf) {
60 MutexAutoLock lock(mMutex);
62 MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer");
64 *aBuf = mBuf;
65 if (++mLockCount > 1 || OnHeap()) {
66 return true;
69 int state = VM_PURGABLE_NONVOLATILE;
70 kern_return_t ret = vm_purgable_control(mach_task_self(), (vm_address_t)mBuf,
71 VM_PURGABLE_SET_STATE, &state);
72 return ret == KERN_SUCCESS && !(state & VM_PURGABLE_EMPTY);
75 void VolatileBuffer::Unlock() {
76 MutexAutoLock lock(mMutex);
78 MOZ_ASSERT(mLockCount > 0, "VolatileBuffer unlocked too many times!");
79 if (--mLockCount || OnHeap()) {
80 return;
83 int state = VM_PURGABLE_VOLATILE | VM_VOLATILE_GROUP_DEFAULT;
84 DebugOnly<kern_return_t> ret = vm_purgable_control(
85 mach_task_self(), (vm_address_t)mBuf, VM_PURGABLE_SET_STATE, &state);
86 MOZ_ASSERT(ret == KERN_SUCCESS, "Failed to set buffer as purgable");
89 bool VolatileBuffer::OnHeap() const { return mHeap; }
91 size_t VolatileBuffer::HeapSizeOfExcludingThis(
92 MallocSizeOf aMallocSizeOf) const {
93 return OnHeap() ? aMallocSizeOf(mBuf) : 0;
96 size_t VolatileBuffer::NonHeapSizeOfExcludingThis() const {
97 if (OnHeap()) {
98 return 0;
101 unsigned long pagemask = getpagesize() - 1;
102 return (mSize + pagemask) & ~pagemask;
105 } // namespace mozilla