• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2019 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 "rtc_base/system/thread_registry.h"
12 
13 #include <map>
14 #include <utility>
15 
16 #include "absl/base/attributes.h"
17 #include "rtc_base/logging.h"
18 #include "rtc_base/platform_thread_types.h"
19 #include "rtc_base/synchronization/mutex.h"
20 #include "sdk/android/native_api/stacktrace/stacktrace.h"
21 
22 namespace webrtc {
23 
24 namespace {
25 
26 struct ThreadData {
27   const rtc::PlatformThreadId thread_id;
28   const rtc::Location location;
29 };
30 
31 // The map of registered threads, and the lock that protects it. We create the
32 // map on first use, and never destroy it.
33 ABSL_CONST_INIT GlobalMutex g_thread_registry_lock(absl::kConstInit);
34 ABSL_CONST_INIT std::map<const ScopedRegisterThreadForDebugging*, ThreadData>*
35     g_registered_threads = nullptr;
36 
37 }  // namespace
38 
ScopedRegisterThreadForDebugging(rtc::Location location)39 ScopedRegisterThreadForDebugging::ScopedRegisterThreadForDebugging(
40     rtc::Location location) {
41   GlobalMutexLock gls(&g_thread_registry_lock);
42   if (g_registered_threads == nullptr) {
43     g_registered_threads =
44         new std::map<const ScopedRegisterThreadForDebugging*, ThreadData>();
45   }
46   const auto result = g_registered_threads->insert(
47       std::make_pair(this, ThreadData{rtc::CurrentThreadId(), location}));
48   RTC_DCHECK(result.second);  // Insertion succeeded without collisions.
49 }
50 
~ScopedRegisterThreadForDebugging()51 ScopedRegisterThreadForDebugging::~ScopedRegisterThreadForDebugging() {
52   GlobalMutexLock gls(&g_thread_registry_lock);
53   RTC_DCHECK(g_registered_threads != nullptr);
54   const int num_erased = g_registered_threads->erase(this);
55   RTC_DCHECK_EQ(num_erased, 1);
56 }
57 
PrintStackTracesOfRegisteredThreads()58 void PrintStackTracesOfRegisteredThreads() {
59   GlobalMutexLock gls(&g_thread_registry_lock);
60   if (g_registered_threads == nullptr) {
61     return;
62   }
63   for (const auto& e : *g_registered_threads) {
64     const ThreadData& td = e.second;
65     RTC_LOG(LS_WARNING) << "Thread " << td.thread_id << " registered at "
66                         << td.location.ToString() << ":";
67     RTC_LOG(LS_WARNING) << StackTraceToString(GetStackTrace(td.thread_id));
68   }
69 }
70 
71 }  // namespace webrtc
72