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

Side by Side 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: Attempt to fix win build error 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2015 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/base/criticalsection.h" 11 #include "webrtc/base/criticalsection.h"
12 12
13 #include "webrtc/base/checks.h" 13 #include "webrtc/base/checks.h"
14 14
15 // TODO(tommi): Split this file up to per-platform implementation files.
16
15 namespace rtc { 17 namespace rtc {
16 18
17 CriticalSection::CriticalSection() { 19 CriticalSection::CriticalSection() {
18 #if defined(WEBRTC_WIN) 20 #if defined(WEBRTC_WIN)
19 InitializeCriticalSection(&crit_); 21 InitializeCriticalSection(&crit_);
20 #else 22 #else
23 #if defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
24 lock_queue_ = 0;
25 owning_thread_ = 0;
26 recursion_ = 0;
27 semaphore_ = dispatch_semaphore_create(0);
28 #else
21 pthread_mutexattr_t mutex_attribute; 29 pthread_mutexattr_t mutex_attribute;
22 pthread_mutexattr_init(&mutex_attribute); 30 pthread_mutexattr_init(&mutex_attribute);
23 pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE); 31 pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE);
24 pthread_mutex_init(&mutex_, &mutex_attribute); 32 pthread_mutex_init(&mutex_, &mutex_attribute);
25 pthread_mutexattr_destroy(&mutex_attribute); 33 pthread_mutexattr_destroy(&mutex_attribute);
34 #endif
26 CS_DEBUG_CODE(thread_ = 0); 35 CS_DEBUG_CODE(thread_ = 0);
27 CS_DEBUG_CODE(recursion_count_ = 0); 36 CS_DEBUG_CODE(recursion_count_ = 0);
28 #endif 37 #endif
29 } 38 }
30 39
31 CriticalSection::~CriticalSection() { 40 CriticalSection::~CriticalSection() {
32 #if defined(WEBRTC_WIN) 41 #if defined(WEBRTC_WIN)
33 DeleteCriticalSection(&crit_); 42 DeleteCriticalSection(&crit_);
34 #else 43 #else
44 #if defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
45 dispatch_release(semaphore_);
46 #else
35 pthread_mutex_destroy(&mutex_); 47 pthread_mutex_destroy(&mutex_);
36 #endif 48 #endif
49 #endif
37 } 50 }
38 51
39 void CriticalSection::Enter() EXCLUSIVE_LOCK_FUNCTION() { 52 void CriticalSection::Enter() EXCLUSIVE_LOCK_FUNCTION() {
40 #if defined(WEBRTC_WIN) 53 #if defined(WEBRTC_WIN)
41 EnterCriticalSection(&crit_); 54 EnterCriticalSection(&crit_);
42 #else 55 #else
56 #if defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
57 int spin = 3000;
58 pthread_t self = pthread_self();
59 bool have_lock = false;
60 do {
61 // Instead of calling TryEnter() in this loop, we do two interlocked
62 // operations, first a read-only one in order to avoid affecting the the
torbjorng (webrtc) 2016/01/21 16:57:23 Nit: The the the there should be fixed.
tommi 2016/01/21 22:02:47 addressed the the the the comment.
63 // lock cache-line while spinning, in case another thread is using the lock.
64 if (owning_thread_ != self) {
65 if (AtomicOps::AcquireLoad(&lock_queue_) == 0) {
66 if (AtomicOps::CompareAndSwap(&lock_queue_, 0, 1) == 0) {
67 have_lock = true;
68 break;
69 }
70 }
71 } else {
72 AtomicOps::Increment(&lock_queue_);
73 have_lock = true;
74 break;
75 }
76
77 sched_yield();
78 } while (--spin);
79
80 if (!have_lock && AtomicOps::Increment(&lock_queue_) > 0) {
81 // Owning thread cannot be the current thread since TryEnter() would
82 // have succeeded.
83 RTC_DCHECK(owning_thread_ != pthread_self());
torbjorng (webrtc) 2016/01/21 16:57:23 pthread_self() -> self
tommi 2016/01/21 22:02:47 Done.
84 // Wait for the lock to become available.
85 dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
86 RTC_DCHECK(owning_thread_ == 0);
87 RTC_DCHECK(!recursion_);
88 }
89
90 owning_thread_ = self;
91 ++recursion_;
92
93 #else
43 pthread_mutex_lock(&mutex_); 94 pthread_mutex_lock(&mutex_);
95 #endif
96
44 #if CS_DEBUG_CHECKS 97 #if CS_DEBUG_CHECKS
45 if (!recursion_count_) { 98 if (!recursion_count_) {
46 RTC_DCHECK(!thread_); 99 RTC_DCHECK(!thread_);
47 thread_ = pthread_self(); 100 thread_ = pthread_self();
48 } else { 101 } else {
49 RTC_DCHECK(CurrentThreadIsOwner()); 102 RTC_DCHECK(CurrentThreadIsOwner());
50 } 103 }
51 ++recursion_count_; 104 ++recursion_count_;
52 #endif 105 #endif
53 #endif 106 #endif
54 } 107 }
55 108
56 bool CriticalSection::TryEnter() EXCLUSIVE_TRYLOCK_FUNCTION(true) { 109 bool CriticalSection::TryEnter() EXCLUSIVE_TRYLOCK_FUNCTION(true) {
57 #if defined(WEBRTC_WIN) 110 #if defined(WEBRTC_WIN)
58 return TryEnterCriticalSection(&crit_) != FALSE; 111 return TryEnterCriticalSection(&crit_) != FALSE;
59 #else 112 #else
113 #if defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
114 if (owning_thread_ != pthread_self()) {
115 if (AtomicOps::CompareAndSwap(&lock_queue_, 0, 1) != 0)
116 return false;
117 owning_thread_ = pthread_self();
118 RTC_DCHECK(!recursion_);
119 } else {
120 AtomicOps::Increment(&lock_queue_);
121 }
122 ++recursion_;
123 #else
60 if (pthread_mutex_trylock(&mutex_) != 0) 124 if (pthread_mutex_trylock(&mutex_) != 0)
61 return false; 125 return false;
126 #endif
62 #if CS_DEBUG_CHECKS 127 #if CS_DEBUG_CHECKS
63 if (!recursion_count_) { 128 if (!recursion_count_) {
64 RTC_DCHECK(!thread_); 129 RTC_DCHECK(!thread_);
65 thread_ = pthread_self(); 130 thread_ = pthread_self();
66 } else { 131 } else {
67 RTC_DCHECK(CurrentThreadIsOwner()); 132 RTC_DCHECK(CurrentThreadIsOwner());
68 } 133 }
69 ++recursion_count_; 134 ++recursion_count_;
70 #endif 135 #endif
71 return true; 136 return true;
72 #endif 137 #endif
73 } 138 }
74 void CriticalSection::Leave() UNLOCK_FUNCTION() { 139 void CriticalSection::Leave() UNLOCK_FUNCTION() {
75 RTC_DCHECK(CurrentThreadIsOwner()); 140 RTC_DCHECK(CurrentThreadIsOwner());
76 #if defined(WEBRTC_WIN) 141 #if defined(WEBRTC_WIN)
77 LeaveCriticalSection(&crit_); 142 LeaveCriticalSection(&crit_);
78 #else 143 #else
79 #if CS_DEBUG_CHECKS 144 #if CS_DEBUG_CHECKS
80 --recursion_count_; 145 --recursion_count_;
81 RTC_DCHECK(recursion_count_ >= 0); 146 RTC_DCHECK(recursion_count_ >= 0);
82 if (!recursion_count_) 147 if (!recursion_count_)
83 thread_ = 0; 148 thread_ = 0;
84 #endif 149 #endif
150 #if defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
151 RTC_DCHECK_EQ(owning_thread_, pthread_self());
152 RTC_DCHECK_GE(recursion_, 0);
153 --recursion_;
154 if (!recursion_)
155 owning_thread_ = 0;
156
157 if (AtomicOps::Decrement(&lock_queue_) > 0 && !recursion_)
158 dispatch_semaphore_signal(semaphore_);
159 #else
85 pthread_mutex_unlock(&mutex_); 160 pthread_mutex_unlock(&mutex_);
86 #endif 161 #endif
162 #endif
87 } 163 }
88 164
89 bool CriticalSection::CurrentThreadIsOwner() const { 165 bool CriticalSection::CurrentThreadIsOwner() const {
90 #if defined(WEBRTC_WIN) 166 #if defined(WEBRTC_WIN)
91 // OwningThread has type HANDLE but actually contains the Thread ID: 167 // OwningThread has type HANDLE but actually contains the Thread ID:
92 // http://stackoverflow.com/questions/12675301/why-is-the-owningthread-member- of-critical-section-of-type-handle-when-it-is-de 168 // http://stackoverflow.com/questions/12675301/why-is-the-owningthread-member- of-critical-section-of-type-handle-when-it-is-de
93 // Converting through size_t avoids the VS 2015 warning C4312: conversion from 169 // Converting through size_t avoids the VS 2015 warning C4312: conversion from
94 // 'type1' to 'type2' of greater size 170 // 'type1' to 'type2' of greater size
95 return crit_.OwningThread == 171 return crit_.OwningThread ==
96 reinterpret_cast<HANDLE>(static_cast<size_t>(GetCurrentThreadId())); 172 reinterpret_cast<HANDLE>(static_cast<size_t>(GetCurrentThreadId()));
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 if (locked_) 204 if (locked_)
129 cs_->Leave(); 205 cs_->Leave();
130 } 206 }
131 207
132 bool TryCritScope::locked() const { 208 bool TryCritScope::locked() const {
133 CS_DEBUG_CODE(lock_was_called_ = true); 209 CS_DEBUG_CODE(lock_was_called_ = true);
134 return locked_; 210 return locked_;
135 } 211 }
136 212
137 void GlobalLockPod::Lock() { 213 void GlobalLockPod::Lock() {
138 #if !defined(WEBRTC_WIN) 214 #if !defined(WEBRTC_WIN) && (!defined(WEBRTC_MAC) || USE_NATIVE_MUTEX_ON_MAC)
139 const struct timespec ts_null = {0}; 215 const struct timespec ts_null = {0};
140 #endif 216 #endif
141 217
142 while (AtomicOps::CompareAndSwap(&lock_acquired, 0, 1)) { 218 while (AtomicOps::CompareAndSwap(&lock_acquired, 0, 1)) {
143 #if defined(WEBRTC_WIN) 219 #if defined(WEBRTC_WIN)
144 ::Sleep(0); 220 ::Sleep(0);
221 #elif defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
222 sched_yield();
145 #else 223 #else
146 nanosleep(&ts_null, nullptr); 224 nanosleep(&ts_null, nullptr);
147 #endif 225 #endif
148 } 226 }
149 } 227 }
150 228
151 void GlobalLockPod::Unlock() { 229 void GlobalLockPod::Unlock() {
152 int old_value = AtomicOps::CompareAndSwap(&lock_acquired, 1, 0); 230 int old_value = AtomicOps::CompareAndSwap(&lock_acquired, 1, 0);
153 RTC_DCHECK_EQ(1, old_value) << "Unlock called without calling Lock first"; 231 RTC_DCHECK_EQ(1, old_value) << "Unlock called without calling Lock first";
154 } 232 }
155 233
156 GlobalLock::GlobalLock() { 234 GlobalLock::GlobalLock() {
157 lock_acquired = 0; 235 lock_acquired = 0;
158 } 236 }
159 237
160 GlobalLockScope::GlobalLockScope(GlobalLockPod* lock) 238 GlobalLockScope::GlobalLockScope(GlobalLockPod* lock)
161 : lock_(lock) { 239 : lock_(lock) {
162 lock_->Lock(); 240 lock_->Lock();
163 } 241 }
164 242
165 GlobalLockScope::~GlobalLockScope() { 243 GlobalLockScope::~GlobalLockScope() {
166 lock_->Unlock(); 244 lock_->Unlock();
167 } 245 }
168 246
169 } // namespace rtc 247 } // namespace rtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698