michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "CrossProcessMutex.h" michael@0: #include "mozilla/unused.h" michael@0: #include "nsDebug.h" michael@0: #include "nsISupportsImpl.h" michael@0: michael@0: namespace { michael@0: michael@0: struct MutexData { michael@0: pthread_mutex_t mMutex; michael@0: mozilla::Atomic mCount; michael@0: }; michael@0: michael@0: } michael@0: michael@0: namespace mozilla { michael@0: michael@0: CrossProcessMutex::CrossProcessMutex(const char*) michael@0: : mSharedBuffer(nullptr) michael@0: , mMutex(nullptr) michael@0: , mCount(nullptr) michael@0: { michael@0: mSharedBuffer = new ipc::SharedMemoryBasic; michael@0: if (!mSharedBuffer->Create(sizeof(MutexData))) { michael@0: MOZ_CRASH(); michael@0: } michael@0: michael@0: if (!mSharedBuffer->Map(sizeof(MutexData))) { michael@0: MOZ_CRASH(); michael@0: } michael@0: michael@0: MutexData* data = static_cast(mSharedBuffer->memory()); michael@0: michael@0: if (!data) { michael@0: MOZ_CRASH(); michael@0: } michael@0: michael@0: mMutex = &(data->mMutex); michael@0: mCount = &(data->mCount); michael@0: michael@0: *mCount = 1; michael@0: michael@0: pthread_mutexattr_t mutexAttributes; michael@0: pthread_mutexattr_init(&mutexAttributes); michael@0: // Make the mutex reentrant so it behaves the same as a win32 mutex michael@0: if (pthread_mutexattr_settype(&mutexAttributes, PTHREAD_MUTEX_RECURSIVE)) { michael@0: MOZ_CRASH(); michael@0: } michael@0: if (pthread_mutexattr_setpshared(&mutexAttributes, PTHREAD_PROCESS_SHARED)) { michael@0: MOZ_CRASH(); michael@0: } michael@0: michael@0: if (pthread_mutex_init(mMutex, &mutexAttributes)) { michael@0: MOZ_CRASH(); michael@0: } michael@0: michael@0: MOZ_COUNT_CTOR(CrossProcessMutex); michael@0: } michael@0: michael@0: CrossProcessMutex::CrossProcessMutex(CrossProcessMutexHandle aHandle) michael@0: : mSharedBuffer(nullptr) michael@0: , mMutex(nullptr) michael@0: , mCount(nullptr) michael@0: { michael@0: if (!ipc::SharedMemoryBasic::IsHandleValid(aHandle)) { michael@0: MOZ_CRASH(); michael@0: } michael@0: michael@0: mSharedBuffer = new ipc::SharedMemoryBasic(aHandle); michael@0: michael@0: if (!mSharedBuffer->Map(sizeof(MutexData))) { michael@0: MOZ_CRASH(); michael@0: } michael@0: michael@0: MutexData* data = static_cast(mSharedBuffer->memory()); michael@0: michael@0: if (!data) { michael@0: MOZ_CRASH(); michael@0: } michael@0: michael@0: mMutex = &(data->mMutex); michael@0: mCount = &(data->mCount); michael@0: (*mCount)++; michael@0: michael@0: MOZ_COUNT_CTOR(CrossProcessMutex); michael@0: } michael@0: michael@0: CrossProcessMutex::~CrossProcessMutex() michael@0: { michael@0: int32_t count = --(*mCount); michael@0: michael@0: if (count == 0) { michael@0: // Nothing can be done if the destroy fails so ignore return code. michael@0: unused << pthread_mutex_destroy(mMutex); michael@0: } michael@0: michael@0: delete mSharedBuffer; michael@0: MOZ_COUNT_DTOR(CrossProcessMutex); michael@0: } michael@0: michael@0: void michael@0: CrossProcessMutex::Lock() michael@0: { michael@0: MOZ_ASSERT(*mCount > 0, "Attempting to lock mutex with zero ref count"); michael@0: pthread_mutex_lock(mMutex); michael@0: } michael@0: michael@0: void michael@0: CrossProcessMutex::Unlock() michael@0: { michael@0: MOZ_ASSERT(*mCount > 0, "Attempting to unlock mutex with zero ref count"); michael@0: pthread_mutex_unlock(mMutex); michael@0: } michael@0: michael@0: CrossProcessMutexHandle michael@0: CrossProcessMutex::ShareToProcess(base::ProcessHandle aHandle) michael@0: { michael@0: CrossProcessMutexHandle result = ipc::SharedMemoryBasic::NULLHandle(); michael@0: michael@0: if (mSharedBuffer && !mSharedBuffer->ShareToProcess(aHandle, &result)) { michael@0: MOZ_CRASH(); michael@0: } michael@0: michael@0: return result; michael@0: } michael@0: michael@0: }