diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /memory/volatile | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'memory/volatile')
-rw-r--r-- | memory/volatile/VolatileBuffer.h | 161 | ||||
-rw-r--r-- | memory/volatile/VolatileBufferAshmem.cpp | 120 | ||||
-rw-r--r-- | memory/volatile/VolatileBufferFallback.cpp | 67 | ||||
-rw-r--r-- | memory/volatile/VolatileBufferOSX.cpp | 105 | ||||
-rw-r--r-- | memory/volatile/VolatileBufferWindows.cpp | 136 | ||||
-rw-r--r-- | memory/volatile/moz.build | 31 | ||||
-rw-r--r-- | memory/volatile/tests/TestVolatileBuffer.cpp | 100 | ||||
-rw-r--r-- | memory/volatile/tests/moz.build | 11 |
8 files changed, 731 insertions, 0 deletions
diff --git a/memory/volatile/VolatileBuffer.h b/memory/volatile/VolatileBuffer.h new file mode 100644 index 0000000000..badd7f3cec --- /dev/null +++ b/memory/volatile/VolatileBuffer.h @@ -0,0 +1,161 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozalloc_VolatileBuffer_h +#define mozalloc_VolatileBuffer_h + +#include "mozilla/mozalloc.h" +#include "mozilla/Mutex.h" +#include "mozilla/RefPtr.h" +#include "mozilla/MemoryReporting.h" +#include "mozilla/RefCounted.h" + +/* VolatileBuffer + * + * This class represents a piece of memory that can potentially be reclaimed + * by the OS when not in use. As long as there are one or more + * VolatileBufferPtrs holding on to a VolatileBuffer, the memory will remain + * available. However, when there are no VolatileBufferPtrs holding a + * VolatileBuffer, the OS can purge the pages if it wants to. The OS can make + * better decisions about what pages to purge than we can. + * + * VolatileBuffers may not always be volatile - if the allocation is too small, + * or if the OS doesn't support the feature, or if the OS doesn't want to, + * the buffer will be allocated on heap. + * + * VolatileBuffer allocations are fallible. They are intended for uses where + * one may allocate large buffers for caching data. Init() must be called + * exactly once. + * + * After getting a reference to VolatileBuffer using VolatileBufferPtr, + * WasPurged() can be used to check if the OS purged any pages in the buffer. + * The OS cannot purge a buffer immediately after a VolatileBuffer is + * initialized. At least one VolatileBufferPtr must be created before the + * buffer can be purged, so the first use of VolatileBufferPtr does not need + * to check WasPurged(). + * + * When a buffer is purged, some or all of the buffer is zeroed out. This + * API cannot tell which parts of the buffer were lost. + * + * VolatileBuffer and VolatileBufferPtr are threadsafe. + */ + +namespace mozilla { + +class VolatileBuffer { + friend class VolatileBufferPtr_base; + + public: + MOZ_DECLARE_REFCOUNTED_TYPENAME(VolatileBuffer) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VolatileBuffer) + + VolatileBuffer(); + + /* aAlignment must be a multiple of the pointer size */ + bool Init(size_t aSize, size_t aAlignment = sizeof(void*)); + + size_t HeapSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const; + size_t NonHeapSizeOfExcludingThis() const; + bool OnHeap() const; + + protected: + bool Lock(void** aBuf); + void Unlock(); + + private: + ~VolatileBuffer(); + + /** + * Protects mLockCount, mFirstLock, and changes to the volatility of our + * buffer. Other member variables are read-only except in Init() and the + * destructor. + */ + Mutex mMutex MOZ_UNANNOTATED; + + void* mBuf; + size_t mSize; + int mLockCount; +#if defined(ANDROID) + int mFd; +#elif defined(XP_DARWIN) + bool mHeap; +#elif defined(XP_WIN) + bool mHeap; + bool mFirstLock; +#endif +}; + +class VolatileBufferPtr_base { + public: + explicit VolatileBufferPtr_base(VolatileBuffer* vbuf) + : mVBuf(vbuf), mMapping(nullptr), mPurged(false) { + Lock(); + } + + ~VolatileBufferPtr_base() { Unlock(); } + + bool WasBufferPurged() const { return mPurged; } + + protected: + RefPtr<VolatileBuffer> mVBuf; + void* mMapping; + + void Set(VolatileBuffer* vbuf) { + Unlock(); + mVBuf = vbuf; + Lock(); + } + + private: + bool mPurged; + + void Lock() { + if (mVBuf) { + mPurged = !mVBuf->Lock(&mMapping); + } else { + mMapping = nullptr; + mPurged = false; + } + } + + void Unlock() { + if (mVBuf) { + mVBuf->Unlock(); + } + } +}; + +template <class T> +class VolatileBufferPtr : public VolatileBufferPtr_base { + public: + explicit VolatileBufferPtr(VolatileBuffer* vbuf) + : VolatileBufferPtr_base(vbuf) {} + VolatileBufferPtr() : VolatileBufferPtr_base(nullptr) {} + + VolatileBufferPtr(VolatileBufferPtr&& aOther) + : VolatileBufferPtr_base(aOther.mVBuf) { + aOther.Set(nullptr); + } + + operator T*() const { return (T*)mMapping; } + + VolatileBufferPtr& operator=(VolatileBuffer* aVBuf) { + Set(aVBuf); + return *this; + } + + VolatileBufferPtr& operator=(VolatileBufferPtr&& aOther) { + MOZ_ASSERT(this != &aOther, "Self-moves are prohibited"); + Set(aOther.mVBuf); + aOther.Set(nullptr); + return *this; + } + + private: + VolatileBufferPtr(VolatileBufferPtr const& vbufptr) = delete; +}; + +} // namespace mozilla + +#endif /* mozalloc_VolatileBuffer_h */ diff --git a/memory/volatile/VolatileBufferAshmem.cpp b/memory/volatile/VolatileBufferAshmem.cpp new file mode 100644 index 0000000000..99a0d1307f --- /dev/null +++ b/memory/volatile/VolatileBufferAshmem.cpp @@ -0,0 +1,120 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "VolatileBuffer.h" +#include "mozilla/Assertions.h" +#include "mozilla/mozalloc.h" + +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include "mozilla/Ashmem.h" + +#ifdef MOZ_MEMORY +extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size); +#endif + +#define MIN_VOLATILE_ALLOC_SIZE 8192 + +namespace mozilla { + +VolatileBuffer::VolatileBuffer() + : mMutex("VolatileBuffer"), + mBuf(nullptr), + mSize(0), + mLockCount(0), + mFd(-1) {} + +bool VolatileBuffer::Init(size_t aSize, size_t aAlignment) { + MOZ_ASSERT(!mSize && !mBuf, "Init called twice"); + MOZ_ASSERT(!(aAlignment % sizeof(void*)), + "Alignment must be multiple of pointer size"); + + mSize = aSize; + if (aSize < MIN_VOLATILE_ALLOC_SIZE) { + goto heap_alloc; + } + + mFd = mozilla::android::ashmem_create(nullptr, mSize); + if (mFd < 0) { + goto heap_alloc; + } + + mBuf = mmap(nullptr, mSize, PROT_READ | PROT_WRITE, MAP_SHARED, mFd, 0); + if (mBuf != MAP_FAILED) { + return true; + } + +heap_alloc: + mBuf = nullptr; + if (mFd >= 0) { + close(mFd); + mFd = -1; + } + +#ifdef MOZ_MEMORY + posix_memalign(&mBuf, aAlignment, aSize); +#else + mBuf = memalign(aAlignment, aSize); +#endif + return !!mBuf; +} + +VolatileBuffer::~VolatileBuffer() { + MOZ_ASSERT(mLockCount == 0, "Being destroyed with non-zero lock count?"); + + if (OnHeap()) { + free(mBuf); + } else { + munmap(mBuf, mSize); + close(mFd); + } +} + +bool VolatileBuffer::Lock(void** aBuf) { + MutexAutoLock lock(mMutex); + + MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer"); + + *aBuf = mBuf; + if (++mLockCount > 1 || OnHeap()) { + return true; + } + + // Zero offset and zero length means we want to pin/unpin the entire thing. + struct ashmem_pin pin = {0, 0}; + return ioctl(mFd, ASHMEM_PIN, &pin) == ASHMEM_NOT_PURGED; +} + +void VolatileBuffer::Unlock() { + MutexAutoLock lock(mMutex); + + MOZ_ASSERT(mLockCount > 0, "VolatileBuffer unlocked too many times!"); + if (--mLockCount || OnHeap()) { + return; + } + + struct ashmem_pin pin = {0, 0}; + ioctl(mFd, ASHMEM_UNPIN, &pin); +} + +bool VolatileBuffer::OnHeap() const { return mFd < 0; } + +size_t VolatileBuffer::HeapSizeOfExcludingThis( + MallocSizeOf aMallocSizeOf) const { + return OnHeap() ? aMallocSizeOf(mBuf) : 0; +} + +size_t VolatileBuffer::NonHeapSizeOfExcludingThis() const { + if (OnHeap()) { + return 0; + } + + return (mSize + (PAGE_SIZE - 1)) & PAGE_MASK; +} + +} // namespace mozilla diff --git a/memory/volatile/VolatileBufferFallback.cpp b/memory/volatile/VolatileBufferFallback.cpp new file mode 100644 index 0000000000..d4311788ff --- /dev/null +++ b/memory/volatile/VolatileBufferFallback.cpp @@ -0,0 +1,67 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "VolatileBuffer.h" +#include "mozilla/Assertions.h" +#include "mozilla/mozalloc.h" + +#ifdef MOZ_MEMORY +int posix_memalign(void** memptr, size_t alignment, size_t size); +#endif + +namespace mozilla { + +VolatileBuffer::VolatileBuffer() + : mMutex("VolatileBuffer"), mBuf(nullptr), mSize(0), mLockCount(0) {} + +bool VolatileBuffer::Init(size_t aSize, size_t aAlignment) { + MOZ_ASSERT(!mSize && !mBuf, "Init called twice"); + MOZ_ASSERT(!(aAlignment % sizeof(void*)), + "Alignment must be multiple of pointer size"); + + mSize = aSize; +#if defined(MOZ_MEMORY) || defined(HAVE_POSIX_MEMALIGN) + if (posix_memalign(&mBuf, aAlignment, aSize) != 0) { + return false; + } +#else +# error "No memalign implementation found" +#endif + return !!mBuf; +} + +VolatileBuffer::~VolatileBuffer() { + MOZ_ASSERT(mLockCount == 0, "Being destroyed with non-zero lock count?"); + + free(mBuf); +} + +bool VolatileBuffer::Lock(void** aBuf) { + MutexAutoLock lock(mMutex); + + MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer"); + + *aBuf = mBuf; + mLockCount++; + + return true; +} + +void VolatileBuffer::Unlock() { + MutexAutoLock lock(mMutex); + + mLockCount--; + MOZ_ASSERT(mLockCount >= 0, "VolatileBuffer unlocked too many times!"); +} + +bool VolatileBuffer::OnHeap() const { return true; } + +size_t VolatileBuffer::HeapSizeOfExcludingThis( + MallocSizeOf aMallocSizeOf) const { + return aMallocSizeOf(mBuf); +} + +size_t VolatileBuffer::NonHeapSizeOfExcludingThis() const { return 0; } + +} // namespace mozilla diff --git a/memory/volatile/VolatileBufferOSX.cpp b/memory/volatile/VolatileBufferOSX.cpp new file mode 100644 index 0000000000..c6299d1db0 --- /dev/null +++ b/memory/volatile/VolatileBufferOSX.cpp @@ -0,0 +1,105 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "VolatileBuffer.h" +#include "mozilla/Assertions.h" +#include "mozilla/DebugOnly.h" +#include "mozilla/mozalloc.h" + +#include <mach/mach.h> +#include <sys/mman.h> +#include <unistd.h> + +#define MIN_VOLATILE_ALLOC_SIZE 8192 + +namespace mozilla { + +VolatileBuffer::VolatileBuffer() + : mMutex("VolatileBuffer"), + mBuf(nullptr), + mSize(0), + mLockCount(0), + mHeap(false) {} + +bool VolatileBuffer::Init(size_t aSize, size_t aAlignment) { + MOZ_ASSERT(!mSize && !mBuf, "Init called twice"); + MOZ_ASSERT(!(aAlignment % sizeof(void*)), + "Alignment must be multiple of pointer size"); + + mSize = aSize; + + kern_return_t ret = 0; + if (aSize < MIN_VOLATILE_ALLOC_SIZE) { + goto heap_alloc; + } + + ret = vm_allocate(mach_task_self(), (vm_address_t*)&mBuf, mSize, + VM_FLAGS_PURGABLE | VM_FLAGS_ANYWHERE); + if (ret == KERN_SUCCESS) { + return true; + } + +heap_alloc: + (void)posix_memalign(&mBuf, aAlignment, aSize); + mHeap = true; + return !!mBuf; +} + +VolatileBuffer::~VolatileBuffer() { + MOZ_ASSERT(mLockCount == 0, "Being destroyed with non-zero lock count?"); + + if (OnHeap()) { + free(mBuf); + } else { + vm_deallocate(mach_task_self(), (vm_address_t)mBuf, mSize); + } +} + +bool VolatileBuffer::Lock(void** aBuf) { + MutexAutoLock lock(mMutex); + + MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer"); + + *aBuf = mBuf; + if (++mLockCount > 1 || OnHeap()) { + return true; + } + + int state = VM_PURGABLE_NONVOLATILE; + kern_return_t ret = vm_purgable_control(mach_task_self(), (vm_address_t)mBuf, + VM_PURGABLE_SET_STATE, &state); + return ret == KERN_SUCCESS && !(state & VM_PURGABLE_EMPTY); +} + +void VolatileBuffer::Unlock() { + MutexAutoLock lock(mMutex); + + MOZ_ASSERT(mLockCount > 0, "VolatileBuffer unlocked too many times!"); + if (--mLockCount || OnHeap()) { + return; + } + + int state = VM_PURGABLE_VOLATILE | VM_VOLATILE_GROUP_DEFAULT; + DebugOnly<kern_return_t> ret = vm_purgable_control( + mach_task_self(), (vm_address_t)mBuf, VM_PURGABLE_SET_STATE, &state); + MOZ_ASSERT(ret == KERN_SUCCESS, "Failed to set buffer as purgable"); +} + +bool VolatileBuffer::OnHeap() const { return mHeap; } + +size_t VolatileBuffer::HeapSizeOfExcludingThis( + MallocSizeOf aMallocSizeOf) const { + return OnHeap() ? aMallocSizeOf(mBuf) : 0; +} + +size_t VolatileBuffer::NonHeapSizeOfExcludingThis() const { + if (OnHeap()) { + return 0; + } + + unsigned long pagemask = getpagesize() - 1; + return (mSize + pagemask) & ~pagemask; +} + +} // namespace mozilla diff --git a/memory/volatile/VolatileBufferWindows.cpp b/memory/volatile/VolatileBufferWindows.cpp new file mode 100644 index 0000000000..6615f89299 --- /dev/null +++ b/memory/volatile/VolatileBufferWindows.cpp @@ -0,0 +1,136 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "VolatileBuffer.h" +#include "mozilla/Assertions.h" +#include "mozilla/DebugOnly.h" +#include "mozilla/mozalloc.h" +#include "mozilla/WindowsVersion.h" + +#include <windows.h> + +#ifdef MOZ_MEMORY +extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size); +#endif + +#ifndef MEM_RESET_UNDO +# define MEM_RESET_UNDO 0x1000000 +#endif + +#define MIN_VOLATILE_ALLOC_SIZE 8192 + +namespace mozilla { + +VolatileBuffer::VolatileBuffer() + : mMutex("VolatileBuffer"), + mBuf(nullptr), + mSize(0), + mLockCount(0), + mHeap(false), + mFirstLock(true) {} + +bool VolatileBuffer::Init(size_t aSize, size_t aAlignment) { + MOZ_ASSERT(!mSize && !mBuf, "Init called twice"); + MOZ_ASSERT(!(aAlignment % sizeof(void*)), + "Alignment must be multiple of pointer size"); + + mSize = aSize; + if (aSize < MIN_VOLATILE_ALLOC_SIZE) { + goto heap_alloc; + } + + static bool sUndoSupported = IsWin8OrLater(); + if (!sUndoSupported) { + goto heap_alloc; + } + + mBuf = VirtualAllocEx(GetCurrentProcess(), nullptr, mSize, + MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if (mBuf) { + return true; + } + +heap_alloc: +#ifdef MOZ_MEMORY + posix_memalign(&mBuf, aAlignment, aSize); +#else + mBuf = _aligned_malloc(aSize, aAlignment); +#endif + mHeap = true; + return !!mBuf; +} + +VolatileBuffer::~VolatileBuffer() { + MOZ_ASSERT(mLockCount == 0, "Being destroyed with non-zero lock count?"); + + if (OnHeap()) { +#ifdef MOZ_MEMORY + free(mBuf); +#else + _aligned_free(mBuf); +#endif + } else { + VirtualFreeEx(GetCurrentProcess(), mBuf, 0, MEM_RELEASE); + } +} + +bool VolatileBuffer::Lock(void** aBuf) { + MutexAutoLock lock(mMutex); + + MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer"); + + *aBuf = mBuf; + if (++mLockCount > 1 || OnHeap()) { + return true; + } + + // MEM_RESET_UNDO's behavior is undefined when called on memory that + // hasn't been MEM_RESET. + if (mFirstLock) { + mFirstLock = false; + return true; + } + + void* addr = VirtualAllocEx(GetCurrentProcess(), mBuf, mSize, MEM_RESET_UNDO, + PAGE_READWRITE); + return !!addr; +} + +void VolatileBuffer::Unlock() { + MutexAutoLock lock(mMutex); + + MOZ_ASSERT(mLockCount > 0, "VolatileBuffer unlocked too many times!"); + if (--mLockCount || OnHeap()) { + return; + } + + DebugOnly<void*> addr = VirtualAllocEx(GetCurrentProcess(), mBuf, mSize, + MEM_RESET, PAGE_READWRITE); + MOZ_ASSERT(addr, "Failed to MEM_RESET"); +} + +bool VolatileBuffer::OnHeap() const { return mHeap; } + +size_t VolatileBuffer::HeapSizeOfExcludingThis( + MallocSizeOf aMallocSizeOf) const { + if (OnHeap()) { +#ifdef MOZ_MEMORY + return aMallocSizeOf(mBuf); +#else + return mSize; +#endif + } + + return 0; +} + +size_t VolatileBuffer::NonHeapSizeOfExcludingThis() const { + if (OnHeap()) { + return 0; + } + + return (mSize + 4095) & ~4095; +} + +} // namespace mozilla diff --git a/memory/volatile/moz.build b/memory/volatile/moz.build new file mode 100644 index 0000000000..9cfe43e5d0 --- /dev/null +++ b/memory/volatile/moz.build @@ -0,0 +1,31 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +NoVisibilityFlags() + +EXPORTS.mozilla += [ + "VolatileBuffer.h", +] + +if CONFIG["OS_TARGET"] == "Android": + UNIFIED_SOURCES += [ + "VolatileBufferAshmem.cpp", + ] +elif CONFIG["OS_TARGET"] == "Darwin": + UNIFIED_SOURCES += [ + "VolatileBufferOSX.cpp", + ] +elif CONFIG["OS_TARGET"] == "WINNT": + UNIFIED_SOURCES += [ + "VolatileBufferWindows.cpp", + ] +else: + UNIFIED_SOURCES += [ + "VolatileBufferFallback.cpp", + ] + +FINAL_LIBRARY = "xul" + +TEST_DIRS += ["tests"] diff --git a/memory/volatile/tests/TestVolatileBuffer.cpp b/memory/volatile/tests/TestVolatileBuffer.cpp new file mode 100644 index 0000000000..e9e9699ec6 --- /dev/null +++ b/memory/volatile/tests/TestVolatileBuffer.cpp @@ -0,0 +1,100 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "gtest/gtest.h" +#include "mozilla/VolatileBuffer.h" +#include <string.h> + +#if defined(ANDROID) +# include <fcntl.h> +# include <linux/ashmem.h> +# include <sys/ioctl.h> +# include <sys/stat.h> +# include <sys/types.h> +#elif defined(XP_DARWIN) +# include <mach/mach.h> +#endif + +using namespace mozilla; + +TEST(VolatileBufferTest, HeapVolatileBuffersWork) +{ + RefPtr<VolatileBuffer> heapbuf = new VolatileBuffer(); + + ASSERT_TRUE(heapbuf) + << "Failed to create VolatileBuffer"; + ASSERT_TRUE(heapbuf->Init(512)) + << "Failed to initialize VolatileBuffer"; + + VolatileBufferPtr<char> ptr(heapbuf); + + EXPECT_FALSE(ptr.WasBufferPurged()) + << "Buffer should not be purged immediately after initialization"; + EXPECT_TRUE(ptr) << "Couldn't get pointer from VolatileBufferPtr"; +} + +TEST(VolatileBufferTest, RealVolatileBuffersWork) +{ + RefPtr<VolatileBuffer> buf = new VolatileBuffer(); + + ASSERT_TRUE(buf) + << "Failed to create VolatileBuffer"; + ASSERT_TRUE(buf->Init(16384)) + << "Failed to initialize VolatileBuffer"; + + const char teststr[] = "foobar"; + + { + VolatileBufferPtr<char> ptr(buf); + + EXPECT_FALSE(ptr.WasBufferPurged()) + << "Buffer should not be purged immediately after initialization"; + EXPECT_TRUE(ptr) << "Couldn't get pointer from VolatileBufferPtr"; + + { + VolatileBufferPtr<char> ptr2(buf); + + EXPECT_FALSE(ptr.WasBufferPurged()) + << "Failed to lock buffer again while currently locked"; + ASSERT_TRUE(ptr2) + << "Didn't get a pointer on the second lock"; + + strcpy(ptr2, teststr); + } + } + + { + VolatileBufferPtr<char> ptr(buf); + + EXPECT_FALSE(ptr.WasBufferPurged()) + << "Buffer was immediately purged after unlock"; + EXPECT_STREQ(ptr, teststr) << "Buffer failed to retain data after unlock"; + } + + // Test purging if we know how to +#if defined(XP_DARWIN) + int state; + vm_purgable_control(mach_task_self(), (vm_address_t)NULL, + VM_PURGABLE_PURGE_ALL, &state); +#else + return; +#endif + + EXPECT_GT(buf->NonHeapSizeOfExcludingThis(), 0ul) + << "Buffer should not be allocated on heap"; + + { + VolatileBufferPtr<char> ptr(buf); + + EXPECT_TRUE(ptr.WasBufferPurged()) + << "Buffer should not be unpurged after forced purge"; + EXPECT_STRNE(ptr, teststr) << "Purge did not actually purge data"; + } + + { + VolatileBufferPtr<char> ptr(buf); + + EXPECT_FALSE(ptr.WasBufferPurged()) << "Buffer still purged after lock"; + } +} diff --git a/memory/volatile/tests/moz.build b/memory/volatile/tests/moz.build new file mode 100644 index 0000000000..31201db9d4 --- /dev/null +++ b/memory/volatile/tests/moz.build @@ -0,0 +1,11 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +UNIFIED_SOURCES = [ + "TestVolatileBuffer.cpp", +] + +FINAL_LIBRARY = "xul-gtest" |