Bug 1121297 (Part 2) - Make VolatileBuffer threadsafe. r=glandium

This commit is contained in:
Seth Fowler 2015-01-16 15:47:35 -08:00
parent 26bd4c1cb6
commit fb673b7c3a
5 changed files with 46 additions and 8 deletions

View file

@ -6,6 +6,7 @@
#define mozalloc_VolatileBuffer_h #define mozalloc_VolatileBuffer_h
#include "mozilla/mozalloc.h" #include "mozilla/mozalloc.h"
#include "mozilla/Mutex.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/MemoryReporting.h" #include "mozilla/MemoryReporting.h"
@ -36,19 +37,19 @@
* When a buffer is purged, some or all of the buffer is zeroed out. This * 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. * API cannot tell which parts of the buffer were lost.
* *
* VolatileBuffer is not thread safe. Do not use VolatileBufferPtrs on * VolatileBuffer and VolatileBufferPtr are threadsafe.
* different threads.
*/ */
namespace mozilla { namespace mozilla {
class VolatileBuffer : public RefCounted<VolatileBuffer> class VolatileBuffer
{ {
friend class VolatileBufferPtr_base; friend class VolatileBufferPtr_base;
public: public:
MOZ_DECLARE_REFCOUNTED_TYPENAME(VolatileBuffer) MOZ_DECLARE_REFCOUNTED_TYPENAME(VolatileBuffer)
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VolatileBuffer)
VolatileBuffer(); VolatileBuffer();
~VolatileBuffer();
/* aAlignment must be a multiple of the pointer size */ /* aAlignment must be a multiple of the pointer size */
bool Init(size_t aSize, size_t aAlignment = sizeof(void*)); bool Init(size_t aSize, size_t aAlignment = sizeof(void*));
@ -62,6 +63,15 @@ protected:
void Unlock(); void Unlock();
private: 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;
void* mBuf; void* mBuf;
size_t mSize; size_t mSize;
int mLockCount; int mLockCount;

View file

@ -22,7 +22,8 @@ extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size);
namespace mozilla { namespace mozilla {
VolatileBuffer::VolatileBuffer() VolatileBuffer::VolatileBuffer()
: mBuf(nullptr) : mMutex("VolatileBuffer")
, mBuf(nullptr)
, mSize(0) , mSize(0)
, mLockCount(0) , mLockCount(0)
, mFd(-1) , mFd(-1)
@ -72,6 +73,8 @@ heap_alloc:
VolatileBuffer::~VolatileBuffer() VolatileBuffer::~VolatileBuffer()
{ {
MOZ_ASSERT(mLockCount == 0, "Being destroyed with non-zero lock count?");
if (OnHeap()) { if (OnHeap()) {
free(mBuf); free(mBuf);
} else { } else {
@ -83,6 +86,8 @@ VolatileBuffer::~VolatileBuffer()
bool bool
VolatileBuffer::Lock(void** aBuf) VolatileBuffer::Lock(void** aBuf)
{ {
MutexAutoLock lock(mMutex);
MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer"); MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer");
*aBuf = mBuf; *aBuf = mBuf;
@ -98,6 +103,8 @@ VolatileBuffer::Lock(void** aBuf)
void void
VolatileBuffer::Unlock() VolatileBuffer::Unlock()
{ {
MutexAutoLock lock(mMutex);
MOZ_ASSERT(mLockCount > 0, "VolatileBuffer unlocked too many times!"); MOZ_ASSERT(mLockCount > 0, "VolatileBuffer unlocked too many times!");
if (--mLockCount || OnHeap()) { if (--mLockCount || OnHeap()) {
return; return;

View file

@ -13,7 +13,8 @@ int posix_memalign(void** memptr, size_t alignment, size_t size);
namespace mozilla { namespace mozilla {
VolatileBuffer::VolatileBuffer() VolatileBuffer::VolatileBuffer()
: mBuf(nullptr) : mMutex("VolatileBuffer")
, mBuf(nullptr)
, mSize(0) , mSize(0)
, mLockCount(0) , mLockCount(0)
{ {
@ -42,12 +43,16 @@ bool VolatileBuffer::Init(size_t aSize, size_t aAlignment)
VolatileBuffer::~VolatileBuffer() VolatileBuffer::~VolatileBuffer()
{ {
MOZ_ASSERT(mLockCount == 0, "Being destroyed with non-zero lock count?");
free(mBuf); free(mBuf);
} }
bool bool
VolatileBuffer::Lock(void** aBuf) VolatileBuffer::Lock(void** aBuf)
{ {
MutexAutoLock lock(mMutex);
MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer"); MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer");
*aBuf = mBuf; *aBuf = mBuf;
@ -59,6 +64,8 @@ VolatileBuffer::Lock(void** aBuf)
void void
VolatileBuffer::Unlock() VolatileBuffer::Unlock()
{ {
MutexAutoLock lock(mMutex);
mLockCount--; mLockCount--;
MOZ_ASSERT(mLockCount >= 0, "VolatileBuffer unlocked too many times!"); MOZ_ASSERT(mLockCount >= 0, "VolatileBuffer unlocked too many times!");
} }

View file

@ -16,7 +16,8 @@
namespace mozilla { namespace mozilla {
VolatileBuffer::VolatileBuffer() VolatileBuffer::VolatileBuffer()
: mBuf(nullptr) : mMutex("VolatileBuffer")
, mBuf(nullptr)
, mSize(0) , mSize(0)
, mLockCount(0) , mLockCount(0)
, mHeap(false) , mHeap(false)
@ -53,6 +54,8 @@ heap_alloc:
VolatileBuffer::~VolatileBuffer() VolatileBuffer::~VolatileBuffer()
{ {
MOZ_ASSERT(mLockCount == 0, "Being destroyed with non-zero lock count?");
if (OnHeap()) { if (OnHeap()) {
free(mBuf); free(mBuf);
} else { } else {
@ -63,6 +66,8 @@ VolatileBuffer::~VolatileBuffer()
bool bool
VolatileBuffer::Lock(void** aBuf) VolatileBuffer::Lock(void** aBuf)
{ {
MutexAutoLock lock(mMutex);
MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer"); MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer");
*aBuf = mBuf; *aBuf = mBuf;
@ -82,6 +87,8 @@ VolatileBuffer::Lock(void** aBuf)
void void
VolatileBuffer::Unlock() VolatileBuffer::Unlock()
{ {
MutexAutoLock lock(mMutex);
MOZ_ASSERT(mLockCount > 0, "VolatileBuffer unlocked too many times!"); MOZ_ASSERT(mLockCount > 0, "VolatileBuffer unlocked too many times!");
if (--mLockCount || OnHeap()) { if (--mLockCount || OnHeap()) {
return; return;

View file

@ -22,7 +22,8 @@ extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size);
namespace mozilla { namespace mozilla {
VolatileBuffer::VolatileBuffer() VolatileBuffer::VolatileBuffer()
: mBuf(nullptr) : mMutex("VolatileBuffer")
, mBuf(nullptr)
, mSize(0) , mSize(0)
, mLockCount(0) , mLockCount(0)
, mHeap(false) , mHeap(false)
@ -68,6 +69,8 @@ heap_alloc:
VolatileBuffer::~VolatileBuffer() VolatileBuffer::~VolatileBuffer()
{ {
MOZ_ASSERT(mLockCount == 0, "Being destroyed with non-zero lock count?");
if (OnHeap()) { if (OnHeap()) {
#ifdef MOZ_MEMORY #ifdef MOZ_MEMORY
free(mBuf); free(mBuf);
@ -82,6 +85,8 @@ VolatileBuffer::~VolatileBuffer()
bool bool
VolatileBuffer::Lock(void** aBuf) VolatileBuffer::Lock(void** aBuf)
{ {
MutexAutoLock lock(mMutex);
MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer"); MOZ_ASSERT(mBuf, "Attempting to lock an uninitialized VolatileBuffer");
*aBuf = mBuf; *aBuf = mBuf;
@ -107,6 +112,8 @@ VolatileBuffer::Lock(void** aBuf)
void void
VolatileBuffer::Unlock() VolatileBuffer::Unlock()
{ {
MutexAutoLock lock(mMutex);
MOZ_ASSERT(mLockCount > 0, "VolatileBuffer unlocked too many times!"); MOZ_ASSERT(mLockCount > 0, "VolatileBuffer unlocked too many times!");
if (--mLockCount || OnHeap()) { if (--mLockCount || OnHeap()) {
return; return;