#include "src/base/platform/mutex.h"
#include <errno.h>
#include <atomic>
#include "src/base/platform/condition-variable.h"
#if DEBUG
#include <unordered_set>
#endif
#if V8_OS_WIN
#include <windows.h>
#endif
namespace v8 {
namespace base {
#if DEBUG
namespace {
thread_local base::SharedMutex* single_held_shared_mutex = …;
TSet;
thread_local TSet* held_shared_mutexes = …;
bool SharedMutexNotHeld(SharedMutex* shared_mutex) { … }
bool TryHoldSharedMutex(SharedMutex* shared_mutex) { … }
bool TryReleaseSharedMutex(SharedMutex* shared_mutex) { … }
}
#endif
#if V8_OS_POSIX
static V8_INLINE void InitializeNativeHandle(pthread_mutex_t* mutex) { … }
static V8_INLINE void InitializeRecursiveNativeHandle(pthread_mutex_t* mutex) { … }
static V8_INLINE void DestroyNativeHandle(pthread_mutex_t* mutex) { … }
static V8_INLINE void LockNativeHandle(pthread_mutex_t* mutex) { … }
static V8_INLINE void UnlockNativeHandle(pthread_mutex_t* mutex) { … }
static V8_INLINE bool TryLockNativeHandle(pthread_mutex_t* mutex) { … }
Mutex::Mutex() { … }
Mutex::~Mutex() { … }
void Mutex::Lock() { … }
void Mutex::Unlock() { … }
bool Mutex::TryLock() { … }
RecursiveMutex::RecursiveMutex() { … }
RecursiveMutex::~RecursiveMutex() { … }
void RecursiveMutex::Lock() { … }
void RecursiveMutex::Unlock() { … }
bool RecursiveMutex::TryLock() { … }
#if V8_OS_DARWIN
SharedMutex::SharedMutex() = default;
SharedMutex::~SharedMutex() = default;
void SharedMutex::LockShared() {
DCHECK(TryHoldSharedMutex(this));
native_handle_.lock_shared();
}
void SharedMutex::LockExclusive() {
DCHECK(TryHoldSharedMutex(this));
native_handle_.lock();
}
void SharedMutex::UnlockShared() {
DCHECK(TryReleaseSharedMutex(this));
native_handle_.unlock_shared();
}
void SharedMutex::UnlockExclusive() {
DCHECK(TryReleaseSharedMutex(this));
native_handle_.unlock();
}
bool SharedMutex::TryLockShared() {
DCHECK(SharedMutexNotHeld(this));
bool result = native_handle_.try_lock_shared();
if (result) DCHECK(TryHoldSharedMutex(this));
return result;
}
bool SharedMutex::TryLockExclusive() {
DCHECK(SharedMutexNotHeld(this));
bool result = native_handle_.try_lock();
if (result) DCHECK(TryHoldSharedMutex(this));
return result;
}
#else
SharedMutex::SharedMutex() { … }
SharedMutex::~SharedMutex() { … }
void SharedMutex::LockShared() { … }
void SharedMutex::LockExclusive() { … }
void SharedMutex::UnlockShared() { … }
void SharedMutex::UnlockExclusive() { … }
bool SharedMutex::TryLockShared() { … }
bool SharedMutex::TryLockExclusive() { … }
#endif
#elif V8_OS_WIN
Mutex::Mutex() : native_handle_(SRWLOCK_INIT) {
#ifdef DEBUG
level_ = 0;
#endif
}
Mutex::~Mutex() {
DCHECK_EQ(0, level_);
}
void Mutex::Lock() {
AcquireSRWLockExclusive(V8ToWindowsType(&native_handle_));
AssertUnheldAndMark();
}
void Mutex::Unlock() {
AssertHeldAndUnmark();
ReleaseSRWLockExclusive(V8ToWindowsType(&native_handle_));
}
bool Mutex::TryLock() {
if (!TryAcquireSRWLockExclusive(V8ToWindowsType(&native_handle_))) {
return false;
}
AssertUnheldAndMark();
return true;
}
RecursiveMutex::RecursiveMutex() {
InitializeCriticalSection(V8ToWindowsType(&native_handle_));
#ifdef DEBUG
level_ = 0;
#endif
}
RecursiveMutex::~RecursiveMutex() {
DeleteCriticalSection(V8ToWindowsType(&native_handle_));
DCHECK_EQ(0, level_);
}
void RecursiveMutex::Lock() {
EnterCriticalSection(V8ToWindowsType(&native_handle_));
#ifdef DEBUG
DCHECK_LE(0, level_);
level_++;
#endif
}
void RecursiveMutex::Unlock() {
#ifdef DEBUG
DCHECK_LT(0, level_);
level_--;
#endif
LeaveCriticalSection(V8ToWindowsType(&native_handle_));
}
bool RecursiveMutex::TryLock() {
if (!TryEnterCriticalSection(V8ToWindowsType(&native_handle_))) {
return false;
}
#ifdef DEBUG
DCHECK_LE(0, level_);
level_++;
#endif
return true;
}
SharedMutex::SharedMutex() : native_handle_(SRWLOCK_INIT) {}
SharedMutex::~SharedMutex() {}
void SharedMutex::LockShared() {
DCHECK(TryHoldSharedMutex(this));
AcquireSRWLockShared(V8ToWindowsType(&native_handle_));
}
void SharedMutex::LockExclusive() {
DCHECK(TryHoldSharedMutex(this));
AcquireSRWLockExclusive(V8ToWindowsType(&native_handle_));
}
void SharedMutex::UnlockShared() {
DCHECK(TryReleaseSharedMutex(this));
ReleaseSRWLockShared(V8ToWindowsType(&native_handle_));
}
void SharedMutex::UnlockExclusive() {
DCHECK(TryReleaseSharedMutex(this));
ReleaseSRWLockExclusive(V8ToWindowsType(&native_handle_));
}
bool SharedMutex::TryLockShared() {
DCHECK(SharedMutexNotHeld(this));
bool result = TryAcquireSRWLockShared(V8ToWindowsType(&native_handle_));
if (result) DCHECK(TryHoldSharedMutex(this));
return result;
}
bool SharedMutex::TryLockExclusive() {
DCHECK(SharedMutexNotHeld(this));
bool result = TryAcquireSRWLockExclusive(V8ToWindowsType(&native_handle_));
if (result) DCHECK(TryHoldSharedMutex(this));
return result;
}
#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() {
DCHECK(TryHoldSharedMutex(this));
native_handle_.AcquireReadLock();
}
void SharedMutex::LockExclusive() {
DCHECK(TryHoldSharedMutex(this));
native_handle_.AcquireWriteLock();
}
void SharedMutex::UnlockShared() {
DCHECK(TryReleaseSharedMutex(this));
native_handle_.ReleaseReadLock();
}
void SharedMutex::UnlockExclusive() {
DCHECK(TryReleaseSharedMutex(this));
native_handle_.ReleaseWriteLock();
}
bool SharedMutex::TryLockShared() {
DCHECK(SharedMutexNotHeld(this));
return false;
}
bool SharedMutex::TryLockExclusive() {
DCHECK(SharedMutexNotHeld(this));
return false;
}
#endif
}
}