Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Side by Side Diff: base/debug/activity_tracker.cc

Issue 2673083003: Fix some issues with atomics in the activity tracker. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/debug/activity_tracker.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « base/debug/activity_tracker.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698