1// Copyright 2013 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/base/platform/mutex.h"
6
7#include <errno.h>
8
9namespace v8 {
10namespace base {
11
12#if V8_OS_POSIX
13
14static V8_INLINE void InitializeNativeHandle(pthread_mutex_t* mutex) {
15  int result;
16#if defined(DEBUG)
17  // Use an error checking mutex in debug mode.
18  pthread_mutexattr_t attr;
19  result = pthread_mutexattr_init(&attr);
20  DCHECK_EQ(0, result);
21  result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
22  DCHECK_EQ(0, result);
23  result = pthread_mutex_init(mutex, &attr);
24  DCHECK_EQ(0, result);
25  result = pthread_mutexattr_destroy(&attr);
26#else
27  // Use a fast mutex (default attributes).
28  result = pthread_mutex_init(mutex, NULL);
29#endif  // defined(DEBUG)
30  DCHECK_EQ(0, result);
31  USE(result);
32}
33
34
35static V8_INLINE void InitializeRecursiveNativeHandle(pthread_mutex_t* mutex) {
36  pthread_mutexattr_t attr;
37  int result = pthread_mutexattr_init(&attr);
38  DCHECK_EQ(0, result);
39  result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
40  DCHECK_EQ(0, result);
41  result = pthread_mutex_init(mutex, &attr);
42  DCHECK_EQ(0, result);
43  result = pthread_mutexattr_destroy(&attr);
44  DCHECK_EQ(0, result);
45  USE(result);
46}
47
48
49static V8_INLINE void DestroyNativeHandle(pthread_mutex_t* mutex) {
50  int result = pthread_mutex_destroy(mutex);
51  DCHECK_EQ(0, result);
52  USE(result);
53}
54
55
56static V8_INLINE void LockNativeHandle(pthread_mutex_t* mutex) {
57  int result = pthread_mutex_lock(mutex);
58  DCHECK_EQ(0, result);
59  USE(result);
60}
61
62
63static V8_INLINE void UnlockNativeHandle(pthread_mutex_t* mutex) {
64  int result = pthread_mutex_unlock(mutex);
65  DCHECK_EQ(0, result);
66  USE(result);
67}
68
69
70static V8_INLINE bool TryLockNativeHandle(pthread_mutex_t* mutex) {
71  int result = pthread_mutex_trylock(mutex);
72  if (result == EBUSY) {
73    return false;
74  }
75  DCHECK_EQ(0, result);
76  return true;
77}
78
79#elif V8_OS_WIN
80
81static V8_INLINE void InitializeNativeHandle(PCRITICAL_SECTION cs) {
82  InitializeCriticalSection(cs);
83}
84
85
86static V8_INLINE void InitializeRecursiveNativeHandle(PCRITICAL_SECTION cs) {
87  InitializeCriticalSection(cs);
88}
89
90
91static V8_INLINE void DestroyNativeHandle(PCRITICAL_SECTION cs) {
92  DeleteCriticalSection(cs);
93}
94
95
96static V8_INLINE void LockNativeHandle(PCRITICAL_SECTION cs) {
97  EnterCriticalSection(cs);
98}
99
100
101static V8_INLINE void UnlockNativeHandle(PCRITICAL_SECTION cs) {
102  LeaveCriticalSection(cs);
103}
104
105
106static V8_INLINE bool TryLockNativeHandle(PCRITICAL_SECTION cs) {
107  return TryEnterCriticalSection(cs);
108}
109
110#endif  // V8_OS_POSIX
111
112
113Mutex::Mutex() {
114  InitializeNativeHandle(&native_handle_);
115#ifdef DEBUG
116  level_ = 0;
117#endif
118}
119
120
121Mutex::~Mutex() {
122  DestroyNativeHandle(&native_handle_);
123  DCHECK_EQ(0, level_);
124}
125
126
127void Mutex::Lock() {
128  LockNativeHandle(&native_handle_);
129  AssertUnheldAndMark();
130}
131
132
133void Mutex::Unlock() {
134  AssertHeldAndUnmark();
135  UnlockNativeHandle(&native_handle_);
136}
137
138
139bool Mutex::TryLock() {
140  if (!TryLockNativeHandle(&native_handle_)) {
141    return false;
142  }
143  AssertUnheldAndMark();
144  return true;
145}
146
147
148RecursiveMutex::RecursiveMutex() {
149  InitializeRecursiveNativeHandle(&native_handle_);
150#ifdef DEBUG
151  level_ = 0;
152#endif
153}
154
155
156RecursiveMutex::~RecursiveMutex() {
157  DestroyNativeHandle(&native_handle_);
158  DCHECK_EQ(0, level_);
159}
160
161
162void RecursiveMutex::Lock() {
163  LockNativeHandle(&native_handle_);
164#ifdef DEBUG
165  DCHECK_LE(0, level_);
166  level_++;
167#endif
168}
169
170
171void RecursiveMutex::Unlock() {
172#ifdef DEBUG
173  DCHECK_LT(0, level_);
174  level_--;
175#endif
176  UnlockNativeHandle(&native_handle_);
177}
178
179
180bool RecursiveMutex::TryLock() {
181  if (!TryLockNativeHandle(&native_handle_)) {
182    return false;
183  }
184#ifdef DEBUG
185  DCHECK_LE(0, level_);
186  level_++;
187#endif
188  return true;
189}
190
191} }  // namespace v8::base
192