xref: /aosp_15_r20/external/cronet/base/allocator/dispatcher/reentry_guard.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/allocator/dispatcher/reentry_guard.h"
6 
7 #include "base/check.h"
8 #include "base/compiler_specific.h"
9 #include "base/debug/crash_logging.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "build/build_config.h"
12 
13 #if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_ANDROID)
14 #include <pthread.h>
15 #endif
16 
17 namespace base::allocator::dispatcher {
18 
19 #if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_ANDROID)
20 // pthread_key_t has different signedness on Mac and Android. Store the null
21 // value in a strongly-typed constant to avoid "comparison of integers of
22 // different signs" warnings when comparing with 0.
23 constexpr pthread_key_t kNullKey = 0;
24 
25 pthread_key_t ReentryGuard::entered_key_ = kNullKey;
26 
InitTLSSlot()27 void ReentryGuard::InitTLSSlot() {
28   if (entered_key_ == kNullKey) {
29     int error = pthread_key_create(&entered_key_, nullptr);
30     CHECK(!error);
31     // Touch the TLS slot immediately to force any allocations.
32     // TODO(https://crbug.com/1411454): Use this technique to avoid allocations
33     // in PoissonAllocationSampler::ScopedMuteThreadSamples, which will make
34     // ReentryGuard redundant.
35     pthread_setspecific(entered_key_, nullptr);
36   }
37 
38   DCHECK_NE(entered_key_, kNullKey);
39 }
40 
41 #else
42 
43 void ReentryGuard::InitTLSSlot() {}
44 
45 #endif
46 
RecordTLSSlotToCrashKey()47 void ReentryGuard::RecordTLSSlotToCrashKey() {
48   // Record the key in crash dumps to detect when it's higher than 32
49   // (PTHREAD_KEY_2NDLEVEL_SIZE).
50   // TODO(crbug.com/1411454): Remove this after diagnosing reentry crashes.
51   static auto* const crash_key = base::debug::AllocateCrashKeyString(
52       "reentry_guard_tls_slot", base::debug::CrashKeySize::Size32);
53 
54 #if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_ANDROID)
55   base::debug::SetCrashKeyString(crash_key, base::NumberToString(entered_key_));
56 #else
57   base::debug::SetCrashKeyString(crash_key, "unused");
58 #endif
59 }
60 
61 }  // namespace base::allocator::dispatcher
62