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 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |