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"
9 #include "nsThreadUtils.h"
12 struct CallbackThreadRegistrySingleton
{
13 CallbackThreadRegistrySingleton()
14 : mRegistry(MakeUnique
<CallbackThreadRegistry
>()) {
15 NS_DispatchToMainThread(
16 NS_NewRunnableFunction(__func__
, [registry
= &mRegistry
] {
17 const auto phase
= ShutdownPhase::XPCOMShutdownFinal
;
18 MOZ_DIAGNOSTIC_ASSERT(!PastShutdownPhase(phase
));
19 ClearOnShutdown(registry
, phase
);
23 UniquePtr
<CallbackThreadRegistry
> mRegistry
;
26 CallbackThreadRegistry::CallbackThreadRegistry()
27 : mThreadIds("CallbackThreadRegistry::mThreadIds") {}
30 CallbackThreadRegistry
* CallbackThreadRegistry::Get() {
31 static CallbackThreadRegistrySingleton sSingleton
;
32 return sSingleton
.mRegistry
.get();
35 static bool CanLeak() {
36 #ifdef NS_BUILD_REFCNT_LOGGING
37 static const bool logging
=
38 getenv("XPCOM_MEM_LEAK_LOG") || getenv("XPCOM_MEM_BLOAT_LOG") ||
39 getenv("XPCOM_MEM_REFCNT_LOG") || getenv("XPCOM_MEM_ALLOC_LOG") ||
40 getenv("XPCOM_MEM_COMPTR_LOG");
47 void CallbackThreadRegistry::Register(ProfilerThreadId aThreadId
,
49 if (!aThreadId
.IsSpecified()) {
50 // profiler_current_thread_id is unspecified on unsupported platforms.
56 "Not registering callback thread due to refcount logging; it may show "
57 "up as a leak of the TLS-backed nsThread wrapper if the thread "
58 "outlives xpcom shutdown.");
62 auto threadIds
= mThreadIds
.Lock();
63 for (uint32_t i
= 0; i
< threadIds
->Length(); i
++) {
64 if ((*threadIds
)[i
].mId
== aThreadId
) {
65 (*threadIds
)[i
].mUserCount
++;
72 threadIds
->AppendElement(tuc
);
73 PROFILER_REGISTER_THREAD(aName
);
76 void CallbackThreadRegistry::Unregister(ProfilerThreadId aThreadId
) {
77 if (!aThreadId
.IsSpecified()) {
78 // profiler_current_thread_id is unspedified on unsupported platforms.
86 auto threadIds
= mThreadIds
.Lock();
87 for (uint32_t i
= 0; i
< threadIds
->Length(); i
++) {
88 if ((*threadIds
)[i
].mId
== aThreadId
) {
89 MOZ_ASSERT((*threadIds
)[i
].mUserCount
> 0);
90 (*threadIds
)[i
].mUserCount
--;
92 if ((*threadIds
)[i
].mUserCount
== 0) {
93 PROFILER_UNREGISTER_THREAD();
94 threadIds
->RemoveElementAt(i
);
99 MOZ_ASSERT_UNREACHABLE("Current thread was not registered");
102 } // namespace mozilla