xref: /aosp_15_r20/external/cronet/base/memory/shared_memory_tracker.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2017 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/memory/shared_memory_tracker.h"
6 
7 #include "base/check.h"
8 #include "base/notreached.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/trace_event/base_tracing.h"
11 #include "base/tracing_buildflags.h"
12 
13 #if BUILDFLAG(ENABLE_BASE_TRACING)
14 #include <optional>
15 
16 #include "base/trace_event/memory_dump_manager.h"  // no-presubmit-check
17 #include "base/trace_event/process_memory_dump.h"  // no-presubmit-check
18 #endif  // BUILDFLAG(ENABLE_BASE_TRACING)
19 
20 namespace base {
21 
22 const char SharedMemoryTracker::kDumpRootName[] = "shared_memory";
23 
24 // static
GetInstance()25 SharedMemoryTracker* SharedMemoryTracker::GetInstance() {
26   static SharedMemoryTracker* instance = new SharedMemoryTracker;
27   return instance;
28 }
29 
30 // static
GetDumpNameForTracing(const UnguessableToken & id)31 std::string SharedMemoryTracker::GetDumpNameForTracing(
32     const UnguessableToken& id) {
33   DCHECK(!id.is_empty());
34   return std::string(kDumpRootName) + "/" + id.ToString();
35 }
36 
37 // static
38 trace_event::MemoryAllocatorDumpGuid
GetGlobalDumpIdForTracing(const UnguessableToken & id)39 SharedMemoryTracker::GetGlobalDumpIdForTracing(const UnguessableToken& id) {
40   std::string dump_name = GetDumpNameForTracing(id);
41   return trace_event::MemoryAllocatorDumpGuid(dump_name);
42 }
43 
44 const trace_event::MemoryAllocatorDump*
GetOrCreateSharedMemoryDump(const SharedMemoryMapping & shared_memory,trace_event::ProcessMemoryDump * pmd)45 SharedMemoryTracker::GetOrCreateSharedMemoryDump(
46     const SharedMemoryMapping& shared_memory,
47     trace_event::ProcessMemoryDump* pmd) {
48   return GetOrCreateSharedMemoryDumpInternal(shared_memory.raw_memory_ptr(),
49                                              shared_memory.mapped_size(),
50                                              shared_memory.guid(), pmd);
51 }
52 
IncrementMemoryUsage(const SharedMemoryMapping & mapping)53 void SharedMemoryTracker::IncrementMemoryUsage(
54     const SharedMemoryMapping& mapping) {
55   AutoLock hold(usages_lock_);
56   DCHECK(usages_.find(mapping.raw_memory_ptr()) == usages_.end());
57   usages_.emplace(mapping.raw_memory_ptr(),
58                   UsageInfo(mapping.mapped_size(), mapping.guid()));
59 }
60 
DecrementMemoryUsage(const SharedMemoryMapping & mapping)61 void SharedMemoryTracker::DecrementMemoryUsage(
62     const SharedMemoryMapping& mapping) {
63   AutoLock hold(usages_lock_);
64   const auto it = usages_.find(mapping.raw_memory_ptr());
65   // TODO(pbos): When removing this NotFatalUntil, use erase(it) below. We can't
66   // do that now because if this CHECK is actually failing there'd be a memory
67   // bug.
68   CHECK(it != usages_.end(), base::NotFatalUntil::M125);
69   usages_.erase(mapping.raw_memory_ptr());
70 }
71 
SharedMemoryTracker()72 SharedMemoryTracker::SharedMemoryTracker() {
73 #if BUILDFLAG(ENABLE_BASE_TRACING)
74   trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
75       this, "SharedMemoryTracker", nullptr);
76 #endif  // BUILDFLAG(ENABLE_BASE_TRACING)
77 }
78 
79 SharedMemoryTracker::~SharedMemoryTracker() = default;
80 
OnMemoryDump(const trace_event::MemoryDumpArgs & args,trace_event::ProcessMemoryDump * pmd)81 bool SharedMemoryTracker::OnMemoryDump(const trace_event::MemoryDumpArgs& args,
82                                        trace_event::ProcessMemoryDump* pmd) {
83   AutoLock hold(usages_lock_);
84   for (const auto& usage : usages_) {
85     const trace_event::MemoryAllocatorDump* dump =
86         GetOrCreateSharedMemoryDumpInternal(
87             usage.first, usage.second.mapped_size, usage.second.mapped_id, pmd);
88     DCHECK(dump);
89   }
90   return true;
91 }
92 
93 // static
94 const trace_event::MemoryAllocatorDump*
GetOrCreateSharedMemoryDumpInternal(void * mapped_memory,size_t mapped_size,const UnguessableToken & mapped_id,trace_event::ProcessMemoryDump * pmd)95 SharedMemoryTracker::GetOrCreateSharedMemoryDumpInternal(
96     void* mapped_memory,
97     size_t mapped_size,
98     const UnguessableToken& mapped_id,
99     trace_event::ProcessMemoryDump* pmd) {
100 #if BUILDFLAG(ENABLE_BASE_TRACING)
101   const std::string dump_name = GetDumpNameForTracing(mapped_id);
102   trace_event::MemoryAllocatorDump* local_dump =
103       pmd->GetAllocatorDump(dump_name);
104   if (local_dump)
105     return local_dump;
106 
107   size_t virtual_size = mapped_size;
108   // If resident size is not available, a virtual size is used as fallback.
109   size_t size = virtual_size;
110 #if defined(COUNT_RESIDENT_BYTES_SUPPORTED)
111   std::optional<size_t> resident_size =
112       trace_event::ProcessMemoryDump::CountResidentBytesInSharedMemory(
113           mapped_memory, mapped_size);
114   if (resident_size.has_value())
115     size = resident_size.value();
116 #endif
117 
118   local_dump = pmd->CreateAllocatorDump(dump_name);
119   local_dump->AddScalar(trace_event::MemoryAllocatorDump::kNameSize,
120                         trace_event::MemoryAllocatorDump::kUnitsBytes, size);
121   local_dump->AddScalar("virtual_size",
122                         trace_event::MemoryAllocatorDump::kUnitsBytes,
123                         virtual_size);
124   auto global_dump_guid = GetGlobalDumpIdForTracing(mapped_id);
125   trace_event::MemoryAllocatorDump* global_dump =
126       pmd->CreateSharedGlobalAllocatorDump(global_dump_guid);
127   global_dump->AddScalar(trace_event::MemoryAllocatorDump::kNameSize,
128                          trace_event::MemoryAllocatorDump::kUnitsBytes, size);
129 
130   // The edges will be overriden by the clients with correct importance.
131   pmd->AddOverridableOwnershipEdge(local_dump->guid(), global_dump->guid(),
132                                    0 /* importance */);
133   return local_dump;
134 #else   // BUILDFLAG(ENABLE_BASE_TRACING)
135   NOTREACHED();
136   return nullptr;
137 #endif  // BUILDFLAG(ENABLE_BASE_TRACING)
138 }
139 
140 }  // namespace
141