| 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_tracker.h" | 5 #include "base/debug/activity_tracker.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/atomic_sequence_num.h" |
| 11 #include "base/debug/stack_trace.h" | 12 #include "base/debug/stack_trace.h" |
| 12 #include "base/files/file.h" | 13 #include "base/files/file.h" |
| 13 #include "base/files/file_path.h" | 14 #include "base/files/file_path.h" |
| 14 #include "base/files/memory_mapped_file.h" | 15 #include "base/files/memory_mapped_file.h" |
| 15 #include "base/logging.h" | 16 #include "base/logging.h" |
| 16 #include "base/memory/ptr_util.h" | 17 #include "base/memory/ptr_util.h" |
| 17 #include "base/metrics/field_trial.h" | 18 #include "base/metrics/field_trial.h" |
| 18 #include "base/metrics/histogram_macros.h" | 19 #include "base/metrics/histogram_macros.h" |
| 19 #include "base/pending_task.h" | 20 #include "base/pending_task.h" |
| 20 #include "base/pickle.h" | 21 #include "base/pickle.h" |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 | 247 |
| 247 StringPiece ActivityUserData::TypedValue::GetStringReference() const { | 248 StringPiece ActivityUserData::TypedValue::GetStringReference() const { |
| 248 DCHECK_EQ(STRING_VALUE_REFERENCE, type_); | 249 DCHECK_EQ(STRING_VALUE_REFERENCE, type_); |
| 249 return ref_value_; | 250 return ref_value_; |
| 250 } | 251 } |
| 251 | 252 |
| 252 ActivityUserData::ValueInfo::ValueInfo() {} | 253 ActivityUserData::ValueInfo::ValueInfo() {} |
| 253 ActivityUserData::ValueInfo::ValueInfo(ValueInfo&&) = default; | 254 ActivityUserData::ValueInfo::ValueInfo(ValueInfo&&) = default; |
| 254 ActivityUserData::ValueInfo::~ValueInfo() {} | 255 ActivityUserData::ValueInfo::~ValueInfo() {} |
| 255 | 256 |
| 256 std::atomic<uint32_t> ActivityUserData::next_id_; | 257 StaticAtomicSequenceNumber ActivityUserData::next_id_; |
| 257 | 258 |
| 258 ActivityUserData::ActivityUserData(void* memory, size_t size) | 259 ActivityUserData::ActivityUserData(void* memory, size_t size) |
| 259 : memory_(reinterpret_cast<char*>(memory)), | 260 : memory_(reinterpret_cast<char*>(memory)), |
| 260 available_(RoundDownToAlignment(size, kMemoryAlignment)), | 261 available_(RoundDownToAlignment(size, kMemoryAlignment)), |
| 261 id_(reinterpret_cast<std::atomic<uint32_t>*>(memory)) { | 262 id_(reinterpret_cast<std::atomic<uint32_t>*>(memory)) { |
| 262 // It's possible that no user data is being stored. | 263 // It's possible that no user data is being stored. |
| 263 if (!memory_) | 264 if (!memory_) |
| 264 return; | 265 return; |
| 265 | 266 |
| 266 DCHECK_LT(kMemoryAlignment, available_); | 267 DCHECK_LT(kMemoryAlignment, available_); |
| 267 if (id_->load(std::memory_order_relaxed) == 0) { | 268 if (id_->load(std::memory_order_relaxed) == 0) { |
| 268 // Generate a new ID and store it in the first 32-bit word of memory_. | 269 // Generate a new ID and store it in the first 32-bit word of memory_. |
| 269 // |id_| must be non-zero for non-sink instances. | 270 // |id_| must be non-zero for non-sink instances. |
| 270 uint32_t id; | 271 uint32_t id; |
| 271 while ((id = next_id_.fetch_add(1, std::memory_order_relaxed)) == 0) | 272 while ((id = next_id_.GetNext()) == 0) |
| 272 ; | 273 ; |
| 273 id_->store(id, std::memory_order_relaxed); | 274 id_->store(id, std::memory_order_relaxed); |
| 274 DCHECK_NE(0U, id_->load(std::memory_order_relaxed)); | 275 DCHECK_NE(0U, id_->load(std::memory_order_relaxed)); |
| 275 } | 276 } |
| 276 memory_ += kMemoryAlignment; | 277 memory_ += kMemoryAlignment; |
| 277 available_ -= kMemoryAlignment; | 278 available_ -= kMemoryAlignment; |
| 278 | 279 |
| 279 // If there is already data present, load that. This allows the same class | 280 // If there is already data present, load that. This allows the same class |
| 280 // to be used for analysis through snapshots. | 281 // to be used for analysis through snapshots. |
| 281 ImportExistingData(); | 282 ImportExistingData(); |
| (...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 892 | 893 |
| 893 // Too many attempts. | 894 // Too many attempts. |
| 894 return false; | 895 return false; |
| 895 } | 896 } |
| 896 | 897 |
| 897 // static | 898 // static |
| 898 size_t ThreadActivityTracker::SizeForStackDepth(int stack_depth) { | 899 size_t ThreadActivityTracker::SizeForStackDepth(int stack_depth) { |
| 899 return static_cast<size_t>(stack_depth) * sizeof(Activity) + sizeof(Header); | 900 return static_cast<size_t>(stack_depth) * sizeof(Activity) + sizeof(Header); |
| 900 } | 901 } |
| 901 | 902 |
| 902 | 903 // The instantiation of the GlobalActivityTracker object. |
| 903 GlobalActivityTracker* GlobalActivityTracker::g_tracker_ = nullptr; | 904 // The object held here will obviously not be destructed at process exit |
| 905 // but that's best since PersistentMemoryAllocator objects (that underlie |
| 906 // GlobalActivityTracker objects) are explicitly forbidden from doing anything |
| 907 // essential at exit anyway due to the fact that they depend on data managed |
| 908 // elsewhere and which could be destructed first. An AtomicWord is used instead |
| 909 // of std::atomic because the latter can create global ctors and dtors. |
| 910 subtle::AtomicWord GlobalActivityTracker::g_tracker_ = 0; |
| 904 | 911 |
| 905 GlobalActivityTracker::ModuleInfo::ModuleInfo() {} | 912 GlobalActivityTracker::ModuleInfo::ModuleInfo() {} |
| 906 GlobalActivityTracker::ModuleInfo::ModuleInfo(ModuleInfo&& rhs) = default; | 913 GlobalActivityTracker::ModuleInfo::ModuleInfo(ModuleInfo&& rhs) = default; |
| 907 GlobalActivityTracker::ModuleInfo::ModuleInfo(const ModuleInfo& rhs) = default; | 914 GlobalActivityTracker::ModuleInfo::ModuleInfo(const ModuleInfo& rhs) = default; |
| 908 GlobalActivityTracker::ModuleInfo::~ModuleInfo() {} | 915 GlobalActivityTracker::ModuleInfo::~ModuleInfo() {} |
| 909 | 916 |
| 910 GlobalActivityTracker::ModuleInfo& GlobalActivityTracker::ModuleInfo::operator=( | 917 GlobalActivityTracker::ModuleInfo& GlobalActivityTracker::ModuleInfo::operator=( |
| 911 ModuleInfo&& rhs) = default; | 918 ModuleInfo&& rhs) = default; |
| 912 GlobalActivityTracker::ModuleInfo& GlobalActivityTracker::ModuleInfo::operator=( | 919 GlobalActivityTracker::ModuleInfo& GlobalActivityTracker::ModuleInfo::operator=( |
| 913 const ModuleInfo& rhs) = default; | 920 const ModuleInfo& rhs) = default; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1055 size_t size) | 1062 size_t size) |
| 1056 : ThreadActivityTracker(base, size), | 1063 : ThreadActivityTracker(base, size), |
| 1057 mem_reference_(mem_reference), | 1064 mem_reference_(mem_reference), |
| 1058 mem_base_(base) {} | 1065 mem_base_(base) {} |
| 1059 | 1066 |
| 1060 GlobalActivityTracker::ManagedActivityTracker::~ManagedActivityTracker() { | 1067 GlobalActivityTracker::ManagedActivityTracker::~ManagedActivityTracker() { |
| 1061 // The global |g_tracker_| must point to the owner of this class since all | 1068 // The global |g_tracker_| must point to the owner of this class since all |
| 1062 // objects of this type must be destructed before |g_tracker_| can be changed | 1069 // objects of this type must be destructed before |g_tracker_| can be changed |
| 1063 // (something that only occurs in tests). | 1070 // (something that only occurs in tests). |
| 1064 DCHECK(g_tracker_); | 1071 DCHECK(g_tracker_); |
| 1065 g_tracker_->ReturnTrackerMemory(this); | 1072 GlobalActivityTracker::Get()->ReturnTrackerMemory(this); |
| 1066 } | 1073 } |
| 1067 | 1074 |
| 1068 void GlobalActivityTracker::CreateWithAllocator( | 1075 void GlobalActivityTracker::CreateWithAllocator( |
| 1069 std::unique_ptr<PersistentMemoryAllocator> allocator, | 1076 std::unique_ptr<PersistentMemoryAllocator> allocator, |
| 1070 int stack_depth) { | 1077 int stack_depth) { |
| 1071 // There's no need to do anything with the result. It is self-managing. | 1078 // There's no need to do anything with the result. It is self-managing. |
| 1072 GlobalActivityTracker* global_tracker = | 1079 GlobalActivityTracker* global_tracker = |
| 1073 new GlobalActivityTracker(std::move(allocator), stack_depth); | 1080 new GlobalActivityTracker(std::move(allocator), stack_depth); |
| 1074 // Create a tracker for this thread since it is known. | 1081 // Create a tracker for this thread since it is known. |
| 1075 global_tracker->CreateTrackerForCurrentThread(); | 1082 global_tracker->CreateTrackerForCurrentThread(); |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1233 allocator_->Allocate(kGlobalDataSize, kTypeIdGlobalDataRecord), | 1240 allocator_->Allocate(kGlobalDataSize, kTypeIdGlobalDataRecord), |
| 1234 kTypeIdGlobalDataRecord, | 1241 kTypeIdGlobalDataRecord, |
| 1235 PersistentMemoryAllocator::kSizeAny), | 1242 PersistentMemoryAllocator::kSizeAny), |
| 1236 kGlobalDataSize) { | 1243 kGlobalDataSize) { |
| 1237 // Ensure the passed memory is valid and empty (iterator finds nothing). | 1244 // Ensure the passed memory is valid and empty (iterator finds nothing). |
| 1238 uint32_t type; | 1245 uint32_t type; |
| 1239 DCHECK(!PersistentMemoryAllocator::Iterator(allocator_.get()).GetNext(&type)); | 1246 DCHECK(!PersistentMemoryAllocator::Iterator(allocator_.get()).GetNext(&type)); |
| 1240 | 1247 |
| 1241 // Ensure that there is no other global object and then make this one such. | 1248 // Ensure that there is no other global object and then make this one such. |
| 1242 DCHECK(!g_tracker_); | 1249 DCHECK(!g_tracker_); |
| 1243 g_tracker_ = this; | 1250 subtle::NoBarrier_Store(&g_tracker_, reinterpret_cast<uintptr_t>(this)); |
| 1244 | 1251 |
| 1245 // The global records must be iterable in order to be found by an analyzer. | 1252 // The global records must be iterable in order to be found by an analyzer. |
| 1246 allocator_->MakeIterable(allocator_->GetAsReference( | 1253 allocator_->MakeIterable(allocator_->GetAsReference( |
| 1247 user_data_.GetBaseAddress(), kTypeIdGlobalDataRecord)); | 1254 user_data_.GetBaseAddress(), kTypeIdGlobalDataRecord)); |
| 1248 } | 1255 } |
| 1249 | 1256 |
| 1250 GlobalActivityTracker::~GlobalActivityTracker() { | 1257 GlobalActivityTracker::~GlobalActivityTracker() { |
| 1251 DCHECK_EQ(g_tracker_, this); | 1258 DCHECK_EQ(Get(), this); |
| 1252 DCHECK_EQ(0, thread_tracker_count_.load(std::memory_order_relaxed)); | 1259 DCHECK_EQ(0, thread_tracker_count_.load(std::memory_order_relaxed)); |
| 1253 g_tracker_ = nullptr; | 1260 subtle::NoBarrier_Store(&g_tracker_, 0); |
| 1254 } | 1261 } |
| 1255 | 1262 |
| 1256 void GlobalActivityTracker::ReturnTrackerMemory( | 1263 void GlobalActivityTracker::ReturnTrackerMemory( |
| 1257 ManagedActivityTracker* tracker) { | 1264 ManagedActivityTracker* tracker) { |
| 1258 PersistentMemoryAllocator::Reference mem_reference = tracker->mem_reference_; | 1265 PersistentMemoryAllocator::Reference mem_reference = tracker->mem_reference_; |
| 1259 void* mem_base = tracker->mem_base_; | 1266 void* mem_base = tracker->mem_base_; |
| 1260 DCHECK(mem_reference); | 1267 DCHECK(mem_reference); |
| 1261 DCHECK(mem_base); | 1268 DCHECK(mem_base); |
| 1262 | 1269 |
| 1263 // Remove the destructed tracker from the set of known ones. | 1270 // Remove the destructed tracker from the set of known ones. |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1352 : GlobalActivityTracker::ScopedThreadActivity( | 1359 : GlobalActivityTracker::ScopedThreadActivity( |
| 1353 program_counter, | 1360 program_counter, |
| 1354 nullptr, | 1361 nullptr, |
| 1355 Activity::ACT_PROCESS_WAIT, | 1362 Activity::ACT_PROCESS_WAIT, |
| 1356 ActivityData::ForProcess(process->Pid()), | 1363 ActivityData::ForProcess(process->Pid()), |
| 1357 /*lock_allowed=*/true) {} | 1364 /*lock_allowed=*/true) {} |
| 1358 #endif | 1365 #endif |
| 1359 | 1366 |
| 1360 } // namespace debug | 1367 } // namespace debug |
| 1361 } // namespace base | 1368 } // namespace base |
| OLD | NEW |