no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / ipc / glue / CrossProcessMutex_posix.cpp
blobc37fcb797dbbb5874615a485cd6247c4bca9d3f8
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "CrossProcessMutex.h"
8 #include "mozilla/Unused.h"
9 #include "nsDebug.h"
10 #include "nsISupportsImpl.h"
12 namespace {
14 struct MutexData {
15 pthread_mutex_t mMutex;
16 mozilla::Atomic<int32_t> mCount;
19 } // namespace
21 namespace mozilla {
23 static void InitMutex(pthread_mutex_t* mMutex) {
24 pthread_mutexattr_t mutexAttributes;
25 pthread_mutexattr_init(&mutexAttributes);
26 // Make the mutex reentrant so it behaves the same as a win32 mutex
27 if (pthread_mutexattr_settype(&mutexAttributes, PTHREAD_MUTEX_RECURSIVE)) {
28 MOZ_CRASH();
30 if (pthread_mutexattr_setpshared(&mutexAttributes, PTHREAD_PROCESS_SHARED)) {
31 MOZ_CRASH();
34 if (pthread_mutex_init(mMutex, &mutexAttributes)) {
35 MOZ_CRASH();
39 CrossProcessMutex::CrossProcessMutex(const char*)
40 : mMutex(nullptr), mCount(nullptr) {
41 #if defined(MOZ_SANDBOX)
42 // POSIX mutexes in shared memory aren't guaranteed to be safe - and
43 // they specifically are not on Linux.
44 MOZ_RELEASE_ASSERT(false);
45 #endif
46 mSharedBuffer = new ipc::SharedMemoryBasic;
47 if (!mSharedBuffer->Create(sizeof(MutexData))) {
48 MOZ_CRASH();
51 if (!mSharedBuffer->Map(sizeof(MutexData))) {
52 MOZ_CRASH();
55 MutexData* data = static_cast<MutexData*>(mSharedBuffer->memory());
57 if (!data) {
58 MOZ_CRASH();
61 mMutex = &(data->mMutex);
62 mCount = &(data->mCount);
64 *mCount = 1;
65 InitMutex(mMutex);
67 MOZ_COUNT_CTOR(CrossProcessMutex);
70 CrossProcessMutex::CrossProcessMutex(CrossProcessMutexHandle aHandle)
71 : mMutex(nullptr), mCount(nullptr) {
72 mSharedBuffer = new ipc::SharedMemoryBasic;
74 if (!mSharedBuffer->IsHandleValid(aHandle)) {
75 MOZ_CRASH();
78 if (!mSharedBuffer->SetHandle(std::move(aHandle),
79 ipc::SharedMemory::RightsReadWrite)) {
80 MOZ_CRASH();
83 if (!mSharedBuffer->Map(sizeof(MutexData))) {
84 MOZ_CRASH();
87 MutexData* data = static_cast<MutexData*>(mSharedBuffer->memory());
89 if (!data) {
90 MOZ_CRASH();
93 mMutex = &(data->mMutex);
94 mCount = &(data->mCount);
95 int32_t count = (*mCount)++;
97 if (count == 0) {
98 // The other side has already let go of their CrossProcessMutex, so now
99 // mMutex is garbage. We need to re-initialize it.
100 InitMutex(mMutex);
103 MOZ_COUNT_CTOR(CrossProcessMutex);
106 CrossProcessMutex::~CrossProcessMutex() {
107 int32_t count = --(*mCount);
109 if (count == 0) {
110 // Nothing can be done if the destroy fails so ignore return code.
111 Unused << pthread_mutex_destroy(mMutex);
114 MOZ_COUNT_DTOR(CrossProcessMutex);
117 void CrossProcessMutex::Lock() {
118 MOZ_ASSERT(*mCount > 0, "Attempting to lock mutex with zero ref count");
119 pthread_mutex_lock(mMutex);
122 void CrossProcessMutex::Unlock() {
123 MOZ_ASSERT(*mCount > 0, "Attempting to unlock mutex with zero ref count");
124 pthread_mutex_unlock(mMutex);
127 CrossProcessMutexHandle CrossProcessMutex::CloneHandle() {
128 CrossProcessMutexHandle result = ipc::SharedMemoryBasic::NULLHandle();
130 if (mSharedBuffer) {
131 result = mSharedBuffer->CloneHandle();
132 if (!result) {
133 MOZ_CRASH();
137 return result;
140 } // namespace mozilla