| 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 |