mutex.cc 6.7 KB
Newer Older
1
// Copyright 2013 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4

5
#include "src/base/platform/mutex.h"
6

7
#include <errno.h>
8 9

namespace v8 {
10
namespace base {
11 12 13

#if V8_OS_POSIX

14
static V8_INLINE void InitializeNativeHandle(pthread_mutex_t* mutex) {
15 16 17 18 19
  int result;
#if defined(DEBUG)
  // Use an error checking mutex in debug mode.
  pthread_mutexattr_t attr;
  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 26 27
  result = pthread_mutexattr_destroy(&attr);
#else
  // Use a fast mutex (default attributes).
28
  result = pthread_mutex_init(mutex, nullptr);
29
#endif  // defined(DEBUG)
30
  DCHECK_EQ(0, result);
31 32 33 34
  USE(result);
}


35
static V8_INLINE void InitializeRecursiveNativeHandle(pthread_mutex_t* mutex) {
36 37
  pthread_mutexattr_t attr;
  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 46 47 48
  USE(result);
}


49
static V8_INLINE void DestroyNativeHandle(pthread_mutex_t* mutex) {
50
  int result = pthread_mutex_destroy(mutex);
51
  DCHECK_EQ(0, result);
52 53 54 55
  USE(result);
}


56
static V8_INLINE void LockNativeHandle(pthread_mutex_t* mutex) {
57
  int result = pthread_mutex_lock(mutex);
58
  DCHECK_EQ(0, result);
59 60 61 62
  USE(result);
}


63
static V8_INLINE void UnlockNativeHandle(pthread_mutex_t* mutex) {
64
  int result = pthread_mutex_unlock(mutex);
65
  DCHECK_EQ(0, result);
66 67 68 69
  USE(result);
}


70
static V8_INLINE bool TryLockNativeHandle(pthread_mutex_t* mutex) {
71 72 73 74
  int result = pthread_mutex_trylock(mutex);
  if (result == EBUSY) {
    return false;
  }
75
  DCHECK_EQ(0, result);
76 77 78 79
  return true;
}


80 81 82 83 84
Mutex::Mutex() {
  InitializeNativeHandle(&native_handle_);
#ifdef DEBUG
  level_ = 0;
#endif
85 86 87
}


88 89 90
Mutex::~Mutex() {
  DestroyNativeHandle(&native_handle_);
  DCHECK_EQ(0, level_);
91 92 93
}


94 95 96
void Mutex::Lock() {
  LockNativeHandle(&native_handle_);
  AssertUnheldAndMark();
97 98 99
}


100 101 102
void Mutex::Unlock() {
  AssertHeldAndUnmark();
  UnlockNativeHandle(&native_handle_);
103 104 105
}


106 107 108 109 110 111
bool Mutex::TryLock() {
  if (!TryLockNativeHandle(&native_handle_)) {
    return false;
  }
  AssertUnheldAndMark();
  return true;
112 113 114
}


115 116 117 118 119
RecursiveMutex::RecursiveMutex() {
  InitializeRecursiveNativeHandle(&native_handle_);
#ifdef DEBUG
  level_ = 0;
#endif
120 121 122
}


123 124 125 126
RecursiveMutex::~RecursiveMutex() {
  DestroyNativeHandle(&native_handle_);
  DCHECK_EQ(0, level_);
}
127

128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157

void RecursiveMutex::Lock() {
  LockNativeHandle(&native_handle_);
#ifdef DEBUG
  DCHECK_LE(0, level_);
  level_++;
#endif
}


void RecursiveMutex::Unlock() {
#ifdef DEBUG
  DCHECK_LT(0, level_);
  level_--;
#endif
  UnlockNativeHandle(&native_handle_);
}


bool RecursiveMutex::TryLock() {
  if (!TryLockNativeHandle(&native_handle_)) {
    return false;
  }
#ifdef DEBUG
  DCHECK_LE(0, level_);
  level_++;
#endif
  return true;
}

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
SharedMutex::SharedMutex() { pthread_rwlock_init(&native_handle_, nullptr); }

SharedMutex::~SharedMutex() {
  int result = pthread_rwlock_destroy(&native_handle_);
  DCHECK_EQ(0, result);
  USE(result);
}

void SharedMutex::LockShared() {
  int result = pthread_rwlock_rdlock(&native_handle_);
  DCHECK_EQ(0, result);
  USE(result);
}

void SharedMutex::LockExclusive() {
  int result = pthread_rwlock_wrlock(&native_handle_);
  DCHECK_EQ(0, result);
  USE(result);
}

void SharedMutex::UnlockShared() {
  int result = pthread_rwlock_unlock(&native_handle_);
  DCHECK_EQ(0, result);
  USE(result);
}

void SharedMutex::UnlockExclusive() {
  // Same code as {UnlockShared} on POSIX.
  UnlockShared();
}

bool SharedMutex::TryLockShared() {
  return pthread_rwlock_tryrdlock(&native_handle_) == 0;
}

bool SharedMutex::TryLockExclusive() {
  return pthread_rwlock_trywrlock(&native_handle_) == 0;
}

197 198 199
#elif V8_OS_WIN

Mutex::Mutex() : native_handle_(SRWLOCK_INIT) {
200 201 202 203 204 205 206
#ifdef DEBUG
  level_ = 0;
#endif
}


Mutex::~Mutex() {
207
  DCHECK_EQ(0, level_);
208 209 210 211
}


void Mutex::Lock() {
212
  AcquireSRWLockExclusive(&native_handle_);
213
  AssertUnheldAndMark();
214 215 216 217
}


void Mutex::Unlock() {
218
  AssertHeldAndUnmark();
219
  ReleaseSRWLockExclusive(&native_handle_);
220 221 222 223
}


bool Mutex::TryLock() {
224
  if (!TryAcquireSRWLockExclusive(&native_handle_)) {
225 226
    return false;
  }
227
  AssertUnheldAndMark();
228 229 230 231 232
  return true;
}


RecursiveMutex::RecursiveMutex() {
233
  InitializeCriticalSection(&native_handle_);
234 235 236 237 238 239 240
#ifdef DEBUG
  level_ = 0;
#endif
}


RecursiveMutex::~RecursiveMutex() {
241
  DeleteCriticalSection(&native_handle_);
242
  DCHECK_EQ(0, level_);
243 244 245 246
}


void RecursiveMutex::Lock() {
247
  EnterCriticalSection(&native_handle_);
248
#ifdef DEBUG
249
  DCHECK_LE(0, level_);
250 251 252 253 254 255 256
  level_++;
#endif
}


void RecursiveMutex::Unlock() {
#ifdef DEBUG
257
  DCHECK_LT(0, level_);
258 259
  level_--;
#endif
260
  LeaveCriticalSection(&native_handle_);
261 262 263 264
}


bool RecursiveMutex::TryLock() {
265
  if (!TryEnterCriticalSection(&native_handle_)) {
266 267 268
    return false;
  }
#ifdef DEBUG
269
  DCHECK_LE(0, level_);
270 271 272 273 274
  level_++;
#endif
  return true;
}

275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
SharedMutex::SharedMutex() : native_handle_(SRWLOCK_INIT) {}

SharedMutex::~SharedMutex() {}

void SharedMutex::LockShared() { AcquireSRWLockShared(&native_handle_); }

void SharedMutex::LockExclusive() { AcquireSRWLockExclusive(&native_handle_); }

void SharedMutex::UnlockShared() { ReleaseSRWLockShared(&native_handle_); }

void SharedMutex::UnlockExclusive() {
  ReleaseSRWLockExclusive(&native_handle_);
}

bool SharedMutex::TryLockShared() {
  return TryAcquireSRWLockShared(&native_handle_);
}

bool SharedMutex::TryLockExclusive() {
  return TryAcquireSRWLockExclusive(&native_handle_);
}

johnx's avatar
johnx committed
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
#elif V8_OS_STARBOARD

Mutex::Mutex() { SbMutexCreate(&native_handle_); }

Mutex::~Mutex() { SbMutexDestroy(&native_handle_); }

void Mutex::Lock() { SbMutexAcquire(&native_handle_); }

void Mutex::Unlock() { SbMutexRelease(&native_handle_); }

RecursiveMutex::RecursiveMutex() {}

RecursiveMutex::~RecursiveMutex() {}

void RecursiveMutex::Lock() { native_handle_.Acquire(); }

void RecursiveMutex::Unlock() { native_handle_.Release(); }

bool RecursiveMutex::TryLock() { return native_handle_.AcquireTry(); }

SharedMutex::SharedMutex() = default;

SharedMutex::~SharedMutex() = default;

void SharedMutex::LockShared() { native_handle_.AcquireReadLock(); }

void SharedMutex::LockExclusive() { native_handle_.AcquireWriteLock(); }

void SharedMutex::UnlockShared() { native_handle_.ReleaseReadLock(); }

void SharedMutex::UnlockExclusive() { native_handle_.ReleaseWriteLock(); }

bool SharedMutex::TryLockShared() { return false; }

bool SharedMutex::TryLockExclusive() { return false; }
#endif  // V8_OS_STARBOARD
333

334 335
}  // namespace base
}  // namespace v8