1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "CallbackThreadRegistry.h"
8 #include "mozilla/ClearOnShutdown.h"
11 struct CallbackThreadRegistrySingleton
{
12 CallbackThreadRegistrySingleton()
13 : mRegistry(MakeUnique
<CallbackThreadRegistry
>()) {
14 NS_DispatchToMainThread(
15 NS_NewRunnableFunction(__func__
, [registry
= &mRegistry
] {
16 const auto phase
= ShutdownPhase::XPCOMShutdownFinal
;
17 MOZ_DIAGNOSTIC_ASSERT(!PastShutdownPhase(phase
));
18 ClearOnShutdown(registry
, phase
);
22 UniquePtr
<CallbackThreadRegistry
> mRegistry
;
25 CallbackThreadRegistry::CallbackThreadRegistry()
26 : mThreadIds("CallbackThreadRegistry::mThreadIds") {}
29 CallbackThreadRegistry
* CallbackThreadRegistry::Get() {
30 static CallbackThreadRegistrySingleton sSingleton
;
31 return sSingleton
.mRegistry
.get();
34 static bool CanLeak() {
35 #ifdef NS_BUILD_REFCNT_LOGGING
36 static const bool logging
=
37 getenv("XPCOM_MEM_LEAK_LOG") || getenv("XPCOM_MEM_BLOAT_LOG") ||
38 getenv("XPCOM_MEM_REFCNT_LOG") || getenv("XPCOM_MEM_ALLOC_LOG") ||
39 getenv("XPCOM_MEM_COMPTR_LOG");
46 void CallbackThreadRegistry::Register(ProfilerThreadId aThreadId
,
48 if (!aThreadId
.IsSpecified()) {
49 // profiler_current_thread_id is unspecified on unsupported platforms.
55 "Not registering callback thread due to refcount logging; it may show "
56 "up as a leak of the TLS-backed nsThread wrapper if the thread "
57 "outlives xpcom shutdown.");
61 auto threadIds
= mThreadIds
.Lock();
62 for (uint32_t i
= 0; i
< threadIds
->Length(); i
++) {
63 if ((*threadIds
)[i
].mId
== aThreadId
) {
64 (*threadIds
)[i
].mUserCount
++;
71 threadIds
->AppendElement(tuc
);
72 PROFILER_REGISTER_THREAD(aName
);
75 void CallbackThreadRegistry::Unregister(ProfilerThreadId aThreadId
) {
76 if (!aThreadId
.IsSpecified()) {
77 // profiler_current_thread_id is unspedified on unsupported platforms.
85 auto threadIds
= mThreadIds
.Lock();
86 for (uint32_t i
= 0; i
< threadIds
->Length(); i
++) {
87 if ((*threadIds
)[i
].mId
== aThreadId
) {
88 MOZ_ASSERT((*threadIds
)[i
].mUserCount
> 0);
89 (*threadIds
)[i
].mUserCount
--;
91 if ((*threadIds
)[i
].mUserCount
== 0) {
92 PROFILER_UNREGISTER_THREAD();
93 threadIds
->RemoveElementAt(i
);
98 MOZ_ASSERT_UNREACHABLE("Current thread was not registered");
101 } // namespace mozilla