xref: /aosp_15_r20/external/cronet/base/allocator/dispatcher/dispatcher.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2022 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/allocator/dispatcher/dispatcher.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include "base/allocator/dispatcher/internal/dispatch_data.h"
8*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
9*6777b538SAndroid Build Coastguard Worker #include "base/dcheck_is_on.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/no_destructor.h"
11*6777b538SAndroid Build Coastguard Worker #include "partition_alloc/partition_alloc_buildflags.h"
12*6777b538SAndroid Build Coastguard Worker #include "partition_alloc/shim/allocator_shim.h"
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
15*6777b538SAndroid Build Coastguard Worker #include <atomic>
16*6777b538SAndroid Build Coastguard Worker #endif
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(USE_PARTITION_ALLOC)
19*6777b538SAndroid Build Coastguard Worker #include "partition_alloc/partition_alloc_hooks.h"
20*6777b538SAndroid Build Coastguard Worker #endif
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker namespace base::allocator::dispatcher {
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker // The private implementation of Dispatcher.
25*6777b538SAndroid Build Coastguard Worker struct Dispatcher::Impl {
Initializebase::allocator::dispatcher::Dispatcher::Impl26*6777b538SAndroid Build Coastguard Worker   void Initialize(const internal::DispatchData& dispatch_data) {
27*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
28*6777b538SAndroid Build Coastguard Worker     DCHECK(!is_initialized_check_flag_.test_and_set());
29*6777b538SAndroid Build Coastguard Worker #endif
30*6777b538SAndroid Build Coastguard Worker 
31*6777b538SAndroid Build Coastguard Worker     dispatch_data_ = dispatch_data;
32*6777b538SAndroid Build Coastguard Worker     ConnectToEmitters(dispatch_data_);
33*6777b538SAndroid Build Coastguard Worker   }
34*6777b538SAndroid Build Coastguard Worker 
Resetbase::allocator::dispatcher::Dispatcher::Impl35*6777b538SAndroid Build Coastguard Worker   void Reset() {
36*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
37*6777b538SAndroid Build Coastguard Worker     DCHECK([&]() {
38*6777b538SAndroid Build Coastguard Worker       auto const was_set = is_initialized_check_flag_.test_and_set();
39*6777b538SAndroid Build Coastguard Worker       is_initialized_check_flag_.clear();
40*6777b538SAndroid Build Coastguard Worker       return was_set;
41*6777b538SAndroid Build Coastguard Worker     }());
42*6777b538SAndroid Build Coastguard Worker #endif
43*6777b538SAndroid Build Coastguard Worker 
44*6777b538SAndroid Build Coastguard Worker     DisconnectFromEmitters(dispatch_data_);
45*6777b538SAndroid Build Coastguard Worker     dispatch_data_ = {};
46*6777b538SAndroid Build Coastguard Worker   }
47*6777b538SAndroid Build Coastguard Worker 
48*6777b538SAndroid Build Coastguard Worker  private:
49*6777b538SAndroid Build Coastguard Worker   // Connect the hooks to the memory subsystem. In some cases, most notably when
50*6777b538SAndroid Build Coastguard Worker   // we have no observers at all, the hooks will be invalid and must NOT be
51*6777b538SAndroid Build Coastguard Worker   // connected. This way we prevent notifications although no observers are
52*6777b538SAndroid Build Coastguard Worker   // present.
ConnectToEmittersbase::allocator::dispatcher::Dispatcher::Impl53*6777b538SAndroid Build Coastguard Worker   static void ConnectToEmitters(const internal::DispatchData& dispatch_data) {
54*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(USE_ALLOCATOR_SHIM)
55*6777b538SAndroid Build Coastguard Worker     if (auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch()) {
56*6777b538SAndroid Build Coastguard Worker       allocator_shim::InsertAllocatorDispatch(allocator_dispatch);
57*6777b538SAndroid Build Coastguard Worker     }
58*6777b538SAndroid Build Coastguard Worker #endif
59*6777b538SAndroid Build Coastguard Worker 
60*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(USE_PARTITION_ALLOC)
61*6777b538SAndroid Build Coastguard Worker     {
62*6777b538SAndroid Build Coastguard Worker       auto* const allocation_hook = dispatch_data.GetAllocationObserverHook();
63*6777b538SAndroid Build Coastguard Worker       auto* const free_hook = dispatch_data.GetFreeObserverHook();
64*6777b538SAndroid Build Coastguard Worker       if (allocation_hook && free_hook) {
65*6777b538SAndroid Build Coastguard Worker         partition_alloc::PartitionAllocHooks::SetObserverHooks(allocation_hook,
66*6777b538SAndroid Build Coastguard Worker                                                                free_hook);
67*6777b538SAndroid Build Coastguard Worker       }
68*6777b538SAndroid Build Coastguard Worker     }
69*6777b538SAndroid Build Coastguard Worker #endif
70*6777b538SAndroid Build Coastguard Worker   }
71*6777b538SAndroid Build Coastguard Worker 
DisconnectFromEmittersbase::allocator::dispatcher::Dispatcher::Impl72*6777b538SAndroid Build Coastguard Worker   static void DisconnectFromEmitters(internal::DispatchData& dispatch_data) {
73*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(USE_ALLOCATOR_SHIM)
74*6777b538SAndroid Build Coastguard Worker     if (auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch()) {
75*6777b538SAndroid Build Coastguard Worker       allocator_shim::RemoveAllocatorDispatchForTesting(
76*6777b538SAndroid Build Coastguard Worker           allocator_dispatch);  // IN-TEST
77*6777b538SAndroid Build Coastguard Worker     }
78*6777b538SAndroid Build Coastguard Worker #endif
79*6777b538SAndroid Build Coastguard Worker 
80*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(USE_PARTITION_ALLOC)
81*6777b538SAndroid Build Coastguard Worker     partition_alloc::PartitionAllocHooks::SetObserverHooks(nullptr, nullptr);
82*6777b538SAndroid Build Coastguard Worker #endif
83*6777b538SAndroid Build Coastguard Worker   }
84*6777b538SAndroid Build Coastguard Worker 
85*6777b538SAndroid Build Coastguard Worker   // Information on the hooks.
86*6777b538SAndroid Build Coastguard Worker   internal::DispatchData dispatch_data_;
87*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
88*6777b538SAndroid Build Coastguard Worker   // Indicator if the dispatcher has been initialized before.
89*6777b538SAndroid Build Coastguard Worker #if !defined(__cpp_lib_atomic_value_initialization) || \
90*6777b538SAndroid Build Coastguard Worker     __cpp_lib_atomic_value_initialization < 201911L
91*6777b538SAndroid Build Coastguard Worker   std::atomic_flag is_initialized_check_flag_ = ATOMIC_FLAG_INIT;
92*6777b538SAndroid Build Coastguard Worker #else
93*6777b538SAndroid Build Coastguard Worker   std::atomic_flag is_initialized_check_flag_;
94*6777b538SAndroid Build Coastguard Worker #endif
95*6777b538SAndroid Build Coastguard Worker #endif
96*6777b538SAndroid Build Coastguard Worker };
97*6777b538SAndroid Build Coastguard Worker 
Dispatcher()98*6777b538SAndroid Build Coastguard Worker Dispatcher::Dispatcher() : impl_(std::make_unique<Impl>()) {}
99*6777b538SAndroid Build Coastguard Worker 
100*6777b538SAndroid Build Coastguard Worker Dispatcher::~Dispatcher() = default;
101*6777b538SAndroid Build Coastguard Worker 
GetInstance()102*6777b538SAndroid Build Coastguard Worker Dispatcher& Dispatcher::GetInstance() {
103*6777b538SAndroid Build Coastguard Worker   static base::NoDestructor<Dispatcher> instance;
104*6777b538SAndroid Build Coastguard Worker   return *instance;
105*6777b538SAndroid Build Coastguard Worker }
106*6777b538SAndroid Build Coastguard Worker 
Initialize(const internal::DispatchData & dispatch_data)107*6777b538SAndroid Build Coastguard Worker void Dispatcher::Initialize(const internal::DispatchData& dispatch_data) {
108*6777b538SAndroid Build Coastguard Worker   impl_->Initialize(dispatch_data);
109*6777b538SAndroid Build Coastguard Worker }
110*6777b538SAndroid Build Coastguard Worker 
ResetForTesting()111*6777b538SAndroid Build Coastguard Worker void Dispatcher::ResetForTesting() {
112*6777b538SAndroid Build Coastguard Worker   impl_->Reset();
113*6777b538SAndroid Build Coastguard Worker }
114*6777b538SAndroid Build Coastguard Worker }  // namespace base::allocator::dispatcher
115