xref: /aosp_15_r20/external/webrtc/rtc_base/race_checker.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/race_checker.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker namespace rtc {
14*d9f75844SAndroid Build Coastguard Worker 
RaceChecker()15*d9f75844SAndroid Build Coastguard Worker RaceChecker::RaceChecker() {}
16*d9f75844SAndroid Build Coastguard Worker 
17*d9f75844SAndroid Build Coastguard Worker // Note that the implementation here is in itself racy, but we pretend it does
18*d9f75844SAndroid Build Coastguard Worker // not matter because we want this useful in release builds without having to
19*d9f75844SAndroid Build Coastguard Worker // pay the cost of using atomics. A race hitting the race checker is likely to
20*d9f75844SAndroid Build Coastguard Worker // cause access_count_ to diverge from zero and therefore cause the ThreadRef
21*d9f75844SAndroid Build Coastguard Worker // comparison to fail, signaling a race, although it may not be in the exact
22*d9f75844SAndroid Build Coastguard Worker // spot where a race *first* appeared in the code we're trying to protect. There
23*d9f75844SAndroid Build Coastguard Worker // is also a chance that an actual race is missed, however the probability of
24*d9f75844SAndroid Build Coastguard Worker // that has been considered small enough to be an acceptable trade off.
Acquire() const25*d9f75844SAndroid Build Coastguard Worker bool RaceChecker::Acquire() const {
26*d9f75844SAndroid Build Coastguard Worker   const PlatformThreadRef current_thread = CurrentThreadRef();
27*d9f75844SAndroid Build Coastguard Worker   // Set new accessing thread if this is a new use.
28*d9f75844SAndroid Build Coastguard Worker   const int current_access_count = access_count_;
29*d9f75844SAndroid Build Coastguard Worker   access_count_ = access_count_ + 1;
30*d9f75844SAndroid Build Coastguard Worker   if (current_access_count == 0)
31*d9f75844SAndroid Build Coastguard Worker     accessing_thread_ = current_thread;
32*d9f75844SAndroid Build Coastguard Worker   // If this is being used concurrently this check will fail for the second
33*d9f75844SAndroid Build Coastguard Worker   // thread entering since it won't set the thread. Recursive use of checked
34*d9f75844SAndroid Build Coastguard Worker   // methods are OK since the accessing thread remains the same.
35*d9f75844SAndroid Build Coastguard Worker   const PlatformThreadRef accessing_thread = accessing_thread_;
36*d9f75844SAndroid Build Coastguard Worker   return IsThreadRefEqual(accessing_thread, current_thread);
37*d9f75844SAndroid Build Coastguard Worker }
38*d9f75844SAndroid Build Coastguard Worker 
Release() const39*d9f75844SAndroid Build Coastguard Worker void RaceChecker::Release() const {
40*d9f75844SAndroid Build Coastguard Worker   access_count_ = access_count_ - 1;
41*d9f75844SAndroid Build Coastguard Worker }
42*d9f75844SAndroid Build Coastguard Worker 
43*d9f75844SAndroid Build Coastguard Worker namespace internal {
RaceCheckerScope(const RaceChecker * race_checker)44*d9f75844SAndroid Build Coastguard Worker RaceCheckerScope::RaceCheckerScope(const RaceChecker* race_checker)
45*d9f75844SAndroid Build Coastguard Worker     : race_checker_(race_checker), race_check_ok_(race_checker->Acquire()) {}
46*d9f75844SAndroid Build Coastguard Worker 
RaceDetected() const47*d9f75844SAndroid Build Coastguard Worker bool RaceCheckerScope::RaceDetected() const {
48*d9f75844SAndroid Build Coastguard Worker   return !race_check_ok_;
49*d9f75844SAndroid Build Coastguard Worker }
50*d9f75844SAndroid Build Coastguard Worker 
~RaceCheckerScope()51*d9f75844SAndroid Build Coastguard Worker RaceCheckerScope::~RaceCheckerScope() {
52*d9f75844SAndroid Build Coastguard Worker   race_checker_->Release();
53*d9f75844SAndroid Build Coastguard Worker }
54*d9f75844SAndroid Build Coastguard Worker 
55*d9f75844SAndroid Build Coastguard Worker }  // namespace internal
56*d9f75844SAndroid Build Coastguard Worker }  // namespace rtc
57