OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/debug/activity_analyzer.h" | 5 #include "base/debug/activity_analyzer.h" |
6 | 6 |
7 #include "base/files/file.h" | 7 #include "base/files/file.h" |
8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
9 #include "base/files/memory_mapped_file.h" | 9 #include "base/files/memory_mapped_file.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
12 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
14 | 14 |
15 namespace base { | 15 namespace base { |
16 namespace debug { | 16 namespace debug { |
17 | 17 |
| 18 ThreadActivityAnalyzer::Snapshot::Snapshot() {} |
| 19 ThreadActivityAnalyzer::Snapshot::~Snapshot() {} |
| 20 |
18 ThreadActivityAnalyzer::ThreadActivityAnalyzer( | 21 ThreadActivityAnalyzer::ThreadActivityAnalyzer( |
19 const ThreadActivityTracker& tracker) | 22 const ThreadActivityTracker& tracker) |
20 : activity_snapshot_valid_(tracker.Snapshot(&activity_snapshot_)) {} | 23 : activity_snapshot_valid_(tracker.CreateSnapshot(&activity_snapshot_)) {} |
21 | 24 |
22 ThreadActivityAnalyzer::ThreadActivityAnalyzer(void* base, size_t size) | 25 ThreadActivityAnalyzer::ThreadActivityAnalyzer(void* base, size_t size) |
23 : ThreadActivityAnalyzer(ThreadActivityTracker(base, size)) {} | 26 : ThreadActivityAnalyzer(ThreadActivityTracker(base, size)) {} |
24 | 27 |
25 ThreadActivityAnalyzer::ThreadActivityAnalyzer( | 28 ThreadActivityAnalyzer::ThreadActivityAnalyzer( |
26 PersistentMemoryAllocator* allocator, | 29 PersistentMemoryAllocator* allocator, |
27 PersistentMemoryAllocator::Reference reference) | 30 PersistentMemoryAllocator::Reference reference) |
28 : ThreadActivityAnalyzer(allocator->GetAsArray<char>( | 31 : ThreadActivityAnalyzer(allocator->GetAsArray<char>( |
29 reference, | 32 reference, |
30 GlobalActivityTracker::kTypeIdActivityTracker, | 33 GlobalActivityTracker::kTypeIdActivityTracker, |
31 1), | 34 1), |
32 allocator->GetAllocSize(reference)) {} | 35 allocator->GetAllocSize(reference)) {} |
33 | 36 |
34 ThreadActivityAnalyzer::~ThreadActivityAnalyzer() {} | 37 ThreadActivityAnalyzer::~ThreadActivityAnalyzer() {} |
35 | 38 |
| 39 void ThreadActivityAnalyzer::AddGlobalInformation( |
| 40 GlobalActivityAnalyzer* global) { |
| 41 if (!IsValid()) |
| 42 return; |
| 43 |
| 44 // User-data is held at the global scope even though it's referenced at the |
| 45 // thread scope. |
| 46 activity_snapshot_.user_data_stack.clear(); |
| 47 for (auto& activity : activity_snapshot_.activity_stack) { |
| 48 // The global GetUserDataSnapshot will return an empty snapshot if the ref |
| 49 // or id is not valid. |
| 50 activity_snapshot_.user_data_stack.push_back(global->GetUserDataSnapshot( |
| 51 activity.user_data_ref, activity.user_data_id)); |
| 52 } |
| 53 } |
| 54 |
36 GlobalActivityAnalyzer::GlobalActivityAnalyzer( | 55 GlobalActivityAnalyzer::GlobalActivityAnalyzer( |
37 std::unique_ptr<PersistentMemoryAllocator> allocator) | 56 std::unique_ptr<PersistentMemoryAllocator> allocator) |
38 : allocator_(std::move(allocator)), allocator_iterator_(allocator_.get()) {} | 57 : allocator_(std::move(allocator)), allocator_iterator_(allocator_.get()) {} |
39 | 58 |
40 GlobalActivityAnalyzer::~GlobalActivityAnalyzer() {} | 59 GlobalActivityAnalyzer::~GlobalActivityAnalyzer() {} |
41 | 60 |
42 #if !defined(OS_NACL) | 61 #if !defined(OS_NACL) |
43 // static | 62 // static |
44 std::unique_ptr<GlobalActivityAnalyzer> GlobalActivityAnalyzer::CreateWithFile( | 63 std::unique_ptr<GlobalActivityAnalyzer> GlobalActivityAnalyzer::CreateWithFile( |
45 const FilePath& file_path) { | 64 const FilePath& file_path) { |
(...skipping 30 matching lines...) Expand all Loading... |
76 } | 95 } |
77 | 96 |
78 ThreadActivityAnalyzer* GlobalActivityAnalyzer::GetAnalyzerForThread( | 97 ThreadActivityAnalyzer* GlobalActivityAnalyzer::GetAnalyzerForThread( |
79 const ThreadKey& key) { | 98 const ThreadKey& key) { |
80 auto found = analyzers_.find(key); | 99 auto found = analyzers_.find(key); |
81 if (found == analyzers_.end()) | 100 if (found == analyzers_.end()) |
82 return nullptr; | 101 return nullptr; |
83 return found->second.get(); | 102 return found->second.get(); |
84 } | 103 } |
85 | 104 |
| 105 ActivityUserData::Snapshot GlobalActivityAnalyzer::GetUserDataSnapshot( |
| 106 uint32_t ref, |
| 107 uint32_t id) { |
| 108 ActivityUserData::Snapshot snapshot; |
| 109 |
| 110 void* memory = allocator_->GetAsArray<char>( |
| 111 ref, GlobalActivityTracker::kTypeIdUserDataRecord, |
| 112 PersistentMemoryAllocator::kSizeAny); |
| 113 if (memory) { |
| 114 size_t size = allocator_->GetAllocSize(ref); |
| 115 const ActivityUserData user_data(memory, size); |
| 116 user_data.CreateSnapshot(&snapshot); |
| 117 if (user_data.id() != id) { |
| 118 // This allocation has been overwritten since it was created. Return an |
| 119 // empty snapshot because whatever was captured is incorrect. |
| 120 snapshot.clear(); |
| 121 } |
| 122 } |
| 123 |
| 124 return snapshot; |
| 125 } |
| 126 |
| 127 ActivityUserData::Snapshot GlobalActivityAnalyzer::GetGlobalUserDataSnapshot() { |
| 128 ActivityUserData::Snapshot snapshot; |
| 129 |
| 130 PersistentMemoryAllocator::Reference ref = |
| 131 PersistentMemoryAllocator::Iterator(allocator_.get()) |
| 132 .GetNextOfType(GlobalActivityTracker::kTypeIdGlobalDataRecord); |
| 133 void* memory = allocator_->GetAsArray<char>( |
| 134 ref, GlobalActivityTracker::kTypeIdGlobalDataRecord, |
| 135 PersistentMemoryAllocator::kSizeAny); |
| 136 if (memory) { |
| 137 size_t size = allocator_->GetAllocSize(ref); |
| 138 const ActivityUserData global_data(memory, size); |
| 139 global_data.CreateSnapshot(&snapshot); |
| 140 } |
| 141 |
| 142 return snapshot; |
| 143 } |
| 144 |
86 std::vector<std::string> GlobalActivityAnalyzer::GetLogMessages() { | 145 std::vector<std::string> GlobalActivityAnalyzer::GetLogMessages() { |
87 std::vector<std::string> messages; | 146 std::vector<std::string> messages; |
88 PersistentMemoryAllocator::Reference ref; | 147 PersistentMemoryAllocator::Reference ref; |
89 | 148 |
90 PersistentMemoryAllocator::Iterator iter(allocator_.get()); | 149 PersistentMemoryAllocator::Iterator iter(allocator_.get()); |
91 while ((ref = iter.GetNextOfType( | 150 while ((ref = iter.GetNextOfType( |
92 GlobalActivityTracker::kTypeIdGlobalLogMessage)) != 0) { | 151 GlobalActivityTracker::kTypeIdGlobalLogMessage)) != 0) { |
93 const char* message = allocator_->GetAsArray<char>( | 152 const char* message = allocator_->GetAsArray<char>( |
94 ref, GlobalActivityTracker::kTypeIdGlobalLogMessage, | 153 ref, GlobalActivityTracker::kTypeIdGlobalLogMessage, |
95 PersistentMemoryAllocator::kSizeAny); | 154 PersistentMemoryAllocator::kSizeAny); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 if (!base) | 192 if (!base) |
134 continue; | 193 continue; |
135 | 194 |
136 // Create the analyzer on the data. This will capture a snapshot of the | 195 // Create the analyzer on the data. This will capture a snapshot of the |
137 // tracker state. This can fail if the tracker is somehow corrupted or is | 196 // tracker state. This can fail if the tracker is somehow corrupted or is |
138 // in the process of shutting down. | 197 // in the process of shutting down. |
139 std::unique_ptr<ThreadActivityAnalyzer> analyzer(new ThreadActivityAnalyzer( | 198 std::unique_ptr<ThreadActivityAnalyzer> analyzer(new ThreadActivityAnalyzer( |
140 base, allocator_->GetAllocSize(tracker_ref))); | 199 base, allocator_->GetAllocSize(tracker_ref))); |
141 if (!analyzer->IsValid()) | 200 if (!analyzer->IsValid()) |
142 continue; | 201 continue; |
| 202 analyzer->AddGlobalInformation(this); |
143 | 203 |
144 // Add this analyzer to the map of known ones, indexed by a unique thread | 204 // Add this analyzer to the map of known ones, indexed by a unique thread |
145 // identifier. | 205 // identifier. |
146 DCHECK(!base::ContainsKey(analyzers_, analyzer->GetThreadKey())); | 206 DCHECK(!base::ContainsKey(analyzers_, analyzer->GetThreadKey())); |
147 analyzer->allocator_reference_ = ref; | 207 analyzer->allocator_reference_ = ref; |
148 analyzers_[analyzer->GetThreadKey()] = std::move(analyzer); | 208 analyzers_[analyzer->GetThreadKey()] = std::move(analyzer); |
149 } | 209 } |
150 } | 210 } |
151 | 211 |
152 } // namespace debug | 212 } // namespace debug |
153 } // namespace base | 213 } // namespace base |
OLD | NEW |