Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Unified Diff: webrtc/base/criticalsection.cc

Issue 1594723003: New lock implementation for mac (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Address comments Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/base/criticalsection.h ('k') | webrtc/base/criticalsection_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/base/criticalsection.cc
diff --git a/webrtc/base/criticalsection.cc b/webrtc/base/criticalsection.cc
index 2c6b100a7dfdfa4c92e179f54f58ba2eea54e40c..d3f42f4a9fe90e532ef31e1523936bba12324a04 100644
--- a/webrtc/base/criticalsection.cc
+++ b/webrtc/base/criticalsection.cc
@@ -12,17 +12,26 @@
#include "webrtc/base/checks.h"
+// TODO(tommi): Split this file up to per-platform implementation files.
+
namespace rtc {
CriticalSection::CriticalSection() {
#if defined(WEBRTC_WIN)
InitializeCriticalSection(&crit_);
#else
+#if defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
+ lock_queue_ = 0;
+ owning_thread_ = 0;
+ recursion_ = 0;
+ semaphore_ = dispatch_semaphore_create(0);
+#else
pthread_mutexattr_t mutex_attribute;
pthread_mutexattr_init(&mutex_attribute);
pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mutex_, &mutex_attribute);
pthread_mutexattr_destroy(&mutex_attribute);
+#endif
CS_DEBUG_CODE(thread_ = 0);
CS_DEBUG_CODE(recursion_count_ = 0);
#endif
@@ -32,15 +41,59 @@ CriticalSection::~CriticalSection() {
#if defined(WEBRTC_WIN)
DeleteCriticalSection(&crit_);
#else
+#if defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
+ dispatch_release(semaphore_);
+#else
pthread_mutex_destroy(&mutex_);
#endif
+#endif
}
void CriticalSection::Enter() const EXCLUSIVE_LOCK_FUNCTION() {
#if defined(WEBRTC_WIN)
EnterCriticalSection(&crit_);
#else
+#if defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
+ int spin = 3000;
+ pthread_t self = pthread_self();
+ bool have_lock = false;
+ do {
+ // Instead of calling TryEnter() in this loop, we do two interlocked
+ // operations, first a read-only one in order to avoid affecting the lock
+ // cache-line while spinning, in case another thread is using the lock.
+ if (owning_thread_ != self) {
joachim 2016/01/22 08:35:38 Maybe change this to use "pthread_equal" to compar
tommi 2016/01/22 08:51:59 Ah, thanks. I had meant to use PlatformThreadRef a
+ if (AtomicOps::AcquireLoad(&lock_queue_) == 0) {
+ if (AtomicOps::CompareAndSwap(&lock_queue_, 0, 1) == 0) {
+ have_lock = true;
+ break;
+ }
+ }
+ } else {
+ AtomicOps::Increment(&lock_queue_);
+ have_lock = true;
+ break;
+ }
+
+ sched_yield();
+ } while (--spin);
+
+ if (!have_lock && AtomicOps::Increment(&lock_queue_) > 1) {
+ // Owning thread cannot be the current thread since TryEnter() would
+ // have succeeded.
+ RTC_DCHECK(owning_thread_ != self);
joachim 2016/01/22 08:35:38 Same here.
+ // Wait for the lock to become available.
+ dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
+ RTC_DCHECK(owning_thread_ == 0);
+ RTC_DCHECK(!recursion_);
+ }
+
+ owning_thread_ = self;
+ ++recursion_;
+
+#else
pthread_mutex_lock(&mutex_);
+#endif
+
#if CS_DEBUG_CHECKS
if (!recursion_count_) {
RTC_DCHECK(!thread_);
@@ -57,8 +110,20 @@ bool CriticalSection::TryEnter() const EXCLUSIVE_TRYLOCK_FUNCTION(true) {
#if defined(WEBRTC_WIN)
return TryEnterCriticalSection(&crit_) != FALSE;
#else
+#if defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
+ if (owning_thread_ != pthread_self()) {
joachim 2016/01/22 08:35:38 And here.
+ if (AtomicOps::CompareAndSwap(&lock_queue_, 0, 1) != 0)
+ return false;
+ owning_thread_ = pthread_self();
+ RTC_DCHECK(!recursion_);
+ } else {
+ AtomicOps::Increment(&lock_queue_);
+ }
+ ++recursion_;
+#else
if (pthread_mutex_trylock(&mutex_) != 0)
return false;
+#endif
#if CS_DEBUG_CHECKS
if (!recursion_count_) {
RTC_DCHECK(!thread_);
@@ -82,8 +147,19 @@ void CriticalSection::Leave() const UNLOCK_FUNCTION() {
if (!recursion_count_)
thread_ = 0;
#endif
+#if defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
+ RTC_DCHECK_EQ(owning_thread_, pthread_self());
+ RTC_DCHECK_GE(recursion_, 0);
+ --recursion_;
+ if (!recursion_)
+ owning_thread_ = 0;
+
+ if (AtomicOps::Decrement(&lock_queue_) > 0 && !recursion_)
+ dispatch_semaphore_signal(semaphore_);
+#else
pthread_mutex_unlock(&mutex_);
#endif
+#endif
}
bool CriticalSection::CurrentThreadIsOwner() const {
@@ -135,13 +211,15 @@ bool TryCritScope::locked() const {
}
void GlobalLockPod::Lock() {
-#if !defined(WEBRTC_WIN)
+#if !defined(WEBRTC_WIN) && (!defined(WEBRTC_MAC) || USE_NATIVE_MUTEX_ON_MAC)
const struct timespec ts_null = {0};
#endif
while (AtomicOps::CompareAndSwap(&lock_acquired, 0, 1)) {
#if defined(WEBRTC_WIN)
::Sleep(0);
+#elif defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
+ sched_yield();
#else
nanosleep(&ts_null, nullptr);
#endif
« no previous file with comments | « webrtc/base/criticalsection.h ('k') | webrtc/base/criticalsection_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698