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

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: 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
« no previous file with comments | « webrtc/base/criticalsection.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 namespace rtc { 15 namespace rtc {
16 16
17 CriticalSection::CriticalSection() { 17 CriticalSection::CriticalSection() {
18 #if defined(WEBRTC_WIN) 18 #if defined(WEBRTC_WIN)
19 InitializeCriticalSection(&crit_); 19 InitializeCriticalSection(&crit_);
20 #else 20 #else
21 #if defined(WEBRTC_MAC)
22 lock_queue_ = 0;
23 owning_thread_ = 0;
24 recursion_ = 0;
25 semaphore_ = dispatch_semaphore_create(0);
26 RTC_DCHECK(semaphore_);
torbjorng (webrtc) 2016/01/20 15:46:43 DCHECK? Shouldn't we barf in all builds if this ca
tommi 2016/01/21 15:04:21 I'll just remove this check. It's almost akin to
27 #else
21 pthread_mutexattr_t mutex_attribute; 28 pthread_mutexattr_t mutex_attribute;
22 pthread_mutexattr_init(&mutex_attribute); 29 pthread_mutexattr_init(&mutex_attribute);
23 pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE); 30 pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE);
24 pthread_mutex_init(&mutex_, &mutex_attribute); 31 pthread_mutex_init(&mutex_, &mutex_attribute);
25 pthread_mutexattr_destroy(&mutex_attribute); 32 pthread_mutexattr_destroy(&mutex_attribute);
33 #endif
26 CS_DEBUG_CODE(thread_ = 0); 34 CS_DEBUG_CODE(thread_ = 0);
27 CS_DEBUG_CODE(recursion_count_ = 0); 35 CS_DEBUG_CODE(recursion_count_ = 0);
28 #endif 36 #endif
29 } 37 }
30 38
31 CriticalSection::~CriticalSection() { 39 CriticalSection::~CriticalSection() {
32 #if defined(WEBRTC_WIN) 40 #if defined(WEBRTC_WIN)
33 DeleteCriticalSection(&crit_); 41 DeleteCriticalSection(&crit_);
34 #else 42 #else
43 #if defined(WEBRTC_MAC)
44 dispatch_release(semaphore_);
45 #else
35 pthread_mutex_destroy(&mutex_); 46 pthread_mutex_destroy(&mutex_);
36 #endif 47 #endif
48 #endif
37 } 49 }
38 50
39 void CriticalSection::Enter() EXCLUSIVE_LOCK_FUNCTION() { 51 void CriticalSection::Enter() EXCLUSIVE_LOCK_FUNCTION() {
40 #if defined(WEBRTC_WIN) 52 #if defined(WEBRTC_WIN)
41 EnterCriticalSection(&crit_); 53 EnterCriticalSection(&crit_);
42 #else 54 #else
55 #if defined(WEBRTC_MAC)
56 int spin = 2000;
57 do {
58 if (TryEnter())
torbjorng (webrtc) 2016/01/20 15:46:43 TryEnter seems to perform a CompareAndSwap uncondi
tommi 2016/01/21 15:04:21 I rewrote the loop to not call TryEnter() but inst
59 return;
60 sched_yield();
61 } while (--spin);
62
63 if (AtomicOps::Increment(&lock_queue_) > 0) {
64 // Owning thread cannot be the current thread since TryEnter() would
65 // have succeeded.
66 RTC_DCHECK(owning_thread_ != pthread_self());
67 // Wait for the lock to become available.
68 dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
69 RTC_DCHECK(owning_thread_ == 0);
70 RTC_DCHECK(!recursion_);
71 owning_thread_ = pthread_self();
72 }
73
74 RTC_DCHECK(owning_thread_ == pthread_self());
75 ++recursion_;
76
77 #else
43 pthread_mutex_lock(&mutex_); 78 pthread_mutex_lock(&mutex_);
79 #endif
80
44 #if CS_DEBUG_CHECKS 81 #if CS_DEBUG_CHECKS
45 if (!recursion_count_) { 82 if (!recursion_count_) {
46 RTC_DCHECK(!thread_); 83 RTC_DCHECK(!thread_);
47 thread_ = pthread_self(); 84 thread_ = pthread_self();
48 } else { 85 } else {
49 RTC_DCHECK(CurrentThreadIsOwner()); 86 RTC_DCHECK(CurrentThreadIsOwner());
50 } 87 }
51 ++recursion_count_; 88 ++recursion_count_;
52 #endif 89 #endif
53 #endif 90 #endif
54 } 91 }
55 92
56 bool CriticalSection::TryEnter() EXCLUSIVE_TRYLOCK_FUNCTION(true) { 93 bool CriticalSection::TryEnter() EXCLUSIVE_TRYLOCK_FUNCTION(true) {
57 #if defined(WEBRTC_WIN) 94 #if defined(WEBRTC_WIN)
58 return TryEnterCriticalSection(&crit_) != FALSE; 95 return TryEnterCriticalSection(&crit_) != FALSE;
59 #else 96 #else
97 #if defined(WEBRTC_MAC)
98 if (owning_thread_ != pthread_self()) {
99 if (AtomicOps::CompareAndSwap(&lock_queue_, 0, 1) != 0)
100 return false;
101 owning_thread_ = pthread_self();
102 RTC_DCHECK(!recursion_);
103 } else {
104 AtomicOps::Increment(&lock_queue_);
105 }
106 ++recursion_;
107 #else
60 if (pthread_mutex_trylock(&mutex_) != 0) 108 if (pthread_mutex_trylock(&mutex_) != 0)
61 return false; 109 return false;
110 #endif
62 #if CS_DEBUG_CHECKS 111 #if CS_DEBUG_CHECKS
63 if (!recursion_count_) { 112 if (!recursion_count_) {
64 RTC_DCHECK(!thread_); 113 RTC_DCHECK(!thread_);
65 thread_ = pthread_self(); 114 thread_ = pthread_self();
66 } else { 115 } else {
67 RTC_DCHECK(CurrentThreadIsOwner()); 116 RTC_DCHECK(CurrentThreadIsOwner());
68 } 117 }
69 ++recursion_count_; 118 ++recursion_count_;
70 #endif 119 #endif
71 return true; 120 return true;
72 #endif 121 #endif
73 } 122 }
74 void CriticalSection::Leave() UNLOCK_FUNCTION() { 123 void CriticalSection::Leave() UNLOCK_FUNCTION() {
75 RTC_DCHECK(CurrentThreadIsOwner()); 124 RTC_DCHECK(CurrentThreadIsOwner());
76 #if defined(WEBRTC_WIN) 125 #if defined(WEBRTC_WIN)
77 LeaveCriticalSection(&crit_); 126 LeaveCriticalSection(&crit_);
78 #else 127 #else
79 #if CS_DEBUG_CHECKS 128 #if CS_DEBUG_CHECKS
80 --recursion_count_; 129 --recursion_count_;
81 RTC_DCHECK(recursion_count_ >= 0); 130 RTC_DCHECK(recursion_count_ >= 0);
82 if (!recursion_count_) 131 if (!recursion_count_)
83 thread_ = 0; 132 thread_ = 0;
84 #endif 133 #endif
134 #if defined(WEBRTC_MAC)
135 RTC_DCHECK_EQ(owning_thread_, pthread_self());
136 RTC_DCHECK_GE(recursion_, 0);
137 --recursion_;
138 if (!recursion_)
139 owning_thread_ = 0;
140
141 if (AtomicOps::Decrement(&lock_queue_) > 0 && !recursion_)
142 dispatch_semaphore_signal(semaphore_);
143 #else
85 pthread_mutex_unlock(&mutex_); 144 pthread_mutex_unlock(&mutex_);
86 #endif 145 #endif
146 #endif
87 } 147 }
88 148
89 bool CriticalSection::CurrentThreadIsOwner() const { 149 bool CriticalSection::CurrentThreadIsOwner() const {
90 #if defined(WEBRTC_WIN) 150 #if defined(WEBRTC_WIN)
91 // OwningThread has type HANDLE but actually contains the Thread ID: 151 // 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 152 // 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 153 // Converting through size_t avoids the VS 2015 warning C4312: conversion from
94 // 'type1' to 'type2' of greater size 154 // 'type1' to 'type2' of greater size
95 return crit_.OwningThread == 155 return crit_.OwningThread ==
96 reinterpret_cast<HANDLE>(static_cast<size_t>(GetCurrentThreadId())); 156 reinterpret_cast<HANDLE>(static_cast<size_t>(GetCurrentThreadId()));
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 if (locked_) 188 if (locked_)
129 cs_->Leave(); 189 cs_->Leave();
130 } 190 }
131 191
132 bool TryCritScope::locked() const { 192 bool TryCritScope::locked() const {
133 CS_DEBUG_CODE(lock_was_called_ = true); 193 CS_DEBUG_CODE(lock_was_called_ = true);
134 return locked_; 194 return locked_;
135 } 195 }
136 196
137 void GlobalLockPod::Lock() { 197 void GlobalLockPod::Lock() {
138 #if !defined(WEBRTC_WIN) 198 #if !defined(WEBRTC_WIN) && !defined(WEBRTC_MAC)
139 const struct timespec ts_null = {0}; 199 const struct timespec ts_null = {0};
140 #endif 200 #endif
141 201
142 while (AtomicOps::CompareAndSwap(&lock_acquired, 0, 1)) { 202 while (AtomicOps::CompareAndSwap(&lock_acquired, 0, 1)) {
143 #if defined(WEBRTC_WIN) 203 #if defined(WEBRTC_WIN)
144 ::Sleep(0); 204 ::Sleep(0);
205 #elif defined(WEBRTC_MAC)
206 sched_yield();
145 #else 207 #else
146 nanosleep(&ts_null, nullptr); 208 nanosleep(&ts_null, nullptr);
147 #endif 209 #endif
148 } 210 }
149 } 211 }
150 212
151 void GlobalLockPod::Unlock() { 213 void GlobalLockPod::Unlock() {
152 int old_value = AtomicOps::CompareAndSwap(&lock_acquired, 1, 0); 214 int old_value = AtomicOps::CompareAndSwap(&lock_acquired, 1, 0);
153 RTC_DCHECK_EQ(1, old_value) << "Unlock called without calling Lock first"; 215 RTC_DCHECK_EQ(1, old_value) << "Unlock called without calling Lock first";
154 } 216 }
155 217
156 GlobalLock::GlobalLock() { 218 GlobalLock::GlobalLock() {
157 lock_acquired = 0; 219 lock_acquired = 0;
158 } 220 }
159 221
160 GlobalLockScope::GlobalLockScope(GlobalLockPod* lock) 222 GlobalLockScope::GlobalLockScope(GlobalLockPod* lock)
161 : lock_(lock) { 223 : lock_(lock) {
162 lock_->Lock(); 224 lock_->Lock();
163 } 225 }
164 226
165 GlobalLockScope::~GlobalLockScope() { 227 GlobalLockScope::~GlobalLockScope() {
166 lock_->Unlock(); 228 lock_->Unlock();
167 } 229 }
168 230
169 } // namespace rtc 231 } // namespace rtc
OLDNEW
« no previous file with comments | « webrtc/base/criticalsection.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698