diff --git a/ipc/glue/CrossProcessMutex.h b/ipc/glue/CrossProcessMutex.h index 7c48cdae4a08..ce1e85a7f440 100644 --- a/ipc/glue/CrossProcessMutex.h +++ b/ipc/glue/CrossProcessMutex.h @@ -9,6 +9,12 @@ #include "base/process.h" #include "mozilla/Mutex.h" +#if defined(OS_LINUX) +#include +#include "SharedMemoryBasic.h" +#include "mozilla/Atomics.h" +#endif + namespace IPC { template 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* mCount; #endif }; diff --git a/ipc/glue/CrossProcessMutex_posix.cpp b/ipc/glue/CrossProcessMutex_posix.cpp new file mode 100644 index 000000000000..c1824936d635 --- /dev/null +++ b/ipc/glue/CrossProcessMutex_posix.cpp @@ -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 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(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(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; +} + +} diff --git a/ipc/glue/moz.build b/ipc/glue/moz.build index e15ede75d198..93292c7ea03e 100644 --- a/ipc/glue/moz.build +++ b/ipc/glue/moz.build @@ -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': + UNIFIED_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.