Bug 1044550: Move GMP shared mem cache from a global to per-GMPParent r=cpearce

This commit is contained in:
Randell Jesup 2014-07-28 11:44:20 -04:00
parent 3f9a64b84f
commit 18183503d2
16 changed files with 102 additions and 109 deletions

View File

@ -42,6 +42,12 @@ GMPChild::~GMPChild()
{
}
void
GMPChild::CheckThread()
{
MOZ_ASSERT(mGMPMessageLoop == MessageLoop::current());
}
bool
GMPChild::Init(const std::string& aPluginPath,
base::ProcessHandle aParentProcessHandle,

View File

@ -7,13 +7,15 @@
#define GMPChild_h_
#include "mozilla/gmp/PGMPChild.h"
#include "GMPSharedMemManager.h"
#include "gmp-entrypoints.h"
#include "prlink.h"
namespace mozilla {
namespace gmp {
class GMPChild : public PGMPChild
class GMPChild : public PGMPChild,
public GMPSharedMem
{
public:
GMPChild();
@ -26,6 +28,9 @@ public:
bool LoadPluginLibrary(const std::string& aPluginPath);
MessageLoop* GMPMessageLoop();
// GMPSharedMem
virtual void CheckThread() MOZ_OVERRIDE;
private:
virtual PCrashReporterChild* AllocPCrashReporterChild(const NativeThreadId& aThread) MOZ_OVERRIDE;
virtual bool DeallocPCrashReporterChild(PCrashReporterChild*) MOZ_OVERRIDE;

View File

@ -63,6 +63,12 @@ GMPParent::~GMPParent()
MOZ_ASSERT(NS_IsMainThread());
}
void
GMPParent::CheckThread()
{
MOZ_ASSERT(mGMPThread == NS_GetCurrentThread());
}
nsresult
GMPParent::CloneFrom(const GMPParent* aOther)
{

View File

@ -51,7 +51,8 @@ enum GMPState {
GMPStateClosing
};
class GMPParent MOZ_FINAL : public PGMPParent
class GMPParent MOZ_FINAL : public PGMPParent,
public GMPSharedMem
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(GMPParent)
@ -117,6 +118,9 @@ public:
return nsCOMPtr<nsIFile>(mDirectory).forget();
}
// GMPSharedMem
virtual void CheckThread() MOZ_OVERRIDE;
private:
~GMPParent();
nsRefPtr<GeckoMediaPluginService> mService;

View File

@ -19,44 +19,12 @@ namespace gmp {
// Compressed (encoded) data goes from the Decoder parent to the child;
// pool there, and then return with Encoded() frames and goes into the parent
// pool.
static StaticAutoPtr<nsTArray<ipc::Shmem>> sGmpFreelist[GMPSharedMemManager::kGMPNumTypes];
static uint32_t sGMPShmemManagerCount = 0;
GMPSharedMemManager::GMPSharedMemManager()
{
if (!sGMPShmemManagerCount) {
for (uint32_t i = 0; i < GMPSharedMemManager::kGMPNumTypes; i++) {
sGmpFreelist[i] = new nsTArray<ipc::Shmem>();
}
}
sGMPShmemManagerCount++;
}
GMPSharedMemManager::~GMPSharedMemManager()
{
MOZ_ASSERT(sGMPShmemManagerCount > 0);
sGMPShmemManagerCount--;
if (!sGMPShmemManagerCount) {
for (uint32_t i = 0; i < GMPSharedMemManager::kGMPNumTypes; i++) {
sGmpFreelist[i] = nullptr;
}
}
}
static nsTArray<ipc::Shmem>&
GetGmpFreelist(GMPSharedMemManager::GMPMemoryClasses aTypes)
{
return *(sGmpFreelist[aTypes]);
}
static uint32_t sGmpAllocated[GMPSharedMemManager::kGMPNumTypes]; // 0's
bool
GMPSharedMemManager::MgrAllocShmem(GMPMemoryClasses aClass, size_t aSize,
GMPSharedMemManager::MgrAllocShmem(GMPSharedMem::GMPMemoryClasses aClass, size_t aSize,
ipc::Shmem::SharedMemory::SharedMemoryType aType,
ipc::Shmem* aMem)
{
CheckThread();
mData->CheckThread();
// first look to see if we have a free buffer large enough
for (uint32_t i = 0; i < GetGmpFreelist(aClass).Length(); i++) {
@ -73,15 +41,15 @@ GMPSharedMemManager::MgrAllocShmem(GMPMemoryClasses aClass, size_t aSize,
aSize = (aSize + (pagesize-1)) & ~(pagesize-1); // round up to page size
bool retval = Alloc(aSize, aType, aMem);
if (retval) {
sGmpAllocated[aClass]++;
mData->mGmpAllocated[aClass]++;
}
return retval;
}
bool
GMPSharedMemManager::MgrDeallocShmem(GMPMemoryClasses aClass, ipc::Shmem& aMem)
GMPSharedMemManager::MgrDeallocShmem(GMPSharedMem::GMPMemoryClasses aClass, ipc::Shmem& aMem)
{
CheckThread();
mData->CheckThread();
size_t size = aMem.Size<uint8_t>();
size_t total = 0;
@ -91,7 +59,7 @@ GMPSharedMemManager::MgrDeallocShmem(GMPMemoryClasses aClass, ipc::Shmem& aMem)
Dealloc(GetGmpFreelist(aClass)[0]);
GetGmpFreelist(aClass).RemoveElementAt(0);
// The allocation numbers will be fubar on the Child!
sGmpAllocated[aClass]--;
mData->mGmpAllocated[aClass]--;
}
for (uint32_t i = 0; i < GetGmpFreelist(aClass).Length(); i++) {
MOZ_ASSERT(GetGmpFreelist(aClass)[i].IsWritable());
@ -107,9 +75,9 @@ GMPSharedMemManager::MgrDeallocShmem(GMPMemoryClasses aClass, ipc::Shmem& aMem)
}
uint32_t
GMPSharedMemManager::NumInUse(GMPMemoryClasses aClass)
GMPSharedMemManager::NumInUse(GMPSharedMem::GMPMemoryClasses aClass)
{
return sGmpAllocated[aClass] - GetGmpFreelist(aClass).Length();
return mData->mGmpAllocated[aClass] - GetGmpFreelist(aClass).Length();
}
}

View File

@ -12,7 +12,9 @@
namespace mozilla {
namespace gmp {
class GMPSharedMemManager
class GMPSharedMemManager;
class GMPSharedMem
{
public:
typedef enum {
@ -28,24 +30,50 @@ public:
// (perhaps temporarily).
static const uint32_t kGMPBufLimit = 20;
GMPSharedMemManager();
virtual ~GMPSharedMemManager();
virtual bool MgrAllocShmem(GMPMemoryClasses aClass, size_t aSize,
ipc::Shmem::SharedMemory::SharedMemoryType aType,
ipc::Shmem* aMem);
virtual bool MgrDeallocShmem(GMPMemoryClasses aClass, ipc::Shmem& aMem);
// So we can know if data is "piling up" for the plugin - I.e. it's hung or crashed
virtual uint32_t NumInUse(GMPMemoryClasses aClass);
GMPSharedMem()
{
for (size_t i = 0; i < sizeof(mGmpAllocated)/sizeof(mGmpAllocated[0]); i++) {
mGmpAllocated[i] = 0;
}
}
virtual ~GMPSharedMem() {}
// Parent and child impls will differ here
virtual void CheckThread() = 0;
protected:
friend class GMPSharedMemManager;
nsTArray<ipc::Shmem> mGmpFreelist[GMPSharedMem::kGMPNumTypes];
uint32_t mGmpAllocated[GMPSharedMem::kGMPNumTypes];
};
class GMPSharedMemManager
{
public:
GMPSharedMemManager(GMPSharedMem *aData) : mData(aData) {}
virtual ~GMPSharedMemManager() {}
virtual bool MgrAllocShmem(GMPSharedMem::GMPMemoryClasses aClass, size_t aSize,
ipc::Shmem::SharedMemory::SharedMemoryType aType,
ipc::Shmem* aMem);
virtual bool MgrDeallocShmem(GMPSharedMem::GMPMemoryClasses aClass, ipc::Shmem& aMem);
// So we can know if data is "piling up" for the plugin - I.e. it's hung or crashed
virtual uint32_t NumInUse(GMPSharedMem::GMPMemoryClasses aClass);
// These have to be implemented using the AllocShmem/etc provided by the IPDL-generated interfaces,
// so have the Parent/Child implement them.
virtual bool Alloc(size_t aSize, ipc::Shmem::SharedMemory::SharedMemoryType aType, ipc::Shmem* aMem) = 0;
virtual void Dealloc(ipc::Shmem& aMem) = 0;
private:
nsTArray<ipc::Shmem>& GetGmpFreelist(GMPSharedMem::GMPMemoryClasses aTypes)
{
return mData->mGmpFreelist[aTypes];
}
GMPSharedMem *mData;
};
} // namespace gmp

View File

@ -14,7 +14,8 @@ namespace mozilla {
namespace gmp {
GMPVideoDecoderChild::GMPVideoDecoderChild(GMPChild* aPlugin)
: mPlugin(aPlugin),
: GMPSharedMemManager(aPlugin),
mPlugin(aPlugin),
mVideoDecoder(nullptr),
mVideoHost(MOZ_THIS_IN_INITIALIZER_LIST())
{
@ -104,12 +105,6 @@ GMPVideoDecoderChild::Error(GMPErr aError)
SendError(aError);
}
void
GMPVideoDecoderChild::CheckThread()
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
}
bool
GMPVideoDecoderChild::RecvInitDecode(const GMPVideoCodec& aCodecSettings,
const nsTArray<uint8_t>& aCodecSpecific,
@ -154,7 +149,7 @@ bool
GMPVideoDecoderChild::RecvChildShmemForPool(Shmem& aFrameBuffer)
{
if (aFrameBuffer.IsWritable()) {
mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMemManager::kGMPFrameData,
mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMem::kGMPFrameData,
aFrameBuffer);
}
return true;

View File

@ -39,8 +39,7 @@ public:
virtual void Error(GMPErr aError) MOZ_OVERRIDE;
// GMPSharedMemManager
virtual void CheckThread();
virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem)
virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem) MOZ_OVERRIDE
{
#ifndef SHMEM_ALLOC_IN_CHILD
return CallNeedShmem(aSize, aMem);
@ -52,7 +51,7 @@ public:
#endif
#endif
}
virtual void Dealloc(Shmem& aMem)
virtual void Dealloc(Shmem& aMem) MOZ_OVERRIDE
{
#ifndef SHMEM_ALLOC_IN_CHILD
SendParentShmemForPool(aMem);

View File

@ -50,7 +50,8 @@ namespace gmp {
// Dead: mIsOpen == false
GMPVideoDecoderParent::GMPVideoDecoderParent(GMPParent* aPlugin)
: mIsOpen(false)
: GMPSharedMemManager(aPlugin)
, mIsOpen(false)
, mPlugin(aPlugin)
, mCallback(nullptr)
, mVideoHost(MOZ_THIS_IN_INITIALIZER_LIST())
@ -132,8 +133,8 @@ GMPVideoDecoderParent::Decode(GMPVideoEncodedFrame* aInputFrame,
// Very rough kill-switch if the plugin stops processing. If it's merely
// hung and continues, we'll come back to life eventually.
// 3* is because we're using 3 buffers per frame for i420 data for now.
if (NumInUse(kGMPFrameData) > 3*GMPSharedMemManager::kGMPBufLimit ||
NumInUse(kGMPEncodedData) > GMPSharedMemManager::kGMPBufLimit) {
if ((NumInUse(GMPSharedMem::kGMPFrameData) > 3*GMPSharedMem::kGMPBufLimit) ||
(NumInUse(GMPSharedMem::kGMPEncodedData) > GMPSharedMem::kGMPBufLimit)) {
return NS_ERROR_FAILURE;
}
@ -228,12 +229,6 @@ GMPVideoDecoderParent::ActorDestroy(ActorDestroyReason aWhy)
mVideoHost.ActorDestroyed();
}
void
GMPVideoDecoderParent::CheckThread()
{
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
}
bool
GMPVideoDecoderParent::RecvDecoded(const GMPVideoi420FrameData& aDecodedFrame)
{
@ -331,7 +326,7 @@ bool
GMPVideoDecoderParent::RecvParentShmemForPool(Shmem& aEncodedBuffer)
{
if (aEncodedBuffer.IsWritable()) {
mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMemManager::kGMPEncodedData,
mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMem::kGMPEncodedData,
aEncodedBuffer);
}
return true;
@ -343,7 +338,7 @@ GMPVideoDecoderParent::AnswerNeedShmem(const uint32_t& aFrameBufferSize,
{
ipc::Shmem mem;
if (!mVideoHost.SharedMemMgr()->MgrAllocShmem(GMPSharedMemManager::kGMPFrameData,
if (!mVideoHost.SharedMemMgr()->MgrAllocShmem(GMPSharedMem::kGMPFrameData,
aFrameBufferSize,
ipc::SharedMemory::TYPE_BASIC, &mem))
{

View File

@ -20,8 +20,8 @@ namespace gmp {
class GMPParent;
class GMPVideoDecoderParent MOZ_FINAL : public PGMPVideoDecoderParent
, public GMPSharedMemManager
, public GMPVideoDecoderProxy
, public GMPSharedMemManager
{
public:
NS_INLINE_DECL_REFCOUNTING(GMPVideoDecoderParent)
@ -46,8 +46,7 @@ public:
virtual const uint64_t ParentID() MOZ_OVERRIDE { return reinterpret_cast<uint64_t>(mPlugin.get()); }
// GMPSharedMemManager
virtual void CheckThread();
virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem)
virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem) MOZ_OVERRIDE
{
#ifdef GMP_SAFE_SHMEM
return AllocShmem(aSize, aType, aMem);
@ -55,7 +54,7 @@ public:
return AllocUnsafeShmem(aSize, aType, aMem);
#endif
}
virtual void Dealloc(Shmem& aMem)
virtual void Dealloc(Shmem& aMem) MOZ_OVERRIDE
{
DeallocShmem(aMem);
}

View File

@ -108,7 +108,7 @@ void
GMPVideoEncodedFrameImpl::DestroyBuffer()
{
if (mHost && mBuffer.IsWritable()) {
mHost->SharedMemMgr()->MgrDeallocShmem(GMPSharedMemManager::kGMPEncodedData, mBuffer);
mHost->SharedMemMgr()->MgrDeallocShmem(GMPSharedMem::kGMPEncodedData, mBuffer);
}
mBuffer = ipc::Shmem();
}
@ -120,7 +120,7 @@ GMPVideoEncodedFrameImpl::CreateEmptyFrame(uint32_t aSize)
DestroyBuffer();
} else if (aSize > AllocatedSize()) {
DestroyBuffer();
if (!mHost->SharedMemMgr()->MgrAllocShmem(GMPSharedMemManager::kGMPEncodedData, aSize,
if (!mHost->SharedMemMgr()->MgrAllocShmem(GMPSharedMem::kGMPEncodedData, aSize,
ipc::SharedMemory::TYPE_BASIC, &mBuffer) ||
!Buffer()) {
return GMPAllocErr;
@ -228,7 +228,7 @@ GMPVideoEncodedFrameImpl::SetAllocatedSize(uint32_t aNewSize)
}
ipc::Shmem new_mem;
if (!mHost->SharedMemMgr()->MgrAllocShmem(GMPSharedMemManager::kGMPEncodedData, aNewSize,
if (!mHost->SharedMemMgr()->MgrAllocShmem(GMPSharedMem::kGMPEncodedData, aNewSize,
ipc::SharedMemory::TYPE_BASIC, &new_mem) ||
!new_mem.get<uint8_t>()) {
return;

View File

@ -14,7 +14,8 @@ namespace mozilla {
namespace gmp {
GMPVideoEncoderChild::GMPVideoEncoderChild(GMPChild* aPlugin)
: mPlugin(aPlugin),
: GMPSharedMemManager(aPlugin),
mPlugin(aPlugin),
mVideoEncoder(nullptr),
mVideoHost(MOZ_THIS_IN_INITIALIZER_LIST())
{
@ -65,12 +66,6 @@ GMPVideoEncoderChild::Error(GMPErr aError)
SendError(aError);
}
void
GMPVideoEncoderChild::CheckThread()
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
}
bool
GMPVideoEncoderChild::RecvInitEncode(const GMPVideoCodec& aCodecSettings,
const nsTArray<uint8_t>& aCodecSpecific,
@ -117,7 +112,7 @@ bool
GMPVideoEncoderChild::RecvChildShmemForPool(Shmem& aEncodedBuffer)
{
if (aEncodedBuffer.IsWritable()) {
mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMemManager::kGMPEncodedData,
mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMem::kGMPEncodedData,
aEncodedBuffer);
}
return true;

View File

@ -35,8 +35,7 @@ public:
virtual void Error(GMPErr aError) MOZ_OVERRIDE;
// GMPSharedMemManager
virtual void CheckThread();
virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem)
virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem) MOZ_OVERRIDE
{
#ifndef SHMEM_ALLOC_IN_CHILD
return CallNeedShmem(aSize, aMem);
@ -48,7 +47,7 @@ public:
#endif
#endif
}
virtual void Dealloc(Shmem& aMem)
virtual void Dealloc(Shmem& aMem) MOZ_OVERRIDE
{
#ifndef SHMEM_ALLOC_IN_CHILD
SendParentShmemForPool(aMem);

View File

@ -55,7 +55,8 @@ namespace gmp {
// Dead: mIsOpen == false
GMPVideoEncoderParent::GMPVideoEncoderParent(GMPParent *aPlugin)
: mIsOpen(false),
: GMPSharedMemManager(aPlugin),
mIsOpen(false),
mPlugin(aPlugin),
mCallback(nullptr),
mVideoHost(MOZ_THIS_IN_INITIALIZER_LIST())
@ -138,8 +139,8 @@ GMPVideoEncoderParent::Encode(GMPVideoi420Frame* aInputFrame,
// Very rough kill-switch if the plugin stops processing. If it's merely
// hung and continues, we'll come back to life eventually.
// 3* is because we're using 3 buffers per frame for i420 data for now.
if (NumInUse(kGMPFrameData) > 3*GMPSharedMemManager::kGMPBufLimit ||
NumInUse(kGMPEncodedData) > GMPSharedMemManager::kGMPBufLimit) {
if ((NumInUse(GMPSharedMem::kGMPFrameData) > 3*GMPSharedMem::kGMPBufLimit) ||
(NumInUse(GMPSharedMem::kGMPEncodedData) > GMPSharedMem::kGMPBufLimit)) {
return GMPGenericErr;
}
@ -249,12 +250,6 @@ GMPVideoEncoderParent::ActorDestroy(ActorDestroyReason aWhy)
mVideoHost.ActorDestroyed();
}
void
GMPVideoEncoderParent::CheckThread()
{
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
}
bool
GMPVideoEncoderParent::RecvEncoded(const GMPVideoEncodedFrameData& aEncodedFrame,
const nsTArray<uint8_t>& aCodecSpecificInfo)
@ -290,7 +285,7 @@ bool
GMPVideoEncoderParent::RecvParentShmemForPool(Shmem& aFrameBuffer)
{
if (aFrameBuffer.IsWritable()) {
mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMemManager::kGMPFrameData,
mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMem::kGMPFrameData,
aFrameBuffer);
}
return true;
@ -302,7 +297,7 @@ GMPVideoEncoderParent::AnswerNeedShmem(const uint32_t& aEncodedBufferSize,
{
ipc::Shmem mem;
if (!mVideoHost.SharedMemMgr()->MgrAllocShmem(GMPSharedMemManager::kGMPEncodedData,
if (!mVideoHost.SharedMemMgr()->MgrAllocShmem(GMPSharedMem::kGMPEncodedData,
aEncodedBufferSize,
ipc::SharedMemory::TYPE_BASIC, &mem))
{

View File

@ -47,8 +47,7 @@ public:
virtual const uint64_t ParentID() MOZ_OVERRIDE { return reinterpret_cast<uint64_t>(mPlugin.get()); }
// GMPSharedMemManager
virtual void CheckThread();
virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem)
virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem) MOZ_OVERRIDE
{
#ifdef GMP_SAFE_SHMEM
return AllocShmem(aSize, aType, aMem);
@ -56,7 +55,7 @@ public:
return AllocUnsafeShmem(aSize, aType, aMem);
#endif
}
virtual void Dealloc(Shmem& aMem)
virtual void Dealloc(Shmem& aMem) MOZ_OVERRIDE
{
DeallocShmem(aMem);
}

View File

@ -84,7 +84,7 @@ GMPPlaneImpl::MaybeResize(int32_t aNewSize) {
}
ipc::Shmem new_mem;
if (!mHost->SharedMemMgr()->MgrAllocShmem(GMPSharedMemManager::kGMPFrameData, aNewSize,
if (!mHost->SharedMemMgr()->MgrAllocShmem(GMPSharedMem::kGMPFrameData, aNewSize,
ipc::SharedMemory::TYPE_BASIC, &new_mem) ||
!new_mem.get<uint8_t>()) {
return GMPAllocErr;
@ -105,7 +105,7 @@ void
GMPPlaneImpl::DestroyBuffer()
{
if (mHost && mBuffer.IsWritable()) {
mHost->SharedMemMgr()->MgrDeallocShmem(GMPSharedMemManager::kGMPFrameData, mBuffer);
mHost->SharedMemMgr()->MgrDeallocShmem(GMPSharedMem::kGMPFrameData, mBuffer);
}
mBuffer = ipc::Shmem();
}