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