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 // Activity tracking provides a low-overhead method of collecting information | 5 // Activity tracking provides a low-overhead method of collecting information |
6 // about the state of the application for analysis both while it is running | 6 // about the state of the application for analysis both while it is running |
7 // and after it has terminated unexpectedly. Its primary purpose is to help | 7 // and after it has terminated unexpectedly. Its primary purpose is to help |
8 // locate reasons the browser becomes unresponsive by providing insight into | 8 // locate reasons the browser becomes unresponsive by providing insight into |
9 // what all the various threads and processes are (or were) doing. | 9 // what all the various threads and processes are (or were) doing. |
10 | 10 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
89 uint32_t padding; | 89 uint32_t padding; |
90 int64_t process_id; | 90 int64_t process_id; |
91 int64_t create_stamp; | 91 int64_t create_stamp; |
92 }; | 92 }; |
93 | 93 |
94 // The data associated with an activity is dependent upon the activity type. | 94 // The data associated with an activity is dependent upon the activity type. |
95 // This union defines all of the various fields. All fields must be explicitly | 95 // This union defines all of the various fields. All fields must be explicitly |
96 // sized types to ensure no interoperability problems between 32-bit and | 96 // sized types to ensure no interoperability problems between 32-bit and |
97 // 64-bit systems. | 97 // 64-bit systems. |
98 union ActivityData { | 98 union ActivityData { |
99 // Expected size for 32/64-bit check. | |
100 // TODO(bcwhite): VC2015 doesn't allow statics in unions. Fix when it does. | |
101 // static constexpr size_t kExpectedInstanceSize = 8; | |
102 | |
99 // Generic activities don't have any defined structure. | 103 // Generic activities don't have any defined structure. |
100 struct { | 104 struct { |
101 uint32_t id; // An arbitrary identifier used for association. | 105 uint32_t id; // An arbitrary identifier used for association. |
102 int32_t info; // An arbitrary value used for information purposes. | 106 int32_t info; // An arbitrary value used for information purposes. |
103 } generic; | 107 } generic; |
104 struct { | 108 struct { |
105 uint64_t sequence_id; // The sequence identifier of the posted task. | 109 uint64_t sequence_id; // The sequence identifier of the posted task. |
106 } task; | 110 } task; |
107 struct { | 111 struct { |
108 uint64_t lock_address; // The memory address of the lock object. | 112 uint64_t lock_address; // The memory address of the lock object. |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
265 // Thread activities involve the life management of threads. | 269 // Thread activities involve the life management of threads. |
266 ACT_THREAD = 4 << 4, | 270 ACT_THREAD = 4 << 4, |
267 ACT_THREAD_START = ACT_THREAD, | 271 ACT_THREAD_START = ACT_THREAD, |
268 ACT_THREAD_JOIN, | 272 ACT_THREAD_JOIN, |
269 | 273 |
270 // Process activities involve the life management of processes. | 274 // Process activities involve the life management of processes. |
271 ACT_PROCESS = 5 << 4, | 275 ACT_PROCESS = 5 << 4, |
272 ACT_PROCESS_START = ACT_PROCESS, | 276 ACT_PROCESS_START = ACT_PROCESS, |
273 ACT_PROCESS_WAIT, | 277 ACT_PROCESS_WAIT, |
274 | 278 |
279 // Exception activities indicate the occurence of something unexpected. | |
280 ACT_EXCEPTION = 14 << 4, | |
281 | |
275 // Generic activities are user defined and can be anything. | 282 // Generic activities are user defined and can be anything. |
276 ACT_GENERIC = 15 << 4, | 283 ACT_GENERIC = 15 << 4, |
277 | 284 |
278 // These constants can be used to separate the category and action from | 285 // These constants can be used to separate the category and action from |
279 // a combined activity type. | 286 // a combined activity type. |
280 ACT_CATEGORY_MASK = 0xF << 4, | 287 ACT_CATEGORY_MASK = 0xF << 4, |
281 ACT_ACTION_MASK = 0xF | 288 ACT_ACTION_MASK = 0xF |
282 }; | 289 }; |
283 | 290 |
284 // Internal representation of time. During collection, this is in "ticks" | 291 // Internal representation of time. During collection, this is in "ticks" |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
378 friend class ActivityUserData; | 385 friend class ActivityUserData; |
379 | 386 |
380 ValueType type_; | 387 ValueType type_; |
381 uint64_t short_value_; // Used to hold copy of numbers, etc. | 388 uint64_t short_value_; // Used to hold copy of numbers, etc. |
382 std::string long_value_; // Used to hold copy of raw/string data. | 389 std::string long_value_; // Used to hold copy of raw/string data. |
383 StringPiece ref_value_; // Used to hold reference to external data. | 390 StringPiece ref_value_; // Used to hold reference to external data. |
384 }; | 391 }; |
385 | 392 |
386 using Snapshot = std::map<std::string, TypedValue>; | 393 using Snapshot = std::map<std::string, TypedValue>; |
387 | 394 |
395 ActivityUserData(); | |
388 ActivityUserData(void* memory, size_t size); | 396 ActivityUserData(void* memory, size_t size); |
389 virtual ~ActivityUserData(); | 397 virtual ~ActivityUserData(); |
390 | 398 |
391 // Gets the unique ID number for this user data. If this changes then the | 399 // Gets the unique ID number for this user data. If this changes then the |
392 // contents have been overwritten by another thread. The return value is | 400 // contents have been overwritten by another thread. The return value is |
393 // always non-zero unless it's actually just a data "sink". | 401 // always non-zero unless it's actually just a data "sink". |
394 uint32_t id() const { | 402 uint32_t id() const { |
395 return header_ ? header_->owner.data_id.load(std::memory_order_relaxed) : 0; | 403 return header_ ? header_->owner.data_id.load(std::memory_order_relaxed) : 0; |
396 } | 404 } |
397 | 405 |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
572 int64_t process_id = 0; | 580 int64_t process_id = 0; |
573 int64_t thread_id = 0; | 581 int64_t thread_id = 0; |
574 | 582 |
575 // The current stack of activities that are underway for this thread. It | 583 // The current stack of activities that are underway for this thread. It |
576 // is limited in its maximum size with later entries being left off. | 584 // is limited in its maximum size with later entries being left off. |
577 std::vector<Activity> activity_stack; | 585 std::vector<Activity> activity_stack; |
578 | 586 |
579 // The current total depth of the activity stack, including those later | 587 // The current total depth of the activity stack, including those later |
580 // entries not recorded in the |activity_stack| vector. | 588 // entries not recorded in the |activity_stack| vector. |
581 uint32_t activity_stack_depth = 0; | 589 uint32_t activity_stack_depth = 0; |
590 | |
591 // The last recorded "exception" activity. | |
592 Activity last_exception; | |
582 }; | 593 }; |
583 | 594 |
584 // This is the base class for having the compiler manage an activity on the | 595 // This is the base class for having the compiler manage an activity on the |
585 // tracker's stack. It does nothing but call methods on the passed |tracker| | 596 // tracker's stack. It does nothing but call methods on the passed |tracker| |
586 // if it is not null, making it safe (and cheap) to create these objects | 597 // if it is not null, making it safe (and cheap) to create these objects |
587 // even if activity tracking is not enabled. | 598 // even if activity tracking is not enabled. |
588 class BASE_EXPORT ScopedActivity { | 599 class BASE_EXPORT ScopedActivity { |
589 public: | 600 public: |
590 ScopedActivity(ThreadActivityTracker* tracker, | 601 ScopedActivity(ThreadActivityTracker* tracker, |
591 const void* program_counter, | 602 const void* program_counter, |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
655 ActivityTrackerMemoryAllocator* allocator); | 666 ActivityTrackerMemoryAllocator* allocator); |
656 | 667 |
657 // Returns if there is true use-data associated with a given ActivityId since | 668 // Returns if there is true use-data associated with a given ActivityId since |
658 // it's possible than any returned object is just a sink. | 669 // it's possible than any returned object is just a sink. |
659 bool HasUserData(ActivityId id); | 670 bool HasUserData(ActivityId id); |
660 | 671 |
661 // Release the user-data information for an activity. | 672 // Release the user-data information for an activity. |
662 void ReleaseUserData(ActivityId id, | 673 void ReleaseUserData(ActivityId id, |
663 ActivityTrackerMemoryAllocator* allocator); | 674 ActivityTrackerMemoryAllocator* allocator); |
664 | 675 |
676 // Save an exception. | |
677 void ExceptionActivity(const void* program_counter, | |
manzagop (departed)
2017/03/20 14:29:55
nit: add a verb, eg [Store/Record/Save]ExceptionAc
bcwhite
2017/03/21 12:25:06
Done.
| |
678 const void* origin, | |
679 Activity::Type type, | |
680 const ActivityData& data); | |
681 | |
665 // Returns whether the current data is valid or not. It is not valid if | 682 // Returns whether the current data is valid or not. It is not valid if |
666 // corruption has been detected in the header or other data structures. | 683 // corruption has been detected in the header or other data structures. |
667 bool IsValid() const; | 684 bool IsValid() const; |
668 | 685 |
669 // Gets a copy of the tracker contents for analysis. Returns false if a | 686 // Gets a copy of the tracker contents for analysis. Returns false if a |
670 // snapshot was not possible, perhaps because the data is not valid; the | 687 // snapshot was not possible, perhaps because the data is not valid; the |
671 // contents of |output_snapshot| are undefined in that case. The current | 688 // contents of |output_snapshot| are undefined in that case. The current |
672 // implementation does not support concurrent snapshot operations. | 689 // implementation does not support concurrent snapshot operations. |
673 bool CreateSnapshot(Snapshot* output_snapshot) const; | 690 bool CreateSnapshot(Snapshot* output_snapshot) const; |
674 | 691 |
(...skipping 10 matching lines...) Expand all Loading... | |
685 ProcessId* out_id, | 702 ProcessId* out_id, |
686 int64_t* out_stamp); | 703 int64_t* out_stamp); |
687 | 704 |
688 // Calculates the memory size required for a given stack depth, including | 705 // Calculates the memory size required for a given stack depth, including |
689 // the internal header structure for the stack. | 706 // the internal header structure for the stack. |
690 static size_t SizeForStackDepth(int stack_depth); | 707 static size_t SizeForStackDepth(int stack_depth); |
691 | 708 |
692 private: | 709 private: |
693 friend class ActivityTrackerTest; | 710 friend class ActivityTrackerTest; |
694 | 711 |
712 std::unique_ptr<ActivityUserData> CreateUserDataForActivity( | |
713 Activity* activity, | |
714 ActivityTrackerMemoryAllocator* allocator); | |
715 | |
695 Header* const header_; // Pointer to the Header structure. | 716 Header* const header_; // Pointer to the Header structure. |
696 Activity* const stack_; // The stack of activities. | 717 Activity* const stack_; // The stack of activities. |
697 const uint32_t stack_slots_; // The total number of stack slots. | 718 const uint32_t stack_slots_; // The total number of stack slots. |
698 | 719 |
699 bool valid_ = false; // Tracks whether the data is valid or not. | 720 bool valid_ = false; // Tracks whether the data is valid or not. |
700 | 721 |
701 base::ThreadChecker thread_checker_; | 722 base::ThreadChecker thread_checker_; |
702 | 723 |
703 DISALLOW_COPY_AND_ASSIGN(ThreadActivityTracker); | 724 DISALLOW_COPY_AND_ASSIGN(ThreadActivityTracker); |
704 }; | 725 }; |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
913 const FilePath::StringType& args) { | 934 const FilePath::StringType& args) { |
914 GlobalActivityTracker* tracker = Get(); | 935 GlobalActivityTracker* tracker = Get(); |
915 if (tracker) | 936 if (tracker) |
916 tracker->RecordProcessLaunch(process_id, exe, args); | 937 tracker->RecordProcessLaunch(process_id, exe, args); |
917 } | 938 } |
918 static void RecordProcessExitIfEnabled(ProcessId process_id, int exit_code) { | 939 static void RecordProcessExitIfEnabled(ProcessId process_id, int exit_code) { |
919 GlobalActivityTracker* tracker = Get(); | 940 GlobalActivityTracker* tracker = Get(); |
920 if (tracker) | 941 if (tracker) |
921 tracker->RecordProcessExit(process_id, exit_code); | 942 tracker->RecordProcessExit(process_id, exit_code); |
922 } | 943 } |
944 | |
923 // Sets the "phase" of the current process, useful for knowing what it was | 945 // Sets the "phase" of the current process, useful for knowing what it was |
924 // doing when it last reported. | 946 // doing when it last reported. |
925 void SetProcessPhase(ProcessPhase phase); | 947 void SetProcessPhase(ProcessPhase phase); |
926 static void SetProcessPhaseIfEnabled(ProcessPhase phase) { | 948 static void SetProcessPhaseIfEnabled(ProcessPhase phase) { |
927 GlobalActivityTracker* tracker = Get(); | 949 GlobalActivityTracker* tracker = Get(); |
928 if (tracker) | 950 if (tracker) |
929 tracker->SetProcessPhase(phase); | 951 tracker->SetProcessPhase(phase); |
930 } | 952 } |
931 | 953 |
932 // Records a log message. The current implementation does NOT recycle these | 954 // Records a log message. The current implementation does NOT recycle these |
(...skipping 18 matching lines...) Expand all Loading... | |
951 // this, construction of a GlobalActivityTracker will cause all existing | 973 // this, construction of a GlobalActivityTracker will cause all existing |
952 // active field trials to be fetched and recorded. | 974 // active field trials to be fetched and recorded. |
953 void RecordFieldTrial(const std::string& trial_name, StringPiece group_name); | 975 void RecordFieldTrial(const std::string& trial_name, StringPiece group_name); |
954 static void RecordFieldTrialIfEnabled(const std::string& trial_name, | 976 static void RecordFieldTrialIfEnabled(const std::string& trial_name, |
955 StringPiece group_name) { | 977 StringPiece group_name) { |
956 GlobalActivityTracker* tracker = Get(); | 978 GlobalActivityTracker* tracker = Get(); |
957 if (tracker) | 979 if (tracker) |
958 tracker->RecordFieldTrial(trial_name, group_name); | 980 tracker->RecordFieldTrial(trial_name, group_name); |
959 } | 981 } |
960 | 982 |
983 // Record exception information for the current thread and return space where | |
manzagop (departed)
2017/03/20 14:29:55
No space is returned?
bcwhite
2017/03/21 12:25:06
Done.
| |
984 // additional information may be recorded. | |
985 // TODO(bcwhite): More parameters (space for 4 + 64 bits). | |
986 ALWAYS_INLINE | |
987 void RecordException(const void* origin) { | |
988 return RecordExceptionImpl(::tracked_objects::GetProgramCounter(), origin); | |
989 } | |
990 | |
961 // Accesses the process data record for storing arbitrary key/value pairs. | 991 // Accesses the process data record for storing arbitrary key/value pairs. |
962 // Updates to this are thread-safe. | 992 // Updates to this are thread-safe. |
963 ActivityUserData& process_data() { return process_data_; } | 993 ActivityUserData& process_data() { return process_data_; } |
964 | 994 |
965 // Accesses the global data record for storing arbitrary key/value pairs. | 995 // Accesses the global data record for storing arbitrary key/value pairs. |
966 // Updates to this are thread-safe. | 996 // Updates to this are thread-safe. |
967 ActivityUserData& global_data() { return global_data_; } | 997 ActivityUserData& global_data() { return global_data_; } |
968 | 998 |
969 private: | 999 private: |
970 friend class GlobalActivityAnalyzer; | 1000 friend class GlobalActivityAnalyzer; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1068 // Creates a global tracker using a given persistent-memory |allocator| and | 1098 // Creates a global tracker using a given persistent-memory |allocator| and |
1069 // providing the given |stack_depth| to each thread tracker it manages. The | 1099 // providing the given |stack_depth| to each thread tracker it manages. The |
1070 // created object is activated so tracking has already started upon return. | 1100 // created object is activated so tracking has already started upon return. |
1071 GlobalActivityTracker(std::unique_ptr<PersistentMemoryAllocator> allocator, | 1101 GlobalActivityTracker(std::unique_ptr<PersistentMemoryAllocator> allocator, |
1072 int stack_depth); | 1102 int stack_depth); |
1073 | 1103 |
1074 // Returns the memory used by an activity-tracker managed by this class. | 1104 // Returns the memory used by an activity-tracker managed by this class. |
1075 // It is called during the destruction of a ManagedActivityTracker object. | 1105 // It is called during the destruction of a ManagedActivityTracker object. |
1076 void ReturnTrackerMemory(ManagedActivityTracker* tracker); | 1106 void ReturnTrackerMemory(ManagedActivityTracker* tracker); |
1077 | 1107 |
1108 // Records exception information. | |
1109 void RecordExceptionImpl(const void* pc, const void* origin); | |
1110 | |
1078 // Releases the activity-tracker associcated with thread. It is called | 1111 // Releases the activity-tracker associcated with thread. It is called |
1079 // automatically when a thread is joined and thus there is nothing more to | 1112 // automatically when a thread is joined and thus there is nothing more to |
1080 // be tracked. |value| is a pointer to a ManagedActivityTracker. | 1113 // be tracked. |value| is a pointer to a ManagedActivityTracker. |
1081 static void OnTLSDestroy(void* value); | 1114 static void OnTLSDestroy(void* value); |
1082 | 1115 |
1083 // Does process-exit work. This can be run on any thread. | 1116 // Does process-exit work. This can be run on any thread. |
1084 void CleanupAfterProcess(ProcessId process_id, | 1117 void CleanupAfterProcess(ProcessId process_id, |
1085 int64_t exit_stamp, | 1118 int64_t exit_stamp, |
1086 int exit_code, | 1119 int exit_code, |
1087 std::string&& command_line); | 1120 std::string&& command_line); |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1261 ScopedProcessWaitActivity(const void* program_counter, | 1294 ScopedProcessWaitActivity(const void* program_counter, |
1262 const base::Process* process); | 1295 const base::Process* process); |
1263 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); | 1296 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); |
1264 }; | 1297 }; |
1265 #endif | 1298 #endif |
1266 | 1299 |
1267 } // namespace debug | 1300 } // namespace debug |
1268 } // namespace base | 1301 } // namespace base |
1269 | 1302 |
1270 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ | 1303 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ |
OLD | NEW |