1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/memory/mozalloc/VolatileBufferAshmem.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,137 @@ 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/NullPtr.h" 1.11 +#include "mozilla/mozalloc.h" 1.12 + 1.13 +#include <fcntl.h> 1.14 +#include <linux/ashmem.h> 1.15 +#include <sys/mman.h> 1.16 +#include <sys/stat.h> 1.17 +#include <sys/types.h> 1.18 +#include <unistd.h> 1.19 + 1.20 +#ifdef MOZ_MEMORY 1.21 +#ifdef MOZ_WIDGET_ANDROID 1.22 +extern "C" int __wrap_posix_memalign(void** memptr, size_t alignment, size_t size); 1.23 +#else 1.24 +extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size); 1.25 +#endif 1.26 +#endif 1.27 + 1.28 +#define MIN_VOLATILE_ALLOC_SIZE 8192 1.29 + 1.30 +namespace mozilla { 1.31 + 1.32 +VolatileBuffer::VolatileBuffer() 1.33 + : mBuf(nullptr) 1.34 + , mSize(0) 1.35 + , mLockCount(0) 1.36 + , mFd(-1) 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 + mFd = open("/" ASHMEM_NAME_DEF, O_RDWR); 1.53 + if (mFd < 0) { 1.54 + goto heap_alloc; 1.55 + } 1.56 + 1.57 + if (ioctl(mFd, ASHMEM_SET_SIZE, mSize) < 0) { 1.58 + close(mFd); 1.59 + mFd = -1; 1.60 + goto heap_alloc; 1.61 + } 1.62 + 1.63 + mBuf = mmap(nullptr, mSize, PROT_READ | PROT_WRITE, MAP_SHARED, mFd, 0); 1.64 + if (mBuf != MAP_FAILED) { 1.65 + return true; 1.66 + } 1.67 + 1.68 +heap_alloc: 1.69 +#ifdef MOZ_MEMORY 1.70 +#ifdef MOZ_WIDGET_ANDROID 1.71 + __wrap_posix_memalign(&mBuf, aAlignment, aSize); 1.72 +#else 1.73 + posix_memalign(&mBuf, aAlignment, aSize); 1.74 +#endif 1.75 +#else 1.76 + mBuf = memalign(aAlignment, aSize); 1.77 +#endif 1.78 + return !!mBuf; 1.79 +} 1.80 + 1.81 +VolatileBuffer::~VolatileBuffer() 1.82 +{ 1.83 + if (OnHeap()) { 1.84 + free(mBuf); 1.85 + } else { 1.86 + munmap(mBuf, mSize); 1.87 + close(mFd); 1.88 + } 1.89 +} 1.90 + 1.91 +bool 1.92 +VolatileBuffer::Lock(void** aBuf) 1.93 +{ 1.94 + MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer"); 1.95 + 1.96 + *aBuf = mBuf; 1.97 + if (++mLockCount > 1 || OnHeap()) { 1.98 + return true; 1.99 + } 1.100 + 1.101 + // Zero offset and zero length means we want to pin/unpin the entire thing. 1.102 + struct ashmem_pin pin = { 0, 0 }; 1.103 + return ioctl(mFd, ASHMEM_PIN, &pin) == ASHMEM_NOT_PURGED; 1.104 +} 1.105 + 1.106 +void 1.107 +VolatileBuffer::Unlock() 1.108 +{ 1.109 + MOZ_ASSERT(mLockCount > 0, "VolatileBuffer unlocked too many times!"); 1.110 + if (--mLockCount || OnHeap()) { 1.111 + return; 1.112 + } 1.113 + 1.114 + struct ashmem_pin pin = { 0, 0 }; 1.115 + ioctl(mFd, ASHMEM_UNPIN, &pin); 1.116 +} 1.117 + 1.118 +bool 1.119 +VolatileBuffer::OnHeap() const 1.120 +{ 1.121 + return mFd < 0; 1.122 +} 1.123 + 1.124 +size_t 1.125 +VolatileBuffer::HeapSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const 1.126 +{ 1.127 + return OnHeap() ? aMallocSizeOf(mBuf) : 0; 1.128 +} 1.129 + 1.130 +size_t 1.131 +VolatileBuffer::NonHeapSizeOfExcludingThis() const 1.132 +{ 1.133 + if (OnHeap()) { 1.134 + return 0; 1.135 + } 1.136 + 1.137 + return (mSize + (PAGE_SIZE - 1)) & PAGE_MASK; 1.138 +} 1.139 + 1.140 +} // namespace mozilla