blob: 86605446c71515bd7954c52e237d0b785bd9f959 [file] [log] [blame]
Karl Wibergab036382019-03-12 18:01:51 +01001/*
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/critical_section.h"
18#include "rtc_base/logging.h"
19#include "rtc_base/platform_thread_types.h"
20#include "sdk/android/native_api/stacktrace/stacktrace.h"
21
22namespace webrtc {
23
24namespace {
25
26struct 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.
Danil Chapovalov5740f3e2019-10-10 11:12:15 +020033ABSL_CONST_INIT rtc::GlobalLock g_thread_registry_lock;
Karl Wibergab036382019-03-12 18:01:51 +010034ABSL_CONST_INIT std::map<const ScopedRegisterThreadForDebugging*, ThreadData>*
35 g_registered_threads = nullptr;
36
37} // namespace
38
39ScopedRegisterThreadForDebugging::ScopedRegisterThreadForDebugging(
40 rtc::Location location) {
41 rtc::GlobalLockScope 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
51ScopedRegisterThreadForDebugging::~ScopedRegisterThreadForDebugging() {
52 rtc::GlobalLockScope 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
58void PrintStackTracesOfRegisteredThreads() {
59 rtc::GlobalLockScope 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