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::ThreadActivityAnalyzer( | 18 ThreadActivityAnalyzer::ThreadActivityAnalyzer( |
19 const ThreadActivityTracker& tracker) | 19 const ThreadActivityTracker& tracker) |
20 : activity_snapshot_valid_(tracker.Snapshot(&activity_snapshot_)) {} | 20 : activity_snapshot_valid_(tracker.CreateSnapshot(&activity_snapshot_)) {} |
21 | 21 |
22 ThreadActivityAnalyzer::ThreadActivityAnalyzer(void* base, size_t size) | 22 ThreadActivityAnalyzer::ThreadActivityAnalyzer(void* base, size_t size) |
23 : ThreadActivityAnalyzer(ThreadActivityTracker(base, size)) {} | 23 : ThreadActivityAnalyzer(ThreadActivityTracker(base, size)) {} |
24 | 24 |
25 ThreadActivityAnalyzer::ThreadActivityAnalyzer( | 25 ThreadActivityAnalyzer::ThreadActivityAnalyzer( |
26 PersistentMemoryAllocator* allocator, | 26 PersistentMemoryAllocator* allocator, |
27 PersistentMemoryAllocator::Reference reference) | 27 PersistentMemoryAllocator::Reference reference) |
28 : ThreadActivityAnalyzer(allocator->GetAsArray<char>( | 28 : ThreadActivityAnalyzer(allocator->GetAsArray<char>( |
29 reference, | 29 reference, |
30 GlobalActivityTracker::kTypeIdActivityTracker, | 30 GlobalActivityTracker::kTypeIdActivityTracker, |
31 1), | 31 1), |
32 allocator->GetAllocSize(reference)) {} | 32 allocator->GetAllocSize(reference)) {} |
33 | 33 |
34 ThreadActivityAnalyzer::~ThreadActivityAnalyzer() {} | 34 ThreadActivityAnalyzer::~ThreadActivityAnalyzer() {} |
35 | 35 |
| 36 void ThreadActivityAnalyzer::AddGlobalInformation( |
| 37 GlobalActivityAnalyzer* global) { |
| 38 if (!IsValid()) |
| 39 return; |
| 40 |
| 41 // User-data is held at the global scope even though it's referenced an the |
| 42 // thread scope. |
| 43 user_data_snapshots_.clear(); |
| 44 for (auto& activity : activity_snapshot_.activity_stack) { |
| 45 if (activity.user_data_ref) { |
| 46 ActivityUserData::Snapshot user_data = global->GetUserDataSnapshot( |
| 47 activity.user_data_ref, activity.user_data_id); |
| 48 user_data_snapshots_.push_back(std::move(user_data)); |
| 49 } |
| 50 } |
| 51 } |
| 52 |
| 53 const ActivityUserData::Snapshot& ThreadActivityAnalyzer::GetUserDataSnapshot( |
| 54 size_t stack_index) { |
| 55 DCHECK_GT(user_data_snapshots_.size(), stack_index); |
| 56 return user_data_snapshots_[stack_index]; |
| 57 } |
| 58 |
36 GlobalActivityAnalyzer::GlobalActivityAnalyzer( | 59 GlobalActivityAnalyzer::GlobalActivityAnalyzer( |
37 std::unique_ptr<PersistentMemoryAllocator> allocator) | 60 std::unique_ptr<PersistentMemoryAllocator> allocator) |
38 : allocator_(std::move(allocator)), allocator_iterator_(allocator_.get()) {} | 61 : allocator_(std::move(allocator)), allocator_iterator_(allocator_.get()) {} |
39 | 62 |
40 GlobalActivityAnalyzer::~GlobalActivityAnalyzer() {} | 63 GlobalActivityAnalyzer::~GlobalActivityAnalyzer() {} |
41 | 64 |
42 #if !defined(OS_NACL) | 65 #if !defined(OS_NACL) |
43 // static | 66 // static |
44 std::unique_ptr<GlobalActivityAnalyzer> GlobalActivityAnalyzer::CreateWithFile( | 67 std::unique_ptr<GlobalActivityAnalyzer> GlobalActivityAnalyzer::CreateWithFile( |
45 const FilePath& file_path) { | 68 const FilePath& file_path) { |
(...skipping 30 matching lines...) Expand all Loading... |
76 } | 99 } |
77 | 100 |
78 ThreadActivityAnalyzer* GlobalActivityAnalyzer::GetAnalyzerForThread( | 101 ThreadActivityAnalyzer* GlobalActivityAnalyzer::GetAnalyzerForThread( |
79 const ThreadKey& key) { | 102 const ThreadKey& key) { |
80 auto found = analyzers_.find(key); | 103 auto found = analyzers_.find(key); |
81 if (found == analyzers_.end()) | 104 if (found == analyzers_.end()) |
82 return nullptr; | 105 return nullptr; |
83 return found->second.get(); | 106 return found->second.get(); |
84 } | 107 } |
85 | 108 |
| 109 ActivityUserData::Snapshot GlobalActivityAnalyzer::GetUserDataSnapshot( |
| 110 uint32_t ref, |
| 111 uint32_t id) { |
| 112 ActivityUserData::Snapshot snapshot; |
| 113 |
| 114 void* memory = allocator_->GetAsArray<char>( |
| 115 ref, GlobalActivityTracker::kTypeIdUserDataRecord, |
| 116 PersistentMemoryAllocator::kSizeAny); |
| 117 if (memory) { |
| 118 size_t size = allocator_->GetAllocSize(ref); |
| 119 const ActivityUserData user_data(memory, size); |
| 120 user_data.CreateSnapshot(&snapshot); |
| 121 if (user_data.id() != id) { |
| 122 // This allocation has been overwritten since it was created. Return an |
| 123 // empty snapshot because whatever was captured is incorrect. |
| 124 snapshot.clear(); |
| 125 } |
| 126 } |
| 127 |
| 128 return snapshot; |
| 129 } |
| 130 |
| 131 ActivityUserData::Snapshot GlobalActivityAnalyzer::GetGlobalUserDataSnapshot() { |
| 132 ActivityUserData::Snapshot snapshot; |
| 133 |
| 134 PersistentMemoryAllocator::Reference ref = |
| 135 PersistentMemoryAllocator::Iterator(allocator_.get()) |
| 136 .GetNextOfType(GlobalActivityTracker::kTypeIdGlobalDataRecord); |
| 137 void* memory = allocator_->GetAsArray<char>( |
| 138 ref, GlobalActivityTracker::kTypeIdGlobalDataRecord, |
| 139 PersistentMemoryAllocator::kSizeAny); |
| 140 if (memory) { |
| 141 size_t size = allocator_->GetAllocSize(ref); |
| 142 const ActivityUserData global_data(memory, size); |
| 143 global_data.CreateSnapshot(&snapshot); |
| 144 } |
| 145 |
| 146 return snapshot; |
| 147 } |
| 148 |
86 GlobalActivityAnalyzer::ProgramLocation | 149 GlobalActivityAnalyzer::ProgramLocation |
87 GlobalActivityAnalyzer::GetProgramLocationFromAddress(uint64_t address) { | 150 GlobalActivityAnalyzer::GetProgramLocationFromAddress(uint64_t address) { |
88 // TODO(bcwhite): Implement this. | 151 // TODO(bcwhite): Implement this. |
89 return { 0, 0 }; | 152 return { 0, 0 }; |
90 } | 153 } |
91 | 154 |
92 void GlobalActivityAnalyzer::PrepareAllAnalyzers() { | 155 void GlobalActivityAnalyzer::PrepareAllAnalyzers() { |
93 // Fetch all the records. This will retrieve only ones created since the | 156 // Fetch all the records. This will retrieve only ones created since the |
94 // last run since the PMA iterator will continue from where it left off. | 157 // last run since the PMA iterator will continue from where it left off. |
95 uint32_t type; | 158 uint32_t type; |
(...skipping 20 matching lines...) Expand all Loading... |
116 if (!base) | 179 if (!base) |
117 continue; | 180 continue; |
118 | 181 |
119 // Create the analyzer on the data. This will capture a snapshot of the | 182 // Create the analyzer on the data. This will capture a snapshot of the |
120 // tracker state. This can fail if the tracker is somehow corrupted or is | 183 // tracker state. This can fail if the tracker is somehow corrupted or is |
121 // in the process of shutting down. | 184 // in the process of shutting down. |
122 std::unique_ptr<ThreadActivityAnalyzer> analyzer(new ThreadActivityAnalyzer( | 185 std::unique_ptr<ThreadActivityAnalyzer> analyzer(new ThreadActivityAnalyzer( |
123 base, allocator_->GetAllocSize(tracker_ref))); | 186 base, allocator_->GetAllocSize(tracker_ref))); |
124 if (!analyzer->IsValid()) | 187 if (!analyzer->IsValid()) |
125 continue; | 188 continue; |
| 189 analyzer->AddGlobalInformation(this); |
126 | 190 |
127 // Add this analyzer to the map of known ones, indexed by a unique thread | 191 // Add this analyzer to the map of known ones, indexed by a unique thread |
128 // identifier. | 192 // identifier. |
129 DCHECK(!base::ContainsKey(analyzers_, analyzer->GetThreadKey())); | 193 DCHECK(!base::ContainsKey(analyzers_, analyzer->GetThreadKey())); |
130 analyzer->allocator_reference_ = ref; | 194 analyzer->allocator_reference_ = ref; |
131 analyzers_[analyzer->GetThreadKey()] = std::move(analyzer); | 195 analyzers_[analyzer->GetThreadKey()] = std::move(analyzer); |
132 } | 196 } |
133 } | 197 } |
134 | 198 |
135 } // namespace debug | 199 } // namespace debug |
136 } // namespace base | 200 } // namespace base |
OLD | NEW |