Bug 895358 - Part 1, Adding POSIX cross process mutex to support progressive tile rendering in B2G; r=khuey

This commit is contained in:
Randall Barker 2013-12-19 12:19:25 -08:00
parent 147ed55ba9
commit d2e583d848
3 changed files with 156 additions and 2 deletions

View File

@ -9,6 +9,12 @@
#include "base/process.h"
#include "mozilla/Mutex.h"
#if defined(OS_LINUX)
#include <pthread.h>
#include "SharedMemoryBasic.h"
#include "mozilla/Atomics.h"
#endif
namespace IPC {
template<typename T>
struct ParamTraits;
@ -27,6 +33,8 @@ struct ParamTraits;
namespace mozilla {
#ifdef XP_WIN
typedef HANDLE CrossProcessMutexHandle;
#elif defined(OS_LINUX)
typedef mozilla::ipc::SharedMemoryBasic::Handle CrossProcessMutexHandle;
#else
// Stub for other platforms. We can't use uintptr_t here since different
// processes could disagree on its size.
@ -91,6 +99,10 @@ private:
#ifdef XP_WIN
HANDLE mMutex;
#elif defined(OS_LINUX)
mozilla::ipc::SharedMemoryBasic* mSharedBuffer;
pthread_mutex_t* mMutex;
mozilla::Atomic<int32_t>* mCount;
#endif
};

View File

@ -0,0 +1,131 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "CrossProcessMutex.h"
#include "mozilla/unused.h"
#include "nsDebug.h"
#include "nsTraceRefcnt.h"
namespace {
struct MutexData {
pthread_mutex_t mMutex;
mozilla::Atomic<int32_t> mCount;
};
}
namespace mozilla {
CrossProcessMutex::CrossProcessMutex(const char*)
: mSharedBuffer(nullptr)
, mMutex(nullptr)
, mCount(nullptr)
{
mSharedBuffer = new ipc::SharedMemoryBasic;
if (!mSharedBuffer->Create(sizeof(MutexData))) {
MOZ_CRASH();
}
if (!mSharedBuffer->Map(sizeof(MutexData))) {
MOZ_CRASH();
}
MutexData* data = static_cast<MutexData*>(mSharedBuffer->memory());
if (!data) {
MOZ_CRASH();
}
mMutex = &(data->mMutex);
mCount = &(data->mCount);
*mCount = 1;
pthread_mutexattr_t mutexAttributes;
pthread_mutexattr_init(&mutexAttributes);
// Make the mutex reentrant so it behaves the same as a win32 mutex
if (pthread_mutexattr_settype(&mutexAttributes, PTHREAD_MUTEX_RECURSIVE)) {
MOZ_CRASH();
}
if (pthread_mutexattr_setpshared(&mutexAttributes, PTHREAD_PROCESS_SHARED)) {
MOZ_CRASH();
}
if (pthread_mutex_init(mMutex, &mutexAttributes)) {
MOZ_CRASH();
}
MOZ_COUNT_CTOR(CrossProcessMutex);
}
CrossProcessMutex::CrossProcessMutex(CrossProcessMutexHandle aHandle)
: mSharedBuffer(nullptr)
, mMutex(nullptr)
, mCount(nullptr)
{
if (!ipc::SharedMemoryBasic::IsHandleValid(aHandle)) {
MOZ_CRASH();
}
mSharedBuffer = new ipc::SharedMemoryBasic(aHandle);
if (!mSharedBuffer->Map(sizeof(MutexData))) {
MOZ_CRASH();
}
MutexData* data = static_cast<MutexData*>(mSharedBuffer->memory());
if (!data) {
MOZ_CRASH();
}
mMutex = &(data->mMutex);
mCount = &(data->mCount);
(*mCount)++;
MOZ_COUNT_CTOR(CrossProcessMutex);
}
CrossProcessMutex::~CrossProcessMutex()
{
int32_t count = --(*mCount);
if (count == 0) {
// Nothing can be done if the destroy fails so ignore return code.
unused << pthread_mutex_destroy(mMutex);
}
delete mSharedBuffer;
MOZ_COUNT_DTOR(CrossProcessMutex);
}
void
CrossProcessMutex::Lock()
{
MOZ_ASSERT(*mCount > 0, "Attempting to lock mutex with zero ref count");
pthread_mutex_lock(mMutex);
}
void
CrossProcessMutex::Unlock()
{
MOZ_ASSERT(*mCount > 0, "Attempting to unlock mutex with zero ref count");
pthread_mutex_unlock(mMutex);
}
CrossProcessMutexHandle
CrossProcessMutex::ShareToProcess(base::ProcessHandle aHandle)
{
CrossProcessMutexHandle result = ipc::SharedMemoryBasic::NULLHandle();
if (mSharedBuffer && !mSharedBuffer->ShareToProcess(aHandle, &result)) {
MOZ_CRASH();
}
return result;
}
}

View File

@ -35,7 +35,6 @@ if CONFIG['OS_ARCH'] == 'WINNT':
'Transport_win.h',
]
SOURCES += [
'CrossProcessMutex_windows.cpp',
'SharedMemory_windows.cpp',
'Transport_win.cpp',
'WindowsMessageLoop.cpp',
@ -45,11 +44,23 @@ else:
'Transport_posix.h',
]
UNIFIED_SOURCES += [
'CrossProcessMutex_unimplemented.cpp',
'SharedMemory_posix.cpp',
'Transport_posix.cpp',
]
if CONFIG['OS_ARCH'] == 'WINNT':
SOURCES += [
'CrossProcessMutex_windows.cpp',
]
elif CONFIG['OS_ARCH'] == 'Linux':
UNIFIED_SOURCES += [
'CrossProcessMutex_posix.cpp',
]
else:
UNIFIED_SOURCES += [
'CrossProcessMutex_unimplemented.cpp',
]
# Android has its own,
# almost-but-not-quite-compatible-with-POSIX-or-/dev/shm shared memory
# impl.