blob: 2c6b100a7dfdfa4c92e179f54f58ba2eea54e40c [file] [log] [blame]
Jiayang Liubef8d2d2015-03-26 14:38:46 -07001/*
2 * Copyright 2015 The WebRTC Project Authors. All rights reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/base/criticalsection.h"
12
13#include "webrtc/base/checks.h"
Jiayang Liubef8d2d2015-03-26 14:38:46 -070014
15namespace rtc {
16
Tommi494f2092015-04-27 17:39:23 +020017CriticalSection::CriticalSection() {
18#if defined(WEBRTC_WIN)
19 InitializeCriticalSection(&crit_);
20#else
21 pthread_mutexattr_t mutex_attribute;
22 pthread_mutexattr_init(&mutex_attribute);
23 pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE);
24 pthread_mutex_init(&mutex_, &mutex_attribute);
25 pthread_mutexattr_destroy(&mutex_attribute);
26 CS_DEBUG_CODE(thread_ = 0);
27 CS_DEBUG_CODE(recursion_count_ = 0);
28#endif
29}
30
31CriticalSection::~CriticalSection() {
32#if defined(WEBRTC_WIN)
33 DeleteCriticalSection(&crit_);
34#else
35 pthread_mutex_destroy(&mutex_);
36#endif
37}
38
Peter Boströmaf9e6632016-01-21 16:56:52 +010039void CriticalSection::Enter() const EXCLUSIVE_LOCK_FUNCTION() {
Tommi494f2092015-04-27 17:39:23 +020040#if defined(WEBRTC_WIN)
41 EnterCriticalSection(&crit_);
42#else
43 pthread_mutex_lock(&mutex_);
44#if CS_DEBUG_CHECKS
45 if (!recursion_count_) {
henrikg91d6ede2015-09-17 00:24:34 -070046 RTC_DCHECK(!thread_);
Tommi494f2092015-04-27 17:39:23 +020047 thread_ = pthread_self();
48 } else {
henrikg91d6ede2015-09-17 00:24:34 -070049 RTC_DCHECK(CurrentThreadIsOwner());
Tommi494f2092015-04-27 17:39:23 +020050 }
51 ++recursion_count_;
52#endif
53#endif
54}
55
Peter Boströmaf9e6632016-01-21 16:56:52 +010056bool CriticalSection::TryEnter() const EXCLUSIVE_TRYLOCK_FUNCTION(true) {
Tommi494f2092015-04-27 17:39:23 +020057#if defined(WEBRTC_WIN)
58 return TryEnterCriticalSection(&crit_) != FALSE;
59#else
60 if (pthread_mutex_trylock(&mutex_) != 0)
61 return false;
62#if CS_DEBUG_CHECKS
63 if (!recursion_count_) {
henrikg91d6ede2015-09-17 00:24:34 -070064 RTC_DCHECK(!thread_);
Tommi494f2092015-04-27 17:39:23 +020065 thread_ = pthread_self();
66 } else {
henrikg91d6ede2015-09-17 00:24:34 -070067 RTC_DCHECK(CurrentThreadIsOwner());
Tommi494f2092015-04-27 17:39:23 +020068 }
69 ++recursion_count_;
70#endif
71 return true;
72#endif
73}
Peter Boströmaf9e6632016-01-21 16:56:52 +010074void CriticalSection::Leave() const UNLOCK_FUNCTION() {
henrikg91d6ede2015-09-17 00:24:34 -070075 RTC_DCHECK(CurrentThreadIsOwner());
Tommi494f2092015-04-27 17:39:23 +020076#if defined(WEBRTC_WIN)
77 LeaveCriticalSection(&crit_);
78#else
79#if CS_DEBUG_CHECKS
80 --recursion_count_;
henrikg91d6ede2015-09-17 00:24:34 -070081 RTC_DCHECK(recursion_count_ >= 0);
Tommi494f2092015-04-27 17:39:23 +020082 if (!recursion_count_)
83 thread_ = 0;
84#endif
85 pthread_mutex_unlock(&mutex_);
86#endif
87}
88
89bool CriticalSection::CurrentThreadIsOwner() const {
90#if defined(WEBRTC_WIN)
brucedawsona10492f2015-10-06 13:34:30 -070091 // 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
93 // Converting through size_t avoids the VS 2015 warning C4312: conversion from
94 // 'type1' to 'type2' of greater size
95 return crit_.OwningThread ==
96 reinterpret_cast<HANDLE>(static_cast<size_t>(GetCurrentThreadId()));
Tommi494f2092015-04-27 17:39:23 +020097#else
98#if CS_DEBUG_CHECKS
99 return pthread_equal(thread_, pthread_self());
100#else
101 return true;
102#endif // CS_DEBUG_CHECKS
103#endif
104}
105
106bool CriticalSection::IsLocked() const {
107#if defined(WEBRTC_WIN)
108 return crit_.LockCount != -1;
109#else
110#if CS_DEBUG_CHECKS
111 return thread_ != 0;
112#else
113 return true;
114#endif
115#endif
116}
117
Peter Boströmaf9e6632016-01-21 16:56:52 +0100118CritScope::CritScope(const CriticalSection* cs) : cs_(cs) { cs_->Enter(); }
Tommi494f2092015-04-27 17:39:23 +0200119CritScope::~CritScope() { cs_->Leave(); }
120
Peter Boströmaf9e6632016-01-21 16:56:52 +0100121TryCritScope::TryCritScope(const CriticalSection* cs)
Tommi494f2092015-04-27 17:39:23 +0200122 : cs_(cs), locked_(cs->TryEnter()) {
123 CS_DEBUG_CODE(lock_was_called_ = false);
124}
125
126TryCritScope::~TryCritScope() {
henrikg91d6ede2015-09-17 00:24:34 -0700127 CS_DEBUG_CODE(RTC_DCHECK(lock_was_called_));
Tommi494f2092015-04-27 17:39:23 +0200128 if (locked_)
129 cs_->Leave();
130}
131
132bool TryCritScope::locked() const {
133 CS_DEBUG_CODE(lock_was_called_ = true);
134 return locked_;
135}
136
Jiayang Liubef8d2d2015-03-26 14:38:46 -0700137void GlobalLockPod::Lock() {
Tommi494f2092015-04-27 17:39:23 +0200138#if !defined(WEBRTC_WIN)
139 const struct timespec ts_null = {0};
140#endif
141
pbos46ad5422015-12-07 14:29:14 -0800142 while (AtomicOps::CompareAndSwap(&lock_acquired, 0, 1)) {
Tommi494f2092015-04-27 17:39:23 +0200143#if defined(WEBRTC_WIN)
144 ::Sleep(0);
145#else
146 nanosleep(&ts_null, nullptr);
147#endif
Jiayang Liubef8d2d2015-03-26 14:38:46 -0700148 }
149}
150
151void GlobalLockPod::Unlock() {
pbos46ad5422015-12-07 14:29:14 -0800152 int old_value = AtomicOps::CompareAndSwap(&lock_acquired, 1, 0);
henrikg91d6ede2015-09-17 00:24:34 -0700153 RTC_DCHECK_EQ(1, old_value) << "Unlock called without calling Lock first";
Jiayang Liubef8d2d2015-03-26 14:38:46 -0700154}
155
pbos46ad5422015-12-07 14:29:14 -0800156GlobalLock::GlobalLock() {
157 lock_acquired = 0;
158}
pbos3c12f4d2015-11-17 03:21:02 -0800159
pbos46ad5422015-12-07 14:29:14 -0800160GlobalLockScope::GlobalLockScope(GlobalLockPod* lock)
161 : lock_(lock) {
Joachim Bauchfec2c6d2015-05-27 23:41:43 +0200162 lock_->Lock();
163}
164
165GlobalLockScope::~GlobalLockScope() {
166 lock_->Unlock();
167}
168
Jiayang Liubef8d2d2015-03-26 14:38:46 -0700169} // namespace rtc