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

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

Issue 2754483002: Add analyzer support for multiple processes. (Closed)
Patch Set: addressed review comments by manzagop Created 3 years, 8 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') | base/debug/activity_tracker_unittest.cc » ('j') | 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
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 // can be converted to a thread-id with a system call. 60 // can be converted to a thread-id with a system call.
61 PlatformThreadId as_tid; 61 PlatformThreadId as_tid;
62 #elif defined(OS_POSIX) 62 #elif defined(OS_POSIX)
63 // On Posix, the handle is always a unique identifier so no conversion 63 // On Posix, the handle is always a unique identifier so no conversion
64 // needs to be done. However, it's value is officially opaque so there 64 // needs to be done. However, it's value is officially opaque so there
65 // is no one correct way to convert it to a numerical identifier. 65 // is no one correct way to convert it to a numerical identifier.
66 PlatformThreadHandle::Handle as_handle; 66 PlatformThreadHandle::Handle as_handle;
67 #endif 67 #endif
68 }; 68 };
69 69
70 // Get the next non-zero identifier. It is only unique within a process. 70 // Gets the next non-zero identifier. It is only unique within a process.
71 uint32_t GetNextDataId() { 71 uint32_t GetNextDataId() {
72 uint32_t id; 72 uint32_t id;
73 while ((id = g_next_id.GetNext()) == 0) 73 while ((id = g_next_id.GetNext()) == 0)
74 ; 74 ;
75 return id; 75 return id;
76 } 76 }
77 77
78 // Gets the current process-id, either from the GlobalActivityTracker if it
79 // exists (where the PID can be defined for testing) or from the system if
80 // there isn't such.
81 int64_t GetProcessId() {
82 GlobalActivityTracker* global = GlobalActivityTracker::Get();
83 if (global)
84 return global->process_id();
85 return GetCurrentProcId();
86 }
87
78 // Finds and reuses a specific allocation or creates a new one. 88 // Finds and reuses a specific allocation or creates a new one.
79 PersistentMemoryAllocator::Reference AllocateFrom( 89 PersistentMemoryAllocator::Reference AllocateFrom(
80 PersistentMemoryAllocator* allocator, 90 PersistentMemoryAllocator* allocator,
81 uint32_t from_type, 91 uint32_t from_type,
82 size_t size, 92 size_t size,
83 uint32_t to_type) { 93 uint32_t to_type) {
84 PersistentMemoryAllocator::Iterator iter(allocator); 94 PersistentMemoryAllocator::Iterator iter(allocator);
85 PersistentMemoryAllocator::Reference ref; 95 PersistentMemoryAllocator::Reference ref;
86 while ((ref = iter.GetNextOfType(from_type)) != 0) { 96 while ((ref = iter.GetNextOfType(from_type)) != 0) {
87 DCHECK_LE(size, allocator->GetAllocSize(ref)); 97 DCHECK_LE(size, allocator->GetAllocSize(ref));
(...skipping 19 matching lines...) Expand all
107 // Converts "tick" timing into wall time. 117 // Converts "tick" timing into wall time.
108 Time WallTimeFromTickTime(int64_t ticks_start, int64_t ticks, Time time_start) { 118 Time WallTimeFromTickTime(int64_t ticks_start, int64_t ticks, Time time_start) {
109 return time_start + TimeDelta::FromInternalValue(ticks - ticks_start); 119 return time_start + TimeDelta::FromInternalValue(ticks - ticks_start);
110 } 120 }
111 121
112 } // namespace 122 } // namespace
113 123
114 OwningProcess::OwningProcess() {} 124 OwningProcess::OwningProcess() {}
115 OwningProcess::~OwningProcess() {} 125 OwningProcess::~OwningProcess() {}
116 126
117 void OwningProcess::Release_Initialize() { 127 void OwningProcess::Release_Initialize(int64_t pid) {
118 uint32_t old_id = data_id.load(std::memory_order_acquire); 128 uint32_t old_id = data_id.load(std::memory_order_acquire);
119 DCHECK_EQ(0U, old_id); 129 DCHECK_EQ(0U, old_id);
120 process_id = GetCurrentProcId(); 130 process_id = pid != 0 ? pid : GetProcessId();
121 create_stamp = Time::Now().ToInternalValue(); 131 create_stamp = Time::Now().ToInternalValue();
122 data_id.store(GetNextDataId(), std::memory_order_release); 132 data_id.store(GetNextDataId(), std::memory_order_release);
123 } 133 }
124 134
125 void OwningProcess::SetOwningProcessIdForTesting(ProcessId pid, int64_t stamp) { 135 void OwningProcess::SetOwningProcessIdForTesting(int64_t pid, int64_t stamp) {
126 DCHECK_NE(0U, data_id); 136 DCHECK_NE(0U, data_id);
127 process_id = pid; 137 process_id = pid;
128 create_stamp = stamp; 138 create_stamp = stamp;
129 } 139 }
130 140
131 // static 141 // static
132 bool OwningProcess::GetOwningProcessId(const void* memory, 142 bool OwningProcess::GetOwningProcessId(const void* memory,
133 ProcessId* out_id, 143 int64_t* out_id,
134 int64_t* out_stamp) { 144 int64_t* out_stamp) {
135 const OwningProcess* info = reinterpret_cast<const OwningProcess*>(memory); 145 const OwningProcess* info = reinterpret_cast<const OwningProcess*>(memory);
136 uint32_t id = info->data_id.load(std::memory_order_acquire); 146 uint32_t id = info->data_id.load(std::memory_order_acquire);
137 if (id == 0) 147 if (id == 0)
138 return false; 148 return false;
139 149
140 *out_id = static_cast<ProcessId>(info->process_id); 150 *out_id = info->process_id;
141 *out_stamp = info->create_stamp; 151 *out_stamp = info->create_stamp;
142 return id == info->data_id.load(std::memory_order_seq_cst); 152 return id == info->data_id.load(std::memory_order_seq_cst);
143 } 153 }
144 154
145 // It doesn't matter what is contained in this (though it will be all zeros) 155 // It doesn't matter what is contained in this (though it will be all zeros)
146 // as only the address of it is important. 156 // as only the address of it is important.
147 const ActivityData kNullActivityData = {}; 157 const ActivityData kNullActivityData = {};
148 158
149 ActivityData ActivityData::ForThread(const PlatformThreadHandle& handle) { 159 ActivityData ActivityData::ForThread(const PlatformThreadHandle& handle) {
150 ThreadRef thread_ref; 160 ThreadRef thread_ref;
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 // thus clang requires explicit out-of-line constructors and destructors even 325 // thus clang requires explicit out-of-line constructors and destructors even
316 // when they do nothing. 326 // when they do nothing.
317 ActivityUserData::ValueInfo::ValueInfo() {} 327 ActivityUserData::ValueInfo::ValueInfo() {}
318 ActivityUserData::ValueInfo::ValueInfo(ValueInfo&&) = default; 328 ActivityUserData::ValueInfo::ValueInfo(ValueInfo&&) = default;
319 ActivityUserData::ValueInfo::~ValueInfo() {} 329 ActivityUserData::ValueInfo::~ValueInfo() {}
320 ActivityUserData::MemoryHeader::MemoryHeader() {} 330 ActivityUserData::MemoryHeader::MemoryHeader() {}
321 ActivityUserData::MemoryHeader::~MemoryHeader() {} 331 ActivityUserData::MemoryHeader::~MemoryHeader() {}
322 ActivityUserData::FieldHeader::FieldHeader() {} 332 ActivityUserData::FieldHeader::FieldHeader() {}
323 ActivityUserData::FieldHeader::~FieldHeader() {} 333 ActivityUserData::FieldHeader::~FieldHeader() {}
324 334
325 ActivityUserData::ActivityUserData() : ActivityUserData(nullptr, 0) {} 335 ActivityUserData::ActivityUserData() : ActivityUserData(nullptr, 0, -1) {}
326 336
327 ActivityUserData::ActivityUserData(void* memory, size_t size) 337 ActivityUserData::ActivityUserData(void* memory, size_t size, int64_t pid)
328 : memory_(reinterpret_cast<char*>(memory)), 338 : memory_(reinterpret_cast<char*>(memory)),
329 available_(RoundDownToAlignment(size, kMemoryAlignment)), 339 available_(RoundDownToAlignment(size, kMemoryAlignment)),
330 header_(reinterpret_cast<MemoryHeader*>(memory)) { 340 header_(reinterpret_cast<MemoryHeader*>(memory)),
341 orig_data_id(0),
342 orig_process_id(0),
343 orig_create_stamp(0) {
331 // It's possible that no user data is being stored. 344 // It's possible that no user data is being stored.
332 if (!memory_) 345 if (!memory_)
333 return; 346 return;
334 347
335 static_assert(0 == sizeof(MemoryHeader) % kMemoryAlignment, "invalid header"); 348 static_assert(0 == sizeof(MemoryHeader) % kMemoryAlignment, "invalid header");
336 DCHECK_LT(sizeof(MemoryHeader), available_); 349 DCHECK_LT(sizeof(MemoryHeader), available_);
337 if (header_->owner.data_id.load(std::memory_order_acquire) == 0) 350 if (header_->owner.data_id.load(std::memory_order_acquire) == 0)
338 header_->owner.Release_Initialize(); 351 header_->owner.Release_Initialize(pid);
339 memory_ += sizeof(MemoryHeader); 352 memory_ += sizeof(MemoryHeader);
340 available_ -= sizeof(MemoryHeader); 353 available_ -= sizeof(MemoryHeader);
341 354
355 // Make a copy of identifying information for later comparison.
356 *const_cast<uint32_t*>(&orig_data_id) =
357 header_->owner.data_id.load(std::memory_order_acquire);
358 *const_cast<int64_t*>(&orig_process_id) = header_->owner.process_id;
359 *const_cast<int64_t*>(&orig_create_stamp) = header_->owner.create_stamp;
360
342 // If there is already data present, load that. This allows the same class 361 // If there is already data present, load that. This allows the same class
343 // to be used for analysis through snapshots. 362 // to be used for analysis through snapshots.
344 ImportExistingData(); 363 ImportExistingData();
345 } 364 }
346 365
347 ActivityUserData::~ActivityUserData() {} 366 ActivityUserData::~ActivityUserData() {}
348 367
349 bool ActivityUserData::CreateSnapshot(Snapshot* output_snapshot) const { 368 bool ActivityUserData::CreateSnapshot(Snapshot* output_snapshot) const {
350 DCHECK(output_snapshot); 369 DCHECK(output_snapshot);
351 DCHECK(output_snapshot->empty()); 370 DCHECK(output_snapshot->empty());
352 371
353 // Find any new data that may have been added by an active instance of this 372 // Find any new data that may have been added by an active instance of this
354 // class that is adding records. 373 // class that is adding records.
355 ImportExistingData(); 374 ImportExistingData();
356 375
376 // Add all the values to the snapshot.
357 for (const auto& entry : values_) { 377 for (const auto& entry : values_) {
358 TypedValue value; 378 TypedValue value;
379 const size_t size = entry.second.size_ptr->load(std::memory_order_acquire);
359 value.type_ = entry.second.type; 380 value.type_ = entry.second.type;
360 DCHECK_GE(entry.second.extent, 381 DCHECK_GE(entry.second.extent, size);
361 entry.second.size_ptr->load(std::memory_order_relaxed));
362 382
363 switch (entry.second.type) { 383 switch (entry.second.type) {
364 case RAW_VALUE: 384 case RAW_VALUE:
365 case STRING_VALUE: 385 case STRING_VALUE:
366 value.long_value_ = 386 value.long_value_ =
367 std::string(reinterpret_cast<char*>(entry.second.memory), 387 std::string(reinterpret_cast<char*>(entry.second.memory), size);
368 entry.second.size_ptr->load(std::memory_order_relaxed));
369 break; 388 break;
370 case RAW_VALUE_REFERENCE: 389 case RAW_VALUE_REFERENCE:
371 case STRING_VALUE_REFERENCE: { 390 case STRING_VALUE_REFERENCE: {
372 ReferenceRecord* ref = 391 ReferenceRecord* ref =
373 reinterpret_cast<ReferenceRecord*>(entry.second.memory); 392 reinterpret_cast<ReferenceRecord*>(entry.second.memory);
374 value.ref_value_ = StringPiece( 393 value.ref_value_ = StringPiece(
375 reinterpret_cast<char*>(static_cast<uintptr_t>(ref->address)), 394 reinterpret_cast<char*>(static_cast<uintptr_t>(ref->address)),
376 static_cast<size_t>(ref->size)); 395 static_cast<size_t>(ref->size));
377 } break; 396 } break;
378 case BOOL_VALUE: 397 case BOOL_VALUE:
379 case CHAR_VALUE: 398 case CHAR_VALUE:
380 value.short_value_ = *reinterpret_cast<char*>(entry.second.memory); 399 value.short_value_ = *reinterpret_cast<char*>(entry.second.memory);
381 break; 400 break;
382 case SIGNED_VALUE: 401 case SIGNED_VALUE:
383 case UNSIGNED_VALUE: 402 case UNSIGNED_VALUE:
384 value.short_value_ = *reinterpret_cast<uint64_t*>(entry.second.memory); 403 value.short_value_ = *reinterpret_cast<uint64_t*>(entry.second.memory);
385 break; 404 break;
386 case END_OF_VALUES: // Included for completeness purposes. 405 case END_OF_VALUES: // Included for completeness purposes.
387 NOTREACHED(); 406 NOTREACHED();
388 } 407 }
389 auto inserted = output_snapshot->insert( 408 auto inserted = output_snapshot->insert(
390 std::make_pair(entry.second.name.as_string(), std::move(value))); 409 std::make_pair(entry.second.name.as_string(), std::move(value)));
391 DCHECK(inserted.second); // True if inserted, false if existed. 410 DCHECK(inserted.second); // True if inserted, false if existed.
392 } 411 }
393 412
413 // Another import attempt will validate that the underlying memory has not
414 // been reused for another purpose. Entries added since the first import
415 // will be ignored here but will be returned if another snapshot is created.
416 ImportExistingData();
417 if (!memory_) {
418 output_snapshot->clear();
419 return false;
420 }
421
422 // Successful snapshot.
394 return true; 423 return true;
395 } 424 }
396 425
397 const void* ActivityUserData::GetBaseAddress() const { 426 const void* ActivityUserData::GetBaseAddress() const {
398 // The |memory_| pointer advances as elements are written but the |header_| 427 // The |memory_| pointer advances as elements are written but the |header_|
399 // value is always at the start of the block so just return that. 428 // value is always at the start of the block so just return that.
400 return header_; 429 return header_;
401 } 430 }
402 431
403 void ActivityUserData::SetOwningProcessIdForTesting(ProcessId pid, 432 void ActivityUserData::SetOwningProcessIdForTesting(int64_t pid,
404 int64_t stamp) { 433 int64_t stamp) {
405 if (!header_) 434 if (!header_)
406 return; 435 return;
407 header_->owner.SetOwningProcessIdForTesting(pid, stamp); 436 header_->owner.SetOwningProcessIdForTesting(pid, stamp);
408 } 437 }
409 438
410 // static 439 // static
411 bool ActivityUserData::GetOwningProcessId(const void* memory, 440 bool ActivityUserData::GetOwningProcessId(const void* memory,
412 ProcessId* out_id, 441 int64_t* out_id,
413 int64_t* out_stamp) { 442 int64_t* out_stamp) {
414 const MemoryHeader* header = reinterpret_cast<const MemoryHeader*>(memory); 443 const MemoryHeader* header = reinterpret_cast<const MemoryHeader*>(memory);
415 return OwningProcess::GetOwningProcessId(&header->owner, out_id, out_stamp); 444 return OwningProcess::GetOwningProcessId(&header->owner, out_id, out_stamp);
416 } 445 }
417 446
418 void ActivityUserData::Set(StringPiece name, 447 void ActivityUserData::Set(StringPiece name,
419 ValueType type, 448 ValueType type,
420 const void* memory, 449 const void* memory,
421 size_t size) { 450 size_t size) {
422 DCHECK_GE(std::numeric_limits<uint8_t>::max(), name.length()); 451 DCHECK_GE(std::numeric_limits<uint8_t>::max(), name.length());
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 ValueType type, 546 ValueType type,
518 const void* memory, 547 const void* memory,
519 size_t size) { 548 size_t size) {
520 ReferenceRecord rec; 549 ReferenceRecord rec;
521 rec.address = reinterpret_cast<uintptr_t>(memory); 550 rec.address = reinterpret_cast<uintptr_t>(memory);
522 rec.size = size; 551 rec.size = size;
523 Set(name, type, &rec, sizeof(rec)); 552 Set(name, type, &rec, sizeof(rec));
524 } 553 }
525 554
526 void ActivityUserData::ImportExistingData() const { 555 void ActivityUserData::ImportExistingData() const {
556 // It's possible that no user data is being stored.
557 if (!memory_)
558 return;
559
527 while (available_ > sizeof(FieldHeader)) { 560 while (available_ > sizeof(FieldHeader)) {
528 FieldHeader* header = reinterpret_cast<FieldHeader*>(memory_); 561 FieldHeader* header = reinterpret_cast<FieldHeader*>(memory_);
529 ValueType type = 562 ValueType type =
530 static_cast<ValueType>(header->type.load(std::memory_order_acquire)); 563 static_cast<ValueType>(header->type.load(std::memory_order_acquire));
531 if (type == END_OF_VALUES) 564 if (type == END_OF_VALUES)
532 return; 565 return;
533 if (header->record_size > available_) 566 if (header->record_size > available_)
534 return; 567 return;
535 568
536 size_t value_offset = RoundUpToAlignment( 569 size_t value_offset = RoundUpToAlignment(
(...skipping 11 matching lines...) Expand all
548 info.memory = memory_ + value_offset; 581 info.memory = memory_ + value_offset;
549 info.size_ptr = &header->value_size; 582 info.size_ptr = &header->value_size;
550 info.extent = header->record_size - value_offset; 583 info.extent = header->record_size - value_offset;
551 584
552 StringPiece key(info.name); 585 StringPiece key(info.name);
553 values_.insert(std::make_pair(key, std::move(info))); 586 values_.insert(std::make_pair(key, std::move(info)));
554 587
555 memory_ += header->record_size; 588 memory_ += header->record_size;
556 available_ -= header->record_size; 589 available_ -= header->record_size;
557 } 590 }
591
592 // Check if memory has been completely reused.
593 if (header_->owner.data_id.load(std::memory_order_acquire) != orig_data_id ||
594 header_->owner.process_id != orig_process_id ||
595 header_->owner.create_stamp != orig_create_stamp) {
596 memory_ = nullptr;
597 values_.clear();
598 }
558 } 599 }
559 600
560 // This information is kept for every thread that is tracked. It is filled 601 // This information is kept for every thread that is tracked. It is filled
561 // the very first time the thread is seen. All fields must be of exact sizes 602 // the very first time the thread is seen. All fields must be of exact sizes
562 // so there is no issue moving between 32 and 64-bit builds. 603 // so there is no issue moving between 32 and 64-bit builds.
563 struct ThreadActivityTracker::Header { 604 struct ThreadActivityTracker::Header {
564 // Defined in .h for analyzer access. Increment this if structure changes! 605 // Defined in .h for analyzer access. Increment this if structure changes!
565 static constexpr uint32_t kPersistentTypeId = 606 static constexpr uint32_t kPersistentTypeId =
566 GlobalActivityTracker::kTypeIdActivityTracker; 607 GlobalActivityTracker::kTypeIdActivityTracker;
567 608
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
888 // during the time-sensitive snapshot operation. It is shrunk once the 929 // during the time-sensitive snapshot operation. It is shrunk once the
889 // actual size is known. 930 // actual size is known.
890 output_snapshot->activity_stack.reserve(stack_slots_); 931 output_snapshot->activity_stack.reserve(stack_slots_);
891 932
892 for (int attempt = 0; attempt < kMaxAttempts; ++attempt) { 933 for (int attempt = 0; attempt < kMaxAttempts; ++attempt) {
893 // Remember the data IDs to ensure nothing is replaced during the snapshot 934 // Remember the data IDs to ensure nothing is replaced during the snapshot
894 // operation. Use "acquire" so that all the non-atomic fields of the 935 // operation. Use "acquire" so that all the non-atomic fields of the
895 // structure are valid (at least at the current moment in time). 936 // structure are valid (at least at the current moment in time).
896 const uint32_t starting_id = 937 const uint32_t starting_id =
897 header_->owner.data_id.load(std::memory_order_acquire); 938 header_->owner.data_id.load(std::memory_order_acquire);
939 const int64_t starting_create_stamp = header_->owner.create_stamp;
898 const int64_t starting_process_id = header_->owner.process_id; 940 const int64_t starting_process_id = header_->owner.process_id;
899 const int64_t starting_thread_id = header_->thread_ref.as_id; 941 const int64_t starting_thread_id = header_->thread_ref.as_id;
900 942
901 // Write a non-zero value to |data_unchanged| so it's possible to detect 943 // Write a non-zero value to |data_unchanged| so it's possible to detect
902 // at the end that nothing has changed since copying the data began. A 944 // at the end that nothing has changed since copying the data began. A
903 // "cst" operation is required to ensure it occurs before everything else. 945 // "cst" operation is required to ensure it occurs before everything else.
904 // Using "cst" memory ordering is relatively expensive but this is only 946 // Using "cst" memory ordering is relatively expensive but this is only
905 // done during analysis so doesn't directly affect the worker threads. 947 // done during analysis so doesn't directly affect the worker threads.
906 header_->data_unchanged.store(1, std::memory_order_seq_cst); 948 header_->data_unchanged.store(1, std::memory_order_seq_cst);
907 949
(...skipping 17 matching lines...) Expand all
925 // it must happen after all the above operations. 967 // it must happen after all the above operations.
926 if (!header_->data_unchanged.load(std::memory_order_seq_cst)) 968 if (!header_->data_unchanged.load(std::memory_order_seq_cst))
927 continue; 969 continue;
928 970
929 // Stack copied. Record it's full depth. 971 // Stack copied. Record it's full depth.
930 output_snapshot->activity_stack_depth = depth; 972 output_snapshot->activity_stack_depth = depth;
931 973
932 // Get the general thread information. 974 // Get the general thread information.
933 output_snapshot->thread_name = 975 output_snapshot->thread_name =
934 std::string(header_->thread_name, sizeof(header_->thread_name) - 1); 976 std::string(header_->thread_name, sizeof(header_->thread_name) - 1);
977 output_snapshot->create_stamp = header_->owner.create_stamp;
935 output_snapshot->thread_id = header_->thread_ref.as_id; 978 output_snapshot->thread_id = header_->thread_ref.as_id;
936 output_snapshot->process_id = header_->owner.process_id; 979 output_snapshot->process_id = header_->owner.process_id;
937 980
938 // All characters of the thread-name buffer were copied so as to not break 981 // All characters of the thread-name buffer were copied so as to not break
939 // if the trailing NUL were missing. Now limit the length if the actual 982 // if the trailing NUL were missing. Now limit the length if the actual
940 // name is shorter. 983 // name is shorter.
941 output_snapshot->thread_name.resize( 984 output_snapshot->thread_name.resize(
942 strlen(output_snapshot->thread_name.c_str())); 985 strlen(output_snapshot->thread_name.c_str()));
943 986
944 // If the data ID has changed then the tracker has exited and the memory 987 // If the data ID has changed then the tracker has exited and the memory
945 // reused by a new one. Try again. 988 // reused by a new one. Try again.
946 if (header_->owner.data_id.load(std::memory_order_seq_cst) != starting_id || 989 if (header_->owner.data_id.load(std::memory_order_seq_cst) != starting_id ||
990 output_snapshot->create_stamp != starting_create_stamp ||
947 output_snapshot->process_id != starting_process_id || 991 output_snapshot->process_id != starting_process_id ||
948 output_snapshot->thread_id != starting_thread_id) { 992 output_snapshot->thread_id != starting_thread_id) {
949 continue; 993 continue;
950 } 994 }
951 995
952 // Only successful if the data is still valid once everything is done since 996 // Only successful if the data is still valid once everything is done since
953 // it's possible for the thread to end somewhere in the middle and all its 997 // it's possible for the thread to end somewhere in the middle and all its
954 // values become garbage. 998 // values become garbage.
955 if (!IsValid()) 999 if (!IsValid())
956 return false; 1000 return false;
(...skipping 17 matching lines...) Expand all
974 } 1018 }
975 1019
976 // Too many attempts. 1020 // Too many attempts.
977 return false; 1021 return false;
978 } 1022 }
979 1023
980 const void* ThreadActivityTracker::GetBaseAddress() { 1024 const void* ThreadActivityTracker::GetBaseAddress() {
981 return header_; 1025 return header_;
982 } 1026 }
983 1027
984 void ThreadActivityTracker::SetOwningProcessIdForTesting(ProcessId pid, 1028 void ThreadActivityTracker::SetOwningProcessIdForTesting(int64_t pid,
985 int64_t stamp) { 1029 int64_t stamp) {
986 header_->owner.SetOwningProcessIdForTesting(pid, stamp); 1030 header_->owner.SetOwningProcessIdForTesting(pid, stamp);
987 } 1031 }
988 1032
989 // static 1033 // static
990 bool ThreadActivityTracker::GetOwningProcessId(const void* memory, 1034 bool ThreadActivityTracker::GetOwningProcessId(const void* memory,
991 ProcessId* out_id, 1035 int64_t* out_id,
992 int64_t* out_stamp) { 1036 int64_t* out_stamp) {
993 const Header* header = reinterpret_cast<const Header*>(memory); 1037 const Header* header = reinterpret_cast<const Header*>(memory);
994 return OwningProcess::GetOwningProcessId(&header->owner, out_id, out_stamp); 1038 return OwningProcess::GetOwningProcessId(&header->owner, out_id, out_stamp);
995 } 1039 }
996 1040
997 // static 1041 // static
998 size_t ThreadActivityTracker::SizeForStackDepth(int stack_depth) { 1042 size_t ThreadActivityTracker::SizeForStackDepth(int stack_depth) {
999 return static_cast<size_t>(stack_depth) * sizeof(Activity) + sizeof(Header); 1043 return static_cast<size_t>(stack_depth) * sizeof(Activity) + sizeof(Header);
1000 } 1044 }
1001 1045
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
1172 user_data_ = 1216 user_data_ =
1173 tracker_->GetUserData(activity_id_, &global->user_data_allocator_); 1217 tracker_->GetUserData(activity_id_, &global->user_data_allocator_);
1174 } else { 1218 } else {
1175 user_data_ = MakeUnique<ActivityUserData>(); 1219 user_data_ = MakeUnique<ActivityUserData>();
1176 } 1220 }
1177 } 1221 }
1178 return *user_data_; 1222 return *user_data_;
1179 } 1223 }
1180 1224
1181 GlobalActivityTracker::ThreadSafeUserData::ThreadSafeUserData(void* memory, 1225 GlobalActivityTracker::ThreadSafeUserData::ThreadSafeUserData(void* memory,
1182 size_t size) 1226 size_t size,
1183 : ActivityUserData(memory, size) {} 1227 int64_t pid)
1228 : ActivityUserData(memory, size, pid) {}
1184 1229
1185 GlobalActivityTracker::ThreadSafeUserData::~ThreadSafeUserData() {} 1230 GlobalActivityTracker::ThreadSafeUserData::~ThreadSafeUserData() {}
1186 1231
1187 void GlobalActivityTracker::ThreadSafeUserData::Set(StringPiece name, 1232 void GlobalActivityTracker::ThreadSafeUserData::Set(StringPiece name,
1188 ValueType type, 1233 ValueType type,
1189 const void* memory, 1234 const void* memory,
1190 size_t size) { 1235 size_t size) {
1191 AutoLock lock(data_lock_); 1236 AutoLock lock(data_lock_);
1192 ActivityUserData::Set(name, type, memory, size); 1237 ActivityUserData::Set(name, type, memory, size);
1193 } 1238 }
1194 1239
1195 GlobalActivityTracker::ManagedActivityTracker::ManagedActivityTracker( 1240 GlobalActivityTracker::ManagedActivityTracker::ManagedActivityTracker(
1196 PersistentMemoryAllocator::Reference mem_reference, 1241 PersistentMemoryAllocator::Reference mem_reference,
1197 void* base, 1242 void* base,
1198 size_t size) 1243 size_t size)
1199 : ThreadActivityTracker(base, size), 1244 : ThreadActivityTracker(base, size),
1200 mem_reference_(mem_reference), 1245 mem_reference_(mem_reference),
1201 mem_base_(base) {} 1246 mem_base_(base) {}
1202 1247
1203 GlobalActivityTracker::ManagedActivityTracker::~ManagedActivityTracker() { 1248 GlobalActivityTracker::ManagedActivityTracker::~ManagedActivityTracker() {
1204 // The global |g_tracker_| must point to the owner of this class since all 1249 // The global |g_tracker_| must point to the owner of this class since all
1205 // objects of this type must be destructed before |g_tracker_| can be changed 1250 // objects of this type must be destructed before |g_tracker_| can be changed
1206 // (something that only occurs in tests). 1251 // (something that only occurs in tests).
1207 DCHECK(g_tracker_); 1252 DCHECK(g_tracker_);
1208 GlobalActivityTracker::Get()->ReturnTrackerMemory(this); 1253 GlobalActivityTracker::Get()->ReturnTrackerMemory(this);
1209 } 1254 }
1210 1255
1211 void GlobalActivityTracker::CreateWithAllocator( 1256 void GlobalActivityTracker::CreateWithAllocator(
1212 std::unique_ptr<PersistentMemoryAllocator> allocator, 1257 std::unique_ptr<PersistentMemoryAllocator> allocator,
1213 int stack_depth) { 1258 int stack_depth,
1259 int64_t process_id) {
1214 // There's no need to do anything with the result. It is self-managing. 1260 // There's no need to do anything with the result. It is self-managing.
1215 GlobalActivityTracker* global_tracker = 1261 GlobalActivityTracker* global_tracker =
1216 new GlobalActivityTracker(std::move(allocator), stack_depth); 1262 new GlobalActivityTracker(std::move(allocator), stack_depth, process_id);
1217 // Create a tracker for this thread since it is known. 1263 // Create a tracker for this thread since it is known.
1218 global_tracker->CreateTrackerForCurrentThread(); 1264 global_tracker->CreateTrackerForCurrentThread();
1219 } 1265 }
1220 1266
1221 #if !defined(OS_NACL) 1267 #if !defined(OS_NACL)
1222 // static 1268 // static
1223 void GlobalActivityTracker::CreateWithFile(const FilePath& file_path, 1269 void GlobalActivityTracker::CreateWithFile(const FilePath& file_path,
1224 size_t size, 1270 size_t size,
1225 uint64_t id, 1271 uint64_t id,
1226 StringPiece name, 1272 StringPiece name,
1227 int stack_depth) { 1273 int stack_depth) {
1228 DCHECK(!file_path.empty()); 1274 DCHECK(!file_path.empty());
1229 DCHECK_GE(static_cast<uint64_t>(std::numeric_limits<int64_t>::max()), size); 1275 DCHECK_GE(static_cast<uint64_t>(std::numeric_limits<int64_t>::max()), size);
1230 1276
1231 // Create and map the file into memory and make it globally available. 1277 // Create and map the file into memory and make it globally available.
1232 std::unique_ptr<MemoryMappedFile> mapped_file(new MemoryMappedFile()); 1278 std::unique_ptr<MemoryMappedFile> mapped_file(new MemoryMappedFile());
1233 bool success = 1279 bool success =
1234 mapped_file->Initialize(File(file_path, 1280 mapped_file->Initialize(File(file_path,
1235 File::FLAG_CREATE_ALWAYS | File::FLAG_READ | 1281 File::FLAG_CREATE_ALWAYS | File::FLAG_READ |
1236 File::FLAG_WRITE | File::FLAG_SHARE_DELETE), 1282 File::FLAG_WRITE | File::FLAG_SHARE_DELETE),
1237 {0, static_cast<int64_t>(size)}, 1283 {0, static_cast<int64_t>(size)},
1238 MemoryMappedFile::READ_WRITE_EXTEND); 1284 MemoryMappedFile::READ_WRITE_EXTEND);
1239 DCHECK(success); 1285 DCHECK(success);
1240 CreateWithAllocator(MakeUnique<FilePersistentMemoryAllocator>( 1286 CreateWithAllocator(MakeUnique<FilePersistentMemoryAllocator>(
1241 std::move(mapped_file), size, id, name, false), 1287 std::move(mapped_file), size, id, name, false),
1242 stack_depth); 1288 stack_depth, 0);
1243 } 1289 }
1244 #endif // !defined(OS_NACL) 1290 #endif // !defined(OS_NACL)
1245 1291
1246 // static 1292 // static
1247 void GlobalActivityTracker::CreateWithLocalMemory(size_t size, 1293 void GlobalActivityTracker::CreateWithLocalMemory(size_t size,
1248 uint64_t id, 1294 uint64_t id,
1249 StringPiece name, 1295 StringPiece name,
1250 int stack_depth) { 1296 int stack_depth,
1297 int64_t process_id) {
1251 CreateWithAllocator( 1298 CreateWithAllocator(
1252 MakeUnique<LocalPersistentMemoryAllocator>(size, id, name), stack_depth); 1299 MakeUnique<LocalPersistentMemoryAllocator>(size, id, name), stack_depth,
1300 process_id);
1253 } 1301 }
1254 1302
1303 // static
1304 void GlobalActivityTracker::SetForTesting(
1305 std::unique_ptr<GlobalActivityTracker> tracker) {
1306 CHECK(!subtle::NoBarrier_Load(&g_tracker_));
1307 subtle::Release_Store(&g_tracker_,
1308 reinterpret_cast<uintptr_t>(tracker.release()));
1309 }
1310
1311 // static
1312 std::unique_ptr<GlobalActivityTracker>
1313 GlobalActivityTracker::ReleaseForTesting() {
1314 GlobalActivityTracker* tracker = Get();
1315 if (!tracker)
1316 return nullptr;
1317
1318 // Thread trackers assume that the global tracker is present for some
1319 // operations so ensure that there aren't any.
1320 tracker->ReleaseTrackerForCurrentThreadForTesting();
1321 DCHECK_EQ(0, tracker->thread_tracker_count_.load(std::memory_order_relaxed));
1322
1323 subtle::Release_Store(&g_tracker_, 0);
1324 return WrapUnique(tracker);
1325 };
1326
1255 ThreadActivityTracker* GlobalActivityTracker::CreateTrackerForCurrentThread() { 1327 ThreadActivityTracker* GlobalActivityTracker::CreateTrackerForCurrentThread() {
1256 DCHECK(!this_thread_tracker_.Get()); 1328 DCHECK(!this_thread_tracker_.Get());
1257 1329
1258 PersistentMemoryAllocator::Reference mem_reference; 1330 PersistentMemoryAllocator::Reference mem_reference;
1259 1331
1260 { 1332 {
1261 base::AutoLock autolock(thread_tracker_allocator_lock_); 1333 base::AutoLock autolock(thread_tracker_allocator_lock_);
1262 mem_reference = thread_tracker_allocator_.GetObjectReference(); 1334 mem_reference = thread_tracker_allocator_.GetObjectReference();
1263 } 1335 }
1264 1336
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1301 int old_count = thread_tracker_count_.fetch_add(1, std::memory_order_relaxed); 1373 int old_count = thread_tracker_count_.fetch_add(1, std::memory_order_relaxed);
1302 1374
1303 UMA_HISTOGRAM_ENUMERATION("ActivityTracker.ThreadTrackers.Count", 1375 UMA_HISTOGRAM_ENUMERATION("ActivityTracker.ThreadTrackers.Count",
1304 old_count + 1, kMaxThreadCount); 1376 old_count + 1, kMaxThreadCount);
1305 return tracker; 1377 return tracker;
1306 } 1378 }
1307 1379
1308 void GlobalActivityTracker::ReleaseTrackerForCurrentThreadForTesting() { 1380 void GlobalActivityTracker::ReleaseTrackerForCurrentThreadForTesting() {
1309 ThreadActivityTracker* tracker = 1381 ThreadActivityTracker* tracker =
1310 reinterpret_cast<ThreadActivityTracker*>(this_thread_tracker_.Get()); 1382 reinterpret_cast<ThreadActivityTracker*>(this_thread_tracker_.Get());
1311 if (tracker) 1383 if (tracker) {
1384 this_thread_tracker_.Set(nullptr);
1312 delete tracker; 1385 delete tracker;
1386 }
1313 } 1387 }
1314 1388
1315 void GlobalActivityTracker::SetBackgroundTaskRunner( 1389 void GlobalActivityTracker::SetBackgroundTaskRunner(
1316 const scoped_refptr<TaskRunner>& runner) { 1390 const scoped_refptr<TaskRunner>& runner) {
1317 AutoLock lock(global_tracker_lock_); 1391 AutoLock lock(global_tracker_lock_);
1318 background_task_runner_ = runner; 1392 background_task_runner_ = runner;
1319 } 1393 }
1320 1394
1321 void GlobalActivityTracker::SetProcessExitCallback( 1395 void GlobalActivityTracker::SetProcessExitCallback(
1322 ProcessExitCallback callback) { 1396 ProcessExitCallback callback) {
1323 AutoLock lock(global_tracker_lock_); 1397 AutoLock lock(global_tracker_lock_);
1324 process_exit_callback_ = callback; 1398 process_exit_callback_ = callback;
1325 } 1399 }
1326 1400
1327 void GlobalActivityTracker::RecordProcessLaunch( 1401 void GlobalActivityTracker::RecordProcessLaunch(
1328 ProcessId process_id, 1402 ProcessId process_id,
1329 const FilePath::StringType& cmd) { 1403 const FilePath::StringType& cmd) {
1330 DCHECK_NE(GetCurrentProcId(), process_id); 1404 const int64_t pid = process_id;
1405 DCHECK_NE(GetProcessId(), pid);
1406 DCHECK_NE(0, pid);
1331 1407
1332 base::AutoLock lock(global_tracker_lock_); 1408 base::AutoLock lock(global_tracker_lock_);
1333 if (base::ContainsKey(known_processes_, process_id)) { 1409 if (base::ContainsKey(known_processes_, pid)) {
1334 // TODO(bcwhite): Measure this in UMA. 1410 // TODO(bcwhite): Measure this in UMA.
1335 NOTREACHED() << "Process #" << process_id 1411 NOTREACHED() << "Process #" << process_id
1336 << " was previously recorded as \"launched\"" 1412 << " was previously recorded as \"launched\""
1337 << " with no corresponding exit."; 1413 << " with no corresponding exit.";
1338 known_processes_.erase(process_id); 1414 known_processes_.erase(pid);
1339 } 1415 }
1340 1416
1341 #if defined(OS_WIN) 1417 #if defined(OS_WIN)
1342 known_processes_.insert(std::make_pair(process_id, UTF16ToUTF8(cmd))); 1418 known_processes_.insert(std::make_pair(pid, UTF16ToUTF8(cmd)));
1343 #else 1419 #else
1344 known_processes_.insert(std::make_pair(process_id, cmd)); 1420 known_processes_.insert(std::make_pair(pid, cmd));
1345 #endif 1421 #endif
1346 } 1422 }
1347 1423
1348 void GlobalActivityTracker::RecordProcessLaunch( 1424 void GlobalActivityTracker::RecordProcessLaunch(
1349 ProcessId process_id, 1425 ProcessId process_id,
1350 const FilePath::StringType& exe, 1426 const FilePath::StringType& exe,
1351 const FilePath::StringType& args) { 1427 const FilePath::StringType& args) {
1428 const int64_t pid = process_id;
1352 if (exe.find(FILE_PATH_LITERAL(" "))) { 1429 if (exe.find(FILE_PATH_LITERAL(" "))) {
1353 RecordProcessLaunch(process_id, 1430 RecordProcessLaunch(pid, FilePath::StringType(FILE_PATH_LITERAL("\"")) +
1354 FilePath::StringType(FILE_PATH_LITERAL("\"")) + exe + 1431 exe + FILE_PATH_LITERAL("\" ") + args);
1355 FILE_PATH_LITERAL("\" ") + args);
1356 } else { 1432 } else {
1357 RecordProcessLaunch(process_id, exe + FILE_PATH_LITERAL(' ') + args); 1433 RecordProcessLaunch(pid, exe + FILE_PATH_LITERAL(' ') + args);
1358 } 1434 }
1359 } 1435 }
1360 1436
1361 void GlobalActivityTracker::RecordProcessExit(ProcessId process_id, 1437 void GlobalActivityTracker::RecordProcessExit(ProcessId process_id,
1362 int exit_code) { 1438 int exit_code) {
1363 DCHECK_NE(GetCurrentProcId(), process_id); 1439 const int64_t pid = process_id;
1440 DCHECK_NE(GetProcessId(), pid);
1441 DCHECK_NE(0, pid);
1364 1442
1365 scoped_refptr<TaskRunner> task_runner; 1443 scoped_refptr<TaskRunner> task_runner;
1366 std::string command_line; 1444 std::string command_line;
1367 { 1445 {
1368 base::AutoLock lock(global_tracker_lock_); 1446 base::AutoLock lock(global_tracker_lock_);
1369 task_runner = background_task_runner_; 1447 task_runner = background_task_runner_;
1370 auto found = known_processes_.find(process_id); 1448 auto found = known_processes_.find(pid);
1371 if (found != known_processes_.end()) { 1449 if (found != known_processes_.end()) {
1372 command_line = std::move(found->second); 1450 command_line = std::move(found->second);
1373 known_processes_.erase(found); 1451 known_processes_.erase(found);
1374 } else { 1452 } else {
1375 DLOG(ERROR) << "Recording exit of unknown process #" << process_id; 1453 DLOG(ERROR) << "Recording exit of unknown process #" << process_id;
1376 } 1454 }
1377 } 1455 }
1378 1456
1379 // Use the current time to differentiate the process that just exited 1457 // Use the current time to differentiate the process that just exited
1380 // from any that might be created in the future with the same ID. 1458 // from any that might be created in the future with the same ID.
1381 int64_t now_stamp = Time::Now().ToInternalValue(); 1459 int64_t now_stamp = Time::Now().ToInternalValue();
1382 1460
1383 // The persistent allocator is thread-safe so run the iteration and 1461 // The persistent allocator is thread-safe so run the iteration and
1384 // adjustments on a worker thread if one was provided. 1462 // adjustments on a worker thread if one was provided.
1385 if (task_runner && !task_runner->RunsTasksOnCurrentThread()) { 1463 if (task_runner && !task_runner->RunsTasksOnCurrentThread()) {
1386 task_runner->PostTask( 1464 task_runner->PostTask(
1387 FROM_HERE, 1465 FROM_HERE,
1388 Bind(&GlobalActivityTracker::CleanupAfterProcess, Unretained(this), 1466 Bind(&GlobalActivityTracker::CleanupAfterProcess, Unretained(this), pid,
1389 process_id, now_stamp, exit_code, Passed(&command_line))); 1467 now_stamp, exit_code, Passed(&command_line)));
1390 return; 1468 return;
1391 } 1469 }
1392 1470
1393 CleanupAfterProcess(process_id, now_stamp, exit_code, 1471 CleanupAfterProcess(pid, now_stamp, exit_code, std::move(command_line));
1394 std::move(command_line));
1395 } 1472 }
1396 1473
1397 void GlobalActivityTracker::SetProcessPhase(ProcessPhase phase) { 1474 void GlobalActivityTracker::SetProcessPhase(ProcessPhase phase) {
1398 process_data().SetInt(kProcessPhaseDataKey, phase); 1475 process_data().SetInt(kProcessPhaseDataKey, phase);
1399 } 1476 }
1400 1477
1401 void GlobalActivityTracker::CleanupAfterProcess(ProcessId process_id, 1478 void GlobalActivityTracker::CleanupAfterProcess(int64_t process_id,
1402 int64_t exit_stamp, 1479 int64_t exit_stamp,
1403 int exit_code, 1480 int exit_code,
1404 std::string&& command_line) { 1481 std::string&& command_line) {
1405 // The process may not have exited cleanly so its necessary to go through 1482 // The process may not have exited cleanly so its necessary to go through
1406 // all the data structures it may have allocated in the persistent memory 1483 // all the data structures it may have allocated in the persistent memory
1407 // segment and mark them as "released". This will allow them to be reused 1484 // segment and mark them as "released". This will allow them to be reused
1408 // later on. 1485 // later on.
1409 1486
1410 PersistentMemoryAllocator::Iterator iter(allocator_.get()); 1487 PersistentMemoryAllocator::Iterator iter(allocator_.get());
1411 PersistentMemoryAllocator::Reference ref; 1488 PersistentMemoryAllocator::Reference ref;
1412 1489
1413 ProcessExitCallback process_exit_callback; 1490 ProcessExitCallback process_exit_callback;
1414 { 1491 {
1415 AutoLock lock(global_tracker_lock_); 1492 AutoLock lock(global_tracker_lock_);
1416 process_exit_callback = process_exit_callback_; 1493 process_exit_callback = process_exit_callback_;
1417 } 1494 }
1418 if (process_exit_callback) { 1495 if (process_exit_callback) {
1419 // Find the processes user-data record so the process phase can be passed 1496 // Find the processes user-data record so the process phase can be passed
1420 // to the callback. 1497 // to the callback.
1421 ActivityUserData::Snapshot process_data_snapshot; 1498 ActivityUserData::Snapshot process_data_snapshot;
1422 while ((ref = iter.GetNextOfType(kTypeIdProcessDataRecord)) != 0) { 1499 while ((ref = iter.GetNextOfType(kTypeIdProcessDataRecord)) != 0) {
1423 const void* memory = allocator_->GetAsArray<char>( 1500 const void* memory = allocator_->GetAsArray<char>(
1424 ref, kTypeIdProcessDataRecord, PersistentMemoryAllocator::kSizeAny); 1501 ref, kTypeIdProcessDataRecord, PersistentMemoryAllocator::kSizeAny);
1425 ProcessId found_id; 1502 int64_t found_id;
1426 int64_t create_stamp; 1503 int64_t create_stamp;
1427 if (ActivityUserData::GetOwningProcessId(memory, &found_id, 1504 if (ActivityUserData::GetOwningProcessId(memory, &found_id,
1428 &create_stamp)) { 1505 &create_stamp)) {
1429 if (found_id == process_id && create_stamp < exit_stamp) { 1506 if (found_id == process_id && create_stamp < exit_stamp) {
1430 const ActivityUserData process_data(const_cast<void*>(memory), 1507 const ActivityUserData process_data(const_cast<void*>(memory),
1431 allocator_->GetAllocSize(ref)); 1508 allocator_->GetAllocSize(ref));
1432 process_data.CreateSnapshot(&process_data_snapshot); 1509 process_data.CreateSnapshot(&process_data_snapshot);
1433 break; // No need to look for any others. 1510 break; // No need to look for any others.
1434 } 1511 }
1435 } 1512 }
(...skipping 16 matching lines...) Expand all
1452 // Find all allocations associated with the exited process and free them. 1529 // Find all allocations associated with the exited process and free them.
1453 uint32_t type; 1530 uint32_t type;
1454 while ((ref = iter.GetNext(&type)) != 0) { 1531 while ((ref = iter.GetNext(&type)) != 0) {
1455 switch (type) { 1532 switch (type) {
1456 case kTypeIdActivityTracker: 1533 case kTypeIdActivityTracker:
1457 case kTypeIdUserDataRecord: 1534 case kTypeIdUserDataRecord:
1458 case kTypeIdProcessDataRecord: 1535 case kTypeIdProcessDataRecord:
1459 case ModuleInfoRecord::kPersistentTypeId: { 1536 case ModuleInfoRecord::kPersistentTypeId: {
1460 const void* memory = allocator_->GetAsArray<char>( 1537 const void* memory = allocator_->GetAsArray<char>(
1461 ref, type, PersistentMemoryAllocator::kSizeAny); 1538 ref, type, PersistentMemoryAllocator::kSizeAny);
1462 ProcessId found_id; 1539 int64_t found_id;
1463 int64_t create_stamp; 1540 int64_t create_stamp;
1464 1541
1465 // By convention, the OwningProcess structure is always the first 1542 // By convention, the OwningProcess structure is always the first
1466 // field of the structure so there's no need to handle all the 1543 // field of the structure so there's no need to handle all the
1467 // cases separately. 1544 // cases separately.
1468 if (OwningProcess::GetOwningProcessId(memory, &found_id, 1545 if (OwningProcess::GetOwningProcessId(memory, &found_id,
1469 &create_stamp)) { 1546 &create_stamp)) {
1470 // Only change the type to be "free" if the process ID matches and 1547 // Only change the type to be "free" if the process ID matches and
1471 // the creation time is before the exit time (so PID re-use doesn't 1548 // the creation time is before the exit time (so PID re-use doesn't
1472 // cause the erasure of something that is in-use). Memory is cleared 1549 // cause the erasure of something that is in-use). Memory is cleared
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1520 } 1597 }
1521 1598
1522 void GlobalActivityTracker::RecordFieldTrial(const std::string& trial_name, 1599 void GlobalActivityTracker::RecordFieldTrial(const std::string& trial_name,
1523 StringPiece group_name) { 1600 StringPiece group_name) {
1524 const std::string key = std::string("FieldTrial.") + trial_name; 1601 const std::string key = std::string("FieldTrial.") + trial_name;
1525 global_data_.SetString(key, group_name); 1602 global_data_.SetString(key, group_name);
1526 } 1603 }
1527 1604
1528 GlobalActivityTracker::GlobalActivityTracker( 1605 GlobalActivityTracker::GlobalActivityTracker(
1529 std::unique_ptr<PersistentMemoryAllocator> allocator, 1606 std::unique_ptr<PersistentMemoryAllocator> allocator,
1530 int stack_depth) 1607 int stack_depth,
1608 int64_t process_id)
1531 : allocator_(std::move(allocator)), 1609 : allocator_(std::move(allocator)),
1532 stack_memory_size_(ThreadActivityTracker::SizeForStackDepth(stack_depth)), 1610 stack_memory_size_(ThreadActivityTracker::SizeForStackDepth(stack_depth)),
1611 process_id_(process_id == 0 ? GetCurrentProcId() : process_id),
1533 this_thread_tracker_(&OnTLSDestroy), 1612 this_thread_tracker_(&OnTLSDestroy),
1534 thread_tracker_count_(0), 1613 thread_tracker_count_(0),
1535 thread_tracker_allocator_(allocator_.get(), 1614 thread_tracker_allocator_(allocator_.get(),
1536 kTypeIdActivityTracker, 1615 kTypeIdActivityTracker,
1537 kTypeIdActivityTrackerFree, 1616 kTypeIdActivityTrackerFree,
1538 stack_memory_size_, 1617 stack_memory_size_,
1539 kCachedThreadMemories, 1618 kCachedThreadMemories,
1540 /*make_iterable=*/true), 1619 /*make_iterable=*/true),
1541 user_data_allocator_(allocator_.get(), 1620 user_data_allocator_(allocator_.get(),
1542 kTypeIdUserDataRecord, 1621 kTypeIdUserDataRecord,
1543 kTypeIdUserDataRecordFree, 1622 kTypeIdUserDataRecordFree,
1544 kUserDataSize, 1623 kUserDataSize,
1545 kCachedUserDataMemories, 1624 kCachedUserDataMemories,
1546 /*make_iterable=*/true), 1625 /*make_iterable=*/true),
1547 process_data_(allocator_->GetAsArray<char>( 1626 process_data_(allocator_->GetAsArray<char>(
1548 AllocateFrom(allocator_.get(), 1627 AllocateFrom(allocator_.get(),
1549 kTypeIdProcessDataRecordFree, 1628 kTypeIdProcessDataRecordFree,
1550 kProcessDataSize, 1629 kProcessDataSize,
1551 kTypeIdProcessDataRecord), 1630 kTypeIdProcessDataRecord),
1552 kTypeIdProcessDataRecord, 1631 kTypeIdProcessDataRecord,
1553 kProcessDataSize), 1632 kProcessDataSize),
1554 kProcessDataSize), 1633 kProcessDataSize,
1634 process_id_),
1555 global_data_( 1635 global_data_(
1556 allocator_->GetAsArray<char>( 1636 allocator_->GetAsArray<char>(
1557 allocator_->Allocate(kGlobalDataSize, kTypeIdGlobalDataRecord), 1637 allocator_->Allocate(kGlobalDataSize, kTypeIdGlobalDataRecord),
1558 kTypeIdGlobalDataRecord, 1638 kTypeIdGlobalDataRecord,
1559 kGlobalDataSize), 1639 kGlobalDataSize),
1560 kGlobalDataSize) { 1640 kGlobalDataSize,
1561 // Ensure the passed memory is valid and empty (iterator finds nothing). 1641 process_id_) {
1562 uint32_t type; 1642 DCHECK_NE(0, process_id_);
1563 DCHECK(!PersistentMemoryAllocator::Iterator(allocator_.get()).GetNext(&type));
1564 1643
1565 // Ensure that there is no other global object and then make this one such. 1644 // Ensure that there is no other global object and then make this one such.
1566 DCHECK(!g_tracker_); 1645 DCHECK(!g_tracker_);
1567 subtle::Release_Store(&g_tracker_, reinterpret_cast<uintptr_t>(this)); 1646 subtle::Release_Store(&g_tracker_, reinterpret_cast<uintptr_t>(this));
1568 1647
1569 // The data records must be iterable in order to be found by an analyzer. 1648 // The data records must be iterable in order to be found by an analyzer.
1570 allocator_->MakeIterable(allocator_->GetAsReference( 1649 allocator_->MakeIterable(allocator_->GetAsReference(
1571 process_data_.GetBaseAddress(), kTypeIdProcessDataRecord)); 1650 process_data_.GetBaseAddress(), kTypeIdProcessDataRecord));
1572 allocator_->MakeIterable(allocator_->GetAsReference( 1651 allocator_->MakeIterable(allocator_->GetAsReference(
1573 global_data_.GetBaseAddress(), kTypeIdGlobalDataRecord)); 1652 global_data_.GetBaseAddress(), kTypeIdGlobalDataRecord));
1574 1653
1575 // Note that this process has launched. 1654 // Note that this process has launched.
1576 SetProcessPhase(PROCESS_LAUNCHED); 1655 SetProcessPhase(PROCESS_LAUNCHED);
1577 1656
1578 // Fetch and record all activated field trials. 1657 // Fetch and record all activated field trials.
1579 FieldTrial::ActiveGroups active_groups; 1658 FieldTrial::ActiveGroups active_groups;
1580 FieldTrialList::GetActiveFieldTrialGroups(&active_groups); 1659 FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
1581 for (auto& group : active_groups) 1660 for (auto& group : active_groups)
1582 RecordFieldTrial(group.trial_name, group.group_name); 1661 RecordFieldTrial(group.trial_name, group.group_name);
1583 } 1662 }
1584 1663
1585 GlobalActivityTracker::~GlobalActivityTracker() { 1664 GlobalActivityTracker::~GlobalActivityTracker() {
1586 DCHECK_EQ(Get(), this); 1665 DCHECK(Get() == nullptr || Get() == this);
1587 DCHECK_EQ(0, thread_tracker_count_.load(std::memory_order_relaxed)); 1666 DCHECK_EQ(0, thread_tracker_count_.load(std::memory_order_relaxed));
1588 subtle::Release_Store(&g_tracker_, 0); 1667 subtle::Release_Store(&g_tracker_, 0);
1589 } 1668 }
1590 1669
1591 void GlobalActivityTracker::ReturnTrackerMemory( 1670 void GlobalActivityTracker::ReturnTrackerMemory(
1592 ManagedActivityTracker* tracker) { 1671 ManagedActivityTracker* tracker) {
1593 PersistentMemoryAllocator::Reference mem_reference = tracker->mem_reference_; 1672 PersistentMemoryAllocator::Reference mem_reference = tracker->mem_reference_;
1594 void* mem_base = tracker->mem_base_; 1673 void* mem_base = tracker->mem_base_;
1595 DCHECK(mem_reference); 1674 DCHECK(mem_reference);
1596 DCHECK(mem_base); 1675 DCHECK(mem_base);
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1704 : GlobalActivityTracker::ScopedThreadActivity( 1783 : GlobalActivityTracker::ScopedThreadActivity(
1705 program_counter, 1784 program_counter,
1706 nullptr, 1785 nullptr,
1707 Activity::ACT_PROCESS_WAIT, 1786 Activity::ACT_PROCESS_WAIT,
1708 ActivityData::ForProcess(process->Pid()), 1787 ActivityData::ForProcess(process->Pid()),
1709 /*lock_allowed=*/true) {} 1788 /*lock_allowed=*/true) {}
1710 #endif 1789 #endif
1711 1790
1712 } // namespace debug 1791 } // namespace debug
1713 } // namespace base 1792 } // namespace base
OLDNEW
« no previous file with comments | « base/debug/activity_tracker.h ('k') | base/debug/activity_tracker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698