Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/ipc/glue/CrossProcessMutex_posix.cpp
Line
Count
Source (jump to first uncovered line)
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/. */
6
7
#include "CrossProcessMutex.h"
8
#include "mozilla/Unused.h"
9
#include "nsDebug.h"
10
#include "nsISupportsImpl.h"
11
12
namespace {
13
14
struct MutexData {
15
  pthread_mutex_t mMutex;
16
  mozilla::Atomic<int32_t> mCount;
17
};
18
19
} // namespace
20
21
namespace mozilla {
22
23
static void
24
InitMutex(pthread_mutex_t* mMutex)
25
0
{
26
0
  pthread_mutexattr_t mutexAttributes;
27
0
  pthread_mutexattr_init(&mutexAttributes);
28
0
  // Make the mutex reentrant so it behaves the same as a win32 mutex
29
0
  if (pthread_mutexattr_settype(&mutexAttributes, PTHREAD_MUTEX_RECURSIVE)) {
30
0
    MOZ_CRASH();
31
0
  }
32
0
  if (pthread_mutexattr_setpshared(&mutexAttributes, PTHREAD_PROCESS_SHARED)) {
33
0
    MOZ_CRASH();
34
0
  }
35
0
36
0
  if (pthread_mutex_init(mMutex, &mutexAttributes)) {
37
0
    MOZ_CRASH();
38
0
  }
39
0
}
40
41
CrossProcessMutex::CrossProcessMutex(const char*)
42
    : mMutex(nullptr)
43
    , mCount(nullptr)
44
0
{
45
0
  mSharedBuffer = new ipc::SharedMemoryBasic;
46
0
  if (!mSharedBuffer->Create(sizeof(MutexData))) {
47
0
    MOZ_CRASH();
48
0
  }
49
0
50
0
  if (!mSharedBuffer->Map(sizeof(MutexData))) {
51
0
    MOZ_CRASH();
52
0
  }
53
0
54
0
  MutexData* data = static_cast<MutexData*>(mSharedBuffer->memory());
55
0
56
0
  if (!data) {
57
0
    MOZ_CRASH();
58
0
  }
59
0
60
0
  mMutex = &(data->mMutex);
61
0
  mCount = &(data->mCount);
62
0
63
0
  *mCount = 1;
64
0
  InitMutex(mMutex);
65
0
66
0
  MOZ_COUNT_CTOR(CrossProcessMutex);
67
0
}
68
69
CrossProcessMutex::CrossProcessMutex(CrossProcessMutexHandle aHandle)
70
    : mMutex(nullptr)
71
    , mCount(nullptr)
72
0
{
73
0
  mSharedBuffer = new ipc::SharedMemoryBasic;
74
0
75
0
  if (!mSharedBuffer->IsHandleValid(aHandle)) {
76
0
    MOZ_CRASH();
77
0
  }
78
0
79
0
  if (!mSharedBuffer->SetHandle(aHandle, ipc::SharedMemory::RightsReadWrite)) {
80
0
    MOZ_CRASH();
81
0
  }
82
0
83
0
  if (!mSharedBuffer->Map(sizeof(MutexData))) {
84
0
    MOZ_CRASH();
85
0
  }
86
0
87
0
  MutexData* data = static_cast<MutexData*>(mSharedBuffer->memory());
88
0
89
0
  if (!data) {
90
0
    MOZ_CRASH();
91
0
  }
92
0
93
0
  mMutex = &(data->mMutex);
94
0
  mCount = &(data->mCount);
95
0
  int32_t count = (*mCount)++;
96
0
97
0
  if (count == 0) {
98
0
    // The other side has already let go of their CrossProcessMutex, so now
99
0
    // mMutex is garbage. We need to re-initialize it.
100
0
    InitMutex(mMutex);
101
0
  }
102
0
103
0
  MOZ_COUNT_CTOR(CrossProcessMutex);
104
0
}
105
106
CrossProcessMutex::~CrossProcessMutex()
107
0
{
108
0
  int32_t count = --(*mCount);
109
0
110
0
  if (count == 0) {
111
0
    // Nothing can be done if the destroy fails so ignore return code.
112
0
    Unused << pthread_mutex_destroy(mMutex);
113
0
  }
114
0
115
0
  MOZ_COUNT_DTOR(CrossProcessMutex);
116
0
}
117
118
void
119
CrossProcessMutex::Lock()
120
0
{
121
0
  MOZ_ASSERT(*mCount > 0, "Attempting to lock mutex with zero ref count");
122
0
  pthread_mutex_lock(mMutex);
123
0
}
124
125
void
126
CrossProcessMutex::Unlock()
127
0
{
128
0
  MOZ_ASSERT(*mCount > 0, "Attempting to unlock mutex with zero ref count");
129
0
  pthread_mutex_unlock(mMutex);
130
0
}
131
132
CrossProcessMutexHandle
133
CrossProcessMutex::ShareToProcess(base::ProcessId aTargetPid)
134
0
{
135
0
  CrossProcessMutexHandle result = ipc::SharedMemoryBasic::NULLHandle();
136
0
137
0
  if (mSharedBuffer && !mSharedBuffer->ShareToProcess(aTargetPid, &result)) {
138
0
    MOZ_CRASH();
139
0
  }
140
0
141
0
  return result;
142
0
}
143
144
} // namespace mozilla