1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #include "platform/mutex.h"
29
30 #include <cerrno>
31
32 namespace v8 {
33 namespace internal {
34
35 #if V8_OS_POSIX
36
InitializeNativeHandle(pthread_mutex_t * mutex)37 static V8_INLINE void InitializeNativeHandle(pthread_mutex_t* mutex) {
38 int result;
39 #if defined(DEBUG)
40 // Use an error checking mutex in debug mode.
41 pthread_mutexattr_t attr;
42 result = pthread_mutexattr_init(&attr);
43 ASSERT_EQ(0, result);
44 result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
45 ASSERT_EQ(0, result);
46 result = pthread_mutex_init(mutex, &attr);
47 ASSERT_EQ(0, result);
48 result = pthread_mutexattr_destroy(&attr);
49 #else
50 // Use a fast mutex (default attributes).
51 result = pthread_mutex_init(mutex, NULL);
52 #endif // defined(DEBUG)
53 ASSERT_EQ(0, result);
54 USE(result);
55 }
56
57
InitializeRecursiveNativeHandle(pthread_mutex_t * mutex)58 static V8_INLINE void InitializeRecursiveNativeHandle(pthread_mutex_t* mutex) {
59 pthread_mutexattr_t attr;
60 int result = pthread_mutexattr_init(&attr);
61 ASSERT_EQ(0, result);
62 result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
63 ASSERT_EQ(0, result);
64 result = pthread_mutex_init(mutex, &attr);
65 ASSERT_EQ(0, result);
66 result = pthread_mutexattr_destroy(&attr);
67 ASSERT_EQ(0, result);
68 USE(result);
69 }
70
71
DestroyNativeHandle(pthread_mutex_t * mutex)72 static V8_INLINE void DestroyNativeHandle(pthread_mutex_t* mutex) {
73 int result = pthread_mutex_destroy(mutex);
74 ASSERT_EQ(0, result);
75 USE(result);
76 }
77
78
LockNativeHandle(pthread_mutex_t * mutex)79 static V8_INLINE void LockNativeHandle(pthread_mutex_t* mutex) {
80 int result = pthread_mutex_lock(mutex);
81 ASSERT_EQ(0, result);
82 USE(result);
83 }
84
85
UnlockNativeHandle(pthread_mutex_t * mutex)86 static V8_INLINE void UnlockNativeHandle(pthread_mutex_t* mutex) {
87 int result = pthread_mutex_unlock(mutex);
88 ASSERT_EQ(0, result);
89 USE(result);
90 }
91
92
TryLockNativeHandle(pthread_mutex_t * mutex)93 static V8_INLINE bool TryLockNativeHandle(pthread_mutex_t* mutex) {
94 int result = pthread_mutex_trylock(mutex);
95 if (result == EBUSY) {
96 return false;
97 }
98 ASSERT_EQ(0, result);
99 return true;
100 }
101
102 #elif V8_OS_WIN
103
104 static V8_INLINE void InitializeNativeHandle(PCRITICAL_SECTION cs) {
105 InitializeCriticalSection(cs);
106 }
107
108
109 static V8_INLINE void InitializeRecursiveNativeHandle(PCRITICAL_SECTION cs) {
110 InitializeCriticalSection(cs);
111 }
112
113
114 static V8_INLINE void DestroyNativeHandle(PCRITICAL_SECTION cs) {
115 DeleteCriticalSection(cs);
116 }
117
118
119 static V8_INLINE void LockNativeHandle(PCRITICAL_SECTION cs) {
120 EnterCriticalSection(cs);
121 }
122
123
124 static V8_INLINE void UnlockNativeHandle(PCRITICAL_SECTION cs) {
125 LeaveCriticalSection(cs);
126 }
127
128
129 static V8_INLINE bool TryLockNativeHandle(PCRITICAL_SECTION cs) {
130 return TryEnterCriticalSection(cs);
131 }
132
133 #endif // V8_OS_POSIX
134
135
Mutex()136 Mutex::Mutex() {
137 InitializeNativeHandle(&native_handle_);
138 #ifdef DEBUG
139 level_ = 0;
140 #endif
141 }
142
143
~Mutex()144 Mutex::~Mutex() {
145 DestroyNativeHandle(&native_handle_);
146 ASSERT_EQ(0, level_);
147 }
148
149
Lock()150 void Mutex::Lock() {
151 LockNativeHandle(&native_handle_);
152 AssertUnheldAndMark();
153 }
154
155
Unlock()156 void Mutex::Unlock() {
157 AssertHeldAndUnmark();
158 UnlockNativeHandle(&native_handle_);
159 }
160
161
TryLock()162 bool Mutex::TryLock() {
163 if (!TryLockNativeHandle(&native_handle_)) {
164 return false;
165 }
166 AssertUnheldAndMark();
167 return true;
168 }
169
170
RecursiveMutex()171 RecursiveMutex::RecursiveMutex() {
172 InitializeRecursiveNativeHandle(&native_handle_);
173 #ifdef DEBUG
174 level_ = 0;
175 #endif
176 }
177
178
~RecursiveMutex()179 RecursiveMutex::~RecursiveMutex() {
180 DestroyNativeHandle(&native_handle_);
181 ASSERT_EQ(0, level_);
182 }
183
184
Lock()185 void RecursiveMutex::Lock() {
186 LockNativeHandle(&native_handle_);
187 #ifdef DEBUG
188 ASSERT_LE(0, level_);
189 level_++;
190 #endif
191 }
192
193
Unlock()194 void RecursiveMutex::Unlock() {
195 #ifdef DEBUG
196 ASSERT_LT(0, level_);
197 level_--;
198 #endif
199 UnlockNativeHandle(&native_handle_);
200 }
201
202
TryLock()203 bool RecursiveMutex::TryLock() {
204 if (!TryLockNativeHandle(&native_handle_)) {
205 return false;
206 }
207 #ifdef DEBUG
208 ASSERT_LE(0, level_);
209 level_++;
210 #endif
211 return true;
212 }
213
214 } } // namespace v8::internal
215