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)39ScopedRegisterThreadForDebugging::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()51ScopedRegisterThreadForDebugging::~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()58void 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