| 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 "base/debug/stack_trace.h" | 7 #include "base/debug/stack_trace.h" |
| 8 #include "base/files/file.h" | 8 #include "base/files/file.h" |
| 9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
| 10 #include "base/files/memory_mapped_file.h" | 10 #include "base/files/memory_mapped_file.h" |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 | 144 |
| 145 // Add this reference to our "free" cache if there is space. If not, the type | 145 // Add this reference to our "free" cache if there is space. If not, the type |
| 146 // has still been changed to indicate that it is free so this (or another) | 146 // has still been changed to indicate that it is free so this (or another) |
| 147 // thread can find it, albeit more slowly, using the iteration method above. | 147 // thread can find it, albeit more slowly, using the iteration method above. |
| 148 if (cache_used_ < cache_size_) | 148 if (cache_used_ < cache_size_) |
| 149 cache_values_[cache_used_++] = ref; | 149 cache_values_[cache_used_++] = ref; |
| 150 } | 150 } |
| 151 | 151 |
| 152 // static | 152 // static |
| 153 void Activity::FillFrom(Activity* activity, | 153 void Activity::FillFrom(Activity* activity, |
| 154 const void* program_counter, |
| 154 const void* origin, | 155 const void* origin, |
| 155 Type type, | 156 Type type, |
| 156 const ActivityData& data) { | 157 const ActivityData& data) { |
| 157 activity->time_internal = base::TimeTicks::Now().ToInternalValue(); | 158 activity->time_internal = base::TimeTicks::Now().ToInternalValue(); |
| 159 activity->calling_address = reinterpret_cast<uintptr_t>(program_counter); |
| 158 activity->origin_address = reinterpret_cast<uintptr_t>(origin); | 160 activity->origin_address = reinterpret_cast<uintptr_t>(origin); |
| 159 activity->activity_type = type; | 161 activity->activity_type = type; |
| 160 activity->data = data; | 162 activity->data = data; |
| 161 | 163 |
| 162 #if defined(SYZYASAN) | 164 #if defined(SYZYASAN) |
| 163 // Create a stacktrace from the current location and get the addresses. | 165 // Create a stacktrace from the current location and get the addresses. |
| 164 StackTrace stack_trace; | 166 StackTrace stack_trace; |
| 165 size_t stack_depth; | 167 size_t stack_depth; |
| 166 const void* const* stack_addrs = stack_trace.Addresses(&stack_depth); | 168 const void* const* stack_addrs = stack_trace.Addresses(&stack_depth); |
| 167 // Copy the stack addresses, ignoring the first one (here). | 169 // Copy the stack addresses, ignoring the first one (here). |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 DCHECK(IsValid()); | 304 DCHECK(IsValid()); |
| 303 } else { | 305 } else { |
| 304 // This is a file with existing data. Perform basic consistency checks. | 306 // This is a file with existing data. Perform basic consistency checks. |
| 305 valid_ = true; | 307 valid_ = true; |
| 306 valid_ = IsValid(); | 308 valid_ = IsValid(); |
| 307 } | 309 } |
| 308 } | 310 } |
| 309 | 311 |
| 310 ThreadActivityTracker::~ThreadActivityTracker() {} | 312 ThreadActivityTracker::~ThreadActivityTracker() {} |
| 311 | 313 |
| 312 void ThreadActivityTracker::PushActivity(const void* origin, | 314 void ThreadActivityTracker::PushActivity(const void* program_counter, |
| 315 const void* origin, |
| 313 Activity::Type type, | 316 Activity::Type type, |
| 314 const ActivityData& data) { | 317 const ActivityData& data) { |
| 315 // A thread-checker creates a lock to check the thread-id which means | 318 // A thread-checker creates a lock to check the thread-id which means |
| 316 // re-entry into this code if lock acquisitions are being tracked. | 319 // re-entry into this code if lock acquisitions are being tracked. |
| 317 DCHECK(type == Activity::ACT_LOCK_ACQUIRE || | 320 DCHECK(type == Activity::ACT_LOCK_ACQUIRE || |
| 318 thread_checker_.CalledOnValidThread()); | 321 thread_checker_.CalledOnValidThread()); |
| 319 | 322 |
| 320 // Get the current depth of the stack. No access to other memory guarded | 323 // Get the current depth of the stack. No access to other memory guarded |
| 321 // by this variable is done here so a "relaxed" load is acceptable. | 324 // by this variable is done here so a "relaxed" load is acceptable. |
| 322 uint32_t depth = header_->current_depth.load(std::memory_order_relaxed); | 325 uint32_t depth = header_->current_depth.load(std::memory_order_relaxed); |
| 323 | 326 |
| 324 // Handle the case where the stack depth has exceeded the storage capacity. | 327 // Handle the case where the stack depth has exceeded the storage capacity. |
| 325 // Extra entries will be lost leaving only the base of the stack. | 328 // Extra entries will be lost leaving only the base of the stack. |
| 326 if (depth >= stack_slots_) { | 329 if (depth >= stack_slots_) { |
| 327 // Since no other threads modify the data, no compare/exchange is needed. | 330 // Since no other threads modify the data, no compare/exchange is needed. |
| 328 // Since no other memory is being modified, a "relaxed" store is acceptable. | 331 // Since no other memory is being modified, a "relaxed" store is acceptable. |
| 329 header_->current_depth.store(depth + 1, std::memory_order_relaxed); | 332 header_->current_depth.store(depth + 1, std::memory_order_relaxed); |
| 330 return; | 333 return; |
| 331 } | 334 } |
| 332 | 335 |
| 333 // Get a pointer to the next activity and load it. No atomicity is required | 336 // Get a pointer to the next activity and load it. No atomicity is required |
| 334 // here because the memory is known only to this thread. It will be made | 337 // here because the memory is known only to this thread. It will be made |
| 335 // known to other threads once the depth is incremented. | 338 // known to other threads once the depth is incremented. |
| 336 Activity::FillFrom(&stack_[depth], origin, type, data); | 339 Activity::FillFrom(&stack_[depth], program_counter, origin, type, data); |
| 337 | 340 |
| 338 // Save the incremented depth. Because this guards |activity| memory filled | 341 // Save the incremented depth. Because this guards |activity| memory filled |
| 339 // above that may be read by another thread once the recorded depth changes, | 342 // above that may be read by another thread once the recorded depth changes, |
| 340 // a "release" store is required. | 343 // a "release" store is required. |
| 341 header_->current_depth.store(depth + 1, std::memory_order_release); | 344 header_->current_depth.store(depth + 1, std::memory_order_release); |
| 342 } | 345 } |
| 343 | 346 |
| 344 void ThreadActivityTracker::ChangeActivity(Activity::Type type, | 347 void ThreadActivityTracker::ChangeActivity(Activity::Type type, |
| 345 const ActivityData& data) { | 348 const ActivityData& data) { |
| 346 DCHECK(thread_checker_.CalledOnValidThread()); | 349 DCHECK(thread_checker_.CalledOnValidThread()); |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 // Release this memory for re-use at a later time. | 674 // Release this memory for re-use at a later time. |
| 672 base::AutoLock autolock(thread_tracker_allocator_lock_); | 675 base::AutoLock autolock(thread_tracker_allocator_lock_); |
| 673 thread_tracker_allocator_.ReleaseObjectReference(mem_reference); | 676 thread_tracker_allocator_.ReleaseObjectReference(mem_reference); |
| 674 } | 677 } |
| 675 | 678 |
| 676 // static | 679 // static |
| 677 void GlobalActivityTracker::OnTLSDestroy(void* value) { | 680 void GlobalActivityTracker::OnTLSDestroy(void* value) { |
| 678 delete reinterpret_cast<ManagedActivityTracker*>(value); | 681 delete reinterpret_cast<ManagedActivityTracker*>(value); |
| 679 } | 682 } |
| 680 | 683 |
| 681 ScopedActivity::ScopedActivity(const tracked_objects::Location& location, | 684 ScopedActivity::ScopedActivity(const void* program_counter, |
| 682 uint8_t action, | 685 uint8_t action, |
| 683 uint32_t id, | 686 uint32_t id, |
| 684 int32_t info) | 687 int32_t info) |
| 685 : GlobalActivityTracker::ScopedThreadActivity( | 688 : GlobalActivityTracker::ScopedThreadActivity( |
| 686 location.program_counter(), | 689 program_counter, |
| 690 nullptr, |
| 687 static_cast<Activity::Type>(Activity::ACT_GENERIC | action), | 691 static_cast<Activity::Type>(Activity::ACT_GENERIC | action), |
| 688 ActivityData::ForGeneric(id, info), | 692 ActivityData::ForGeneric(id, info), |
| 689 /*lock_allowed=*/true), | 693 /*lock_allowed=*/true), |
| 690 id_(id) { | 694 id_(id) { |
| 691 // The action must not affect the category bits of the activity type. | 695 // The action must not affect the category bits of the activity type. |
| 692 DCHECK_EQ(0, action & Activity::ACT_CATEGORY_MASK); | 696 DCHECK_EQ(0, action & Activity::ACT_CATEGORY_MASK); |
| 693 } | 697 } |
| 694 | 698 |
| 695 void ScopedActivity::ChangeAction(uint8_t action) { | 699 void ScopedActivity::ChangeAction(uint8_t action) { |
| 696 DCHECK_EQ(0, action & Activity::ACT_CATEGORY_MASK); | 700 DCHECK_EQ(0, action & Activity::ACT_CATEGORY_MASK); |
| 697 ChangeTypeAndData(static_cast<Activity::Type>(Activity::ACT_GENERIC | action), | 701 ChangeTypeAndData(static_cast<Activity::Type>(Activity::ACT_GENERIC | action), |
| 698 kNullActivityData); | 702 kNullActivityData); |
| 699 } | 703 } |
| 700 | 704 |
| 701 void ScopedActivity::ChangeInfo(int32_t info) { | 705 void ScopedActivity::ChangeInfo(int32_t info) { |
| 702 ChangeTypeAndData(Activity::ACT_NULL, ActivityData::ForGeneric(id_, info)); | 706 ChangeTypeAndData(Activity::ACT_NULL, ActivityData::ForGeneric(id_, info)); |
| 703 } | 707 } |
| 704 | 708 |
| 705 void ScopedActivity::ChangeActionAndInfo(uint8_t action, int32_t info) { | 709 void ScopedActivity::ChangeActionAndInfo(uint8_t action, int32_t info) { |
| 706 DCHECK_EQ(0, action & Activity::ACT_CATEGORY_MASK); | 710 DCHECK_EQ(0, action & Activity::ACT_CATEGORY_MASK); |
| 707 ChangeTypeAndData(static_cast<Activity::Type>(Activity::ACT_GENERIC | action), | 711 ChangeTypeAndData(static_cast<Activity::Type>(Activity::ACT_GENERIC | action), |
| 708 ActivityData::ForGeneric(id_, info)); | 712 ActivityData::ForGeneric(id_, info)); |
| 709 } | 713 } |
| 710 | 714 |
| 711 ScopedTaskRunActivity::ScopedTaskRunActivity(const base::PendingTask& task) | 715 ScopedTaskRunActivity::ScopedTaskRunActivity( |
| 716 const void* program_counter, |
| 717 const base::PendingTask& task) |
| 712 : GlobalActivityTracker::ScopedThreadActivity( | 718 : GlobalActivityTracker::ScopedThreadActivity( |
| 719 program_counter, |
| 713 task.posted_from.program_counter(), | 720 task.posted_from.program_counter(), |
| 714 Activity::ACT_TASK_RUN, | 721 Activity::ACT_TASK_RUN, |
| 715 ActivityData::ForTask(task.sequence_num), | 722 ActivityData::ForTask(task.sequence_num), |
| 716 /*lock_allowed=*/true) {} | 723 /*lock_allowed=*/true) {} |
| 717 | 724 |
| 718 ScopedLockAcquireActivity::ScopedLockAcquireActivity( | 725 ScopedLockAcquireActivity::ScopedLockAcquireActivity( |
| 726 const void* program_counter, |
| 719 const base::internal::LockImpl* lock) | 727 const base::internal::LockImpl* lock) |
| 720 : GlobalActivityTracker::ScopedThreadActivity( | 728 : GlobalActivityTracker::ScopedThreadActivity( |
| 729 program_counter, |
| 721 nullptr, | 730 nullptr, |
| 722 Activity::ACT_LOCK_ACQUIRE, | 731 Activity::ACT_LOCK_ACQUIRE, |
| 723 ActivityData::ForLock(lock), | 732 ActivityData::ForLock(lock), |
| 724 /*lock_allowed=*/false) {} | 733 /*lock_allowed=*/false) {} |
| 725 | 734 |
| 726 ScopedEventWaitActivity::ScopedEventWaitActivity( | 735 ScopedEventWaitActivity::ScopedEventWaitActivity( |
| 736 const void* program_counter, |
| 727 const base::WaitableEvent* event) | 737 const base::WaitableEvent* event) |
| 728 : GlobalActivityTracker::ScopedThreadActivity( | 738 : GlobalActivityTracker::ScopedThreadActivity( |
| 739 program_counter, |
| 729 nullptr, | 740 nullptr, |
| 730 Activity::ACT_EVENT_WAIT, | 741 Activity::ACT_EVENT_WAIT, |
| 731 ActivityData::ForEvent(event), | 742 ActivityData::ForEvent(event), |
| 732 /*lock_allowed=*/true) {} | 743 /*lock_allowed=*/true) {} |
| 733 | 744 |
| 734 ScopedThreadJoinActivity::ScopedThreadJoinActivity( | 745 ScopedThreadJoinActivity::ScopedThreadJoinActivity( |
| 746 const void* program_counter, |
| 735 const base::PlatformThreadHandle* thread) | 747 const base::PlatformThreadHandle* thread) |
| 736 : GlobalActivityTracker::ScopedThreadActivity( | 748 : GlobalActivityTracker::ScopedThreadActivity( |
| 749 program_counter, |
| 737 nullptr, | 750 nullptr, |
| 738 Activity::ACT_THREAD_JOIN, | 751 Activity::ACT_THREAD_JOIN, |
| 739 ActivityData::ForThread(*thread), | 752 ActivityData::ForThread(*thread), |
| 740 /*lock_allowed=*/true) {} | 753 /*lock_allowed=*/true) {} |
| 741 | 754 |
| 742 #if !defined(OS_NACL) && !defined(OS_IOS) | 755 #if !defined(OS_NACL) && !defined(OS_IOS) |
| 743 ScopedProcessWaitActivity::ScopedProcessWaitActivity( | 756 ScopedProcessWaitActivity::ScopedProcessWaitActivity( |
| 757 const void* program_counter, |
| 744 const base::Process* process) | 758 const base::Process* process) |
| 745 : GlobalActivityTracker::ScopedThreadActivity( | 759 : GlobalActivityTracker::ScopedThreadActivity( |
| 760 program_counter, |
| 746 nullptr, | 761 nullptr, |
| 747 Activity::ACT_PROCESS_WAIT, | 762 Activity::ACT_PROCESS_WAIT, |
| 748 ActivityData::ForProcess(process->Pid()), | 763 ActivityData::ForProcess(process->Pid()), |
| 749 /*lock_allowed=*/true) {} | 764 /*lock_allowed=*/true) {} |
| 750 #endif | 765 #endif |
| 751 | 766 |
| 752 } // namespace debug | 767 } // namespace debug |
| 753 } // namespace base | 768 } // namespace base |
| OLD | NEW |