|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
2 * This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "CrossProcessMutex.h" |
|
7 #include "mozilla/unused.h" |
|
8 #include "nsDebug.h" |
|
9 #include "nsISupportsImpl.h" |
|
10 |
|
11 namespace { |
|
12 |
|
13 struct MutexData { |
|
14 pthread_mutex_t mMutex; |
|
15 mozilla::Atomic<int32_t> mCount; |
|
16 }; |
|
17 |
|
18 } |
|
19 |
|
20 namespace mozilla { |
|
21 |
|
22 CrossProcessMutex::CrossProcessMutex(const char*) |
|
23 : mSharedBuffer(nullptr) |
|
24 , mMutex(nullptr) |
|
25 , mCount(nullptr) |
|
26 { |
|
27 mSharedBuffer = new ipc::SharedMemoryBasic; |
|
28 if (!mSharedBuffer->Create(sizeof(MutexData))) { |
|
29 MOZ_CRASH(); |
|
30 } |
|
31 |
|
32 if (!mSharedBuffer->Map(sizeof(MutexData))) { |
|
33 MOZ_CRASH(); |
|
34 } |
|
35 |
|
36 MutexData* data = static_cast<MutexData*>(mSharedBuffer->memory()); |
|
37 |
|
38 if (!data) { |
|
39 MOZ_CRASH(); |
|
40 } |
|
41 |
|
42 mMutex = &(data->mMutex); |
|
43 mCount = &(data->mCount); |
|
44 |
|
45 *mCount = 1; |
|
46 |
|
47 pthread_mutexattr_t mutexAttributes; |
|
48 pthread_mutexattr_init(&mutexAttributes); |
|
49 // Make the mutex reentrant so it behaves the same as a win32 mutex |
|
50 if (pthread_mutexattr_settype(&mutexAttributes, PTHREAD_MUTEX_RECURSIVE)) { |
|
51 MOZ_CRASH(); |
|
52 } |
|
53 if (pthread_mutexattr_setpshared(&mutexAttributes, PTHREAD_PROCESS_SHARED)) { |
|
54 MOZ_CRASH(); |
|
55 } |
|
56 |
|
57 if (pthread_mutex_init(mMutex, &mutexAttributes)) { |
|
58 MOZ_CRASH(); |
|
59 } |
|
60 |
|
61 MOZ_COUNT_CTOR(CrossProcessMutex); |
|
62 } |
|
63 |
|
64 CrossProcessMutex::CrossProcessMutex(CrossProcessMutexHandle aHandle) |
|
65 : mSharedBuffer(nullptr) |
|
66 , mMutex(nullptr) |
|
67 , mCount(nullptr) |
|
68 { |
|
69 if (!ipc::SharedMemoryBasic::IsHandleValid(aHandle)) { |
|
70 MOZ_CRASH(); |
|
71 } |
|
72 |
|
73 mSharedBuffer = new ipc::SharedMemoryBasic(aHandle); |
|
74 |
|
75 if (!mSharedBuffer->Map(sizeof(MutexData))) { |
|
76 MOZ_CRASH(); |
|
77 } |
|
78 |
|
79 MutexData* data = static_cast<MutexData*>(mSharedBuffer->memory()); |
|
80 |
|
81 if (!data) { |
|
82 MOZ_CRASH(); |
|
83 } |
|
84 |
|
85 mMutex = &(data->mMutex); |
|
86 mCount = &(data->mCount); |
|
87 (*mCount)++; |
|
88 |
|
89 MOZ_COUNT_CTOR(CrossProcessMutex); |
|
90 } |
|
91 |
|
92 CrossProcessMutex::~CrossProcessMutex() |
|
93 { |
|
94 int32_t count = --(*mCount); |
|
95 |
|
96 if (count == 0) { |
|
97 // Nothing can be done if the destroy fails so ignore return code. |
|
98 unused << pthread_mutex_destroy(mMutex); |
|
99 } |
|
100 |
|
101 delete mSharedBuffer; |
|
102 MOZ_COUNT_DTOR(CrossProcessMutex); |
|
103 } |
|
104 |
|
105 void |
|
106 CrossProcessMutex::Lock() |
|
107 { |
|
108 MOZ_ASSERT(*mCount > 0, "Attempting to lock mutex with zero ref count"); |
|
109 pthread_mutex_lock(mMutex); |
|
110 } |
|
111 |
|
112 void |
|
113 CrossProcessMutex::Unlock() |
|
114 { |
|
115 MOZ_ASSERT(*mCount > 0, "Attempting to unlock mutex with zero ref count"); |
|
116 pthread_mutex_unlock(mMutex); |
|
117 } |
|
118 |
|
119 CrossProcessMutexHandle |
|
120 CrossProcessMutex::ShareToProcess(base::ProcessHandle aHandle) |
|
121 { |
|
122 CrossProcessMutexHandle result = ipc::SharedMemoryBasic::NULLHandle(); |
|
123 |
|
124 if (mSharedBuffer && !mSharedBuffer->ShareToProcess(aHandle, &result)) { |
|
125 MOZ_CRASH(); |
|
126 } |
|
127 |
|
128 return result; |
|
129 } |
|
130 |
|
131 } |