| 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. |
| 109 } lock; | 113 } lock; |
| 110 struct { | 114 struct { |
| 111 uint64_t event_address; // The memory address of the event object. | 115 uint64_t event_address; // The memory address of the event object. |
| 112 } event; | 116 } event; |
| 113 struct { | 117 struct { |
| 114 int64_t thread_id; // A unique identifier for a thread within a process. | 118 int64_t thread_id; // A unique identifier for a thread within a process. |
| 115 } thread; | 119 } thread; |
| 116 struct { | 120 struct { |
| 117 int64_t process_id; // A unique identifier for a process. | 121 int64_t process_id; // A unique identifier for a process. |
| 118 } process; | 122 } process; |
| 123 struct { |
| 124 uint32_t code; // An "exception code" number. |
| 125 } exception; |
| 119 | 126 |
| 120 // These methods create an ActivityData object from the appropriate | 127 // These methods create an ActivityData object from the appropriate |
| 121 // parameters. Objects of this type should always be created this way to | 128 // parameters. Objects of this type should always be created this way to |
| 122 // ensure that no fields remain unpopulated should the set of recorded | 129 // ensure that no fields remain unpopulated should the set of recorded |
| 123 // fields change. They're defined inline where practical because they | 130 // fields change. They're defined inline where practical because they |
| 124 // reduce to loading a small local structure with a few values, roughly | 131 // reduce to loading a small local structure with a few values, roughly |
| 125 // the same as loading all those values into parameters. | 132 // the same as loading all those values into parameters. |
| 126 | 133 |
| 127 static ActivityData ForGeneric(uint32_t id, int32_t info) { | 134 static ActivityData ForGeneric(uint32_t id, int32_t info) { |
| 128 ActivityData data; | 135 ActivityData data; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 154 ActivityData data; | 161 ActivityData data; |
| 155 data.thread.thread_id = id; | 162 data.thread.thread_id = id; |
| 156 return data; | 163 return data; |
| 157 } | 164 } |
| 158 | 165 |
| 159 static ActivityData ForProcess(const int64_t id) { | 166 static ActivityData ForProcess(const int64_t id) { |
| 160 ActivityData data; | 167 ActivityData data; |
| 161 data.process.process_id = id; | 168 data.process.process_id = id; |
| 162 return data; | 169 return data; |
| 163 } | 170 } |
| 171 |
| 172 static ActivityData ForException(const uint32_t code) { |
| 173 ActivityData data; |
| 174 data.exception.code = code; |
| 175 return data; |
| 176 } |
| 164 }; | 177 }; |
| 165 | 178 |
| 166 // A "null" activity-data that can be passed to indicate "do not change". | 179 // A "null" activity-data that can be passed to indicate "do not change". |
| 167 extern const ActivityData kNullActivityData; | 180 extern const ActivityData kNullActivityData; |
| 168 | 181 |
| 169 | 182 |
| 170 // A helper class that is used for managing memory allocations within a | 183 // A helper class that is used for managing memory allocations within a |
| 171 // persistent memory allocator. Instances of this class are NOT thread-safe. | 184 // persistent memory allocator. Instances of this class are NOT thread-safe. |
| 172 // Use from a single thread or protect access with a lock. | 185 // Use from a single thread or protect access with a lock. |
| 173 class BASE_EXPORT ActivityTrackerMemoryAllocator { | 186 class BASE_EXPORT ActivityTrackerMemoryAllocator { |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 // Thread activities involve the life management of threads. | 278 // Thread activities involve the life management of threads. |
| 266 ACT_THREAD = 4 << 4, | 279 ACT_THREAD = 4 << 4, |
| 267 ACT_THREAD_START = ACT_THREAD, | 280 ACT_THREAD_START = ACT_THREAD, |
| 268 ACT_THREAD_JOIN, | 281 ACT_THREAD_JOIN, |
| 269 | 282 |
| 270 // Process activities involve the life management of processes. | 283 // Process activities involve the life management of processes. |
| 271 ACT_PROCESS = 5 << 4, | 284 ACT_PROCESS = 5 << 4, |
| 272 ACT_PROCESS_START = ACT_PROCESS, | 285 ACT_PROCESS_START = ACT_PROCESS, |
| 273 ACT_PROCESS_WAIT, | 286 ACT_PROCESS_WAIT, |
| 274 | 287 |
| 288 // Exception activities indicate the occurence of something unexpected. |
| 289 ACT_EXCEPTION = 14 << 4, |
| 290 |
| 275 // Generic activities are user defined and can be anything. | 291 // Generic activities are user defined and can be anything. |
| 276 ACT_GENERIC = 15 << 4, | 292 ACT_GENERIC = 15 << 4, |
| 277 | 293 |
| 278 // These constants can be used to separate the category and action from | 294 // These constants can be used to separate the category and action from |
| 279 // a combined activity type. | 295 // a combined activity type. |
| 280 ACT_CATEGORY_MASK = 0xF << 4, | 296 ACT_CATEGORY_MASK = 0xF << 4, |
| 281 ACT_ACTION_MASK = 0xF | 297 ACT_ACTION_MASK = 0xF |
| 282 }; | 298 }; |
| 283 | 299 |
| 284 // Internal representation of time. During collection, this is in "ticks" | 300 // 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; | 394 friend class ActivityUserData; |
| 379 | 395 |
| 380 ValueType type_; | 396 ValueType type_; |
| 381 uint64_t short_value_; // Used to hold copy of numbers, etc. | 397 uint64_t short_value_; // Used to hold copy of numbers, etc. |
| 382 std::string long_value_; // Used to hold copy of raw/string data. | 398 std::string long_value_; // Used to hold copy of raw/string data. |
| 383 StringPiece ref_value_; // Used to hold reference to external data. | 399 StringPiece ref_value_; // Used to hold reference to external data. |
| 384 }; | 400 }; |
| 385 | 401 |
| 386 using Snapshot = std::map<std::string, TypedValue>; | 402 using Snapshot = std::map<std::string, TypedValue>; |
| 387 | 403 |
| 404 // Initialize the object either as a "sink" that just accepts and discards |
| 405 // data or an active one that writes to a given (zeroed) memory block. |
| 406 ActivityUserData(); |
| 388 ActivityUserData(void* memory, size_t size); | 407 ActivityUserData(void* memory, size_t size); |
| 389 virtual ~ActivityUserData(); | 408 virtual ~ActivityUserData(); |
| 390 | 409 |
| 391 // Gets the unique ID number for this user data. If this changes then the | 410 // 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 | 411 // contents have been overwritten by another thread. The return value is |
| 393 // always non-zero unless it's actually just a data "sink". | 412 // always non-zero unless it's actually just a data "sink". |
| 394 uint32_t id() const { | 413 uint32_t id() const { |
| 395 return header_ ? header_->owner.data_id.load(std::memory_order_relaxed) : 0; | 414 return header_ ? header_->owner.data_id.load(std::memory_order_relaxed) : 0; |
| 396 } | 415 } |
| 397 | 416 |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 int64_t process_id = 0; | 591 int64_t process_id = 0; |
| 573 int64_t thread_id = 0; | 592 int64_t thread_id = 0; |
| 574 | 593 |
| 575 // The current stack of activities that are underway for this thread. It | 594 // 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. | 595 // is limited in its maximum size with later entries being left off. |
| 577 std::vector<Activity> activity_stack; | 596 std::vector<Activity> activity_stack; |
| 578 | 597 |
| 579 // The current total depth of the activity stack, including those later | 598 // The current total depth of the activity stack, including those later |
| 580 // entries not recorded in the |activity_stack| vector. | 599 // entries not recorded in the |activity_stack| vector. |
| 581 uint32_t activity_stack_depth = 0; | 600 uint32_t activity_stack_depth = 0; |
| 601 |
| 602 // The last recorded "exception" activity. |
| 603 Activity last_exception; |
| 582 }; | 604 }; |
| 583 | 605 |
| 584 // This is the base class for having the compiler manage an activity on the | 606 // 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| | 607 // 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 | 608 // if it is not null, making it safe (and cheap) to create these objects |
| 587 // even if activity tracking is not enabled. | 609 // even if activity tracking is not enabled. |
| 588 class BASE_EXPORT ScopedActivity { | 610 class BASE_EXPORT ScopedActivity { |
| 589 public: | 611 public: |
| 590 ScopedActivity(ThreadActivityTracker* tracker, | 612 ScopedActivity(ThreadActivityTracker* tracker, |
| 591 const void* program_counter, | 613 const void* program_counter, |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 ActivityTrackerMemoryAllocator* allocator); | 677 ActivityTrackerMemoryAllocator* allocator); |
| 656 | 678 |
| 657 // Returns if there is true use-data associated with a given ActivityId since | 679 // 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. | 680 // it's possible than any returned object is just a sink. |
| 659 bool HasUserData(ActivityId id); | 681 bool HasUserData(ActivityId id); |
| 660 | 682 |
| 661 // Release the user-data information for an activity. | 683 // Release the user-data information for an activity. |
| 662 void ReleaseUserData(ActivityId id, | 684 void ReleaseUserData(ActivityId id, |
| 663 ActivityTrackerMemoryAllocator* allocator); | 685 ActivityTrackerMemoryAllocator* allocator); |
| 664 | 686 |
| 687 // Save an exception. |origin| is the location of the exception. |
| 688 void RecordExceptionActivity(const void* program_counter, |
| 689 const void* origin, |
| 690 Activity::Type type, |
| 691 const ActivityData& data); |
| 692 |
| 665 // Returns whether the current data is valid or not. It is not valid if | 693 // 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. | 694 // corruption has been detected in the header or other data structures. |
| 667 bool IsValid() const; | 695 bool IsValid() const; |
| 668 | 696 |
| 669 // Gets a copy of the tracker contents for analysis. Returns false if a | 697 // 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 | 698 // snapshot was not possible, perhaps because the data is not valid; the |
| 671 // contents of |output_snapshot| are undefined in that case. The current | 699 // contents of |output_snapshot| are undefined in that case. The current |
| 672 // implementation does not support concurrent snapshot operations. | 700 // implementation does not support concurrent snapshot operations. |
| 673 bool CreateSnapshot(Snapshot* output_snapshot) const; | 701 bool CreateSnapshot(Snapshot* output_snapshot) const; |
| 674 | 702 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 685 ProcessId* out_id, | 713 ProcessId* out_id, |
| 686 int64_t* out_stamp); | 714 int64_t* out_stamp); |
| 687 | 715 |
| 688 // Calculates the memory size required for a given stack depth, including | 716 // Calculates the memory size required for a given stack depth, including |
| 689 // the internal header structure for the stack. | 717 // the internal header structure for the stack. |
| 690 static size_t SizeForStackDepth(int stack_depth); | 718 static size_t SizeForStackDepth(int stack_depth); |
| 691 | 719 |
| 692 private: | 720 private: |
| 693 friend class ActivityTrackerTest; | 721 friend class ActivityTrackerTest; |
| 694 | 722 |
| 723 std::unique_ptr<ActivityUserData> CreateUserDataForActivity( |
| 724 Activity* activity, |
| 725 ActivityTrackerMemoryAllocator* allocator); |
| 726 |
| 695 Header* const header_; // Pointer to the Header structure. | 727 Header* const header_; // Pointer to the Header structure. |
| 696 Activity* const stack_; // The stack of activities. | 728 Activity* const stack_; // The stack of activities. |
| 697 const uint32_t stack_slots_; // The total number of stack slots. | 729 const uint32_t stack_slots_; // The total number of stack slots. |
| 698 | 730 |
| 699 bool valid_ = false; // Tracks whether the data is valid or not. | 731 bool valid_ = false; // Tracks whether the data is valid or not. |
| 700 | 732 |
| 701 base::ThreadChecker thread_checker_; | 733 base::ThreadChecker thread_checker_; |
| 702 | 734 |
| 703 DISALLOW_COPY_AND_ASSIGN(ThreadActivityTracker); | 735 DISALLOW_COPY_AND_ASSIGN(ThreadActivityTracker); |
| 704 }; | 736 }; |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 913 const FilePath::StringType& args) { | 945 const FilePath::StringType& args) { |
| 914 GlobalActivityTracker* tracker = Get(); | 946 GlobalActivityTracker* tracker = Get(); |
| 915 if (tracker) | 947 if (tracker) |
| 916 tracker->RecordProcessLaunch(process_id, exe, args); | 948 tracker->RecordProcessLaunch(process_id, exe, args); |
| 917 } | 949 } |
| 918 static void RecordProcessExitIfEnabled(ProcessId process_id, int exit_code) { | 950 static void RecordProcessExitIfEnabled(ProcessId process_id, int exit_code) { |
| 919 GlobalActivityTracker* tracker = Get(); | 951 GlobalActivityTracker* tracker = Get(); |
| 920 if (tracker) | 952 if (tracker) |
| 921 tracker->RecordProcessExit(process_id, exit_code); | 953 tracker->RecordProcessExit(process_id, exit_code); |
| 922 } | 954 } |
| 955 |
| 923 // Sets the "phase" of the current process, useful for knowing what it was | 956 // Sets the "phase" of the current process, useful for knowing what it was |
| 924 // doing when it last reported. | 957 // doing when it last reported. |
| 925 void SetProcessPhase(ProcessPhase phase); | 958 void SetProcessPhase(ProcessPhase phase); |
| 926 static void SetProcessPhaseIfEnabled(ProcessPhase phase) { | 959 static void SetProcessPhaseIfEnabled(ProcessPhase phase) { |
| 927 GlobalActivityTracker* tracker = Get(); | 960 GlobalActivityTracker* tracker = Get(); |
| 928 if (tracker) | 961 if (tracker) |
| 929 tracker->SetProcessPhase(phase); | 962 tracker->SetProcessPhase(phase); |
| 930 } | 963 } |
| 931 | 964 |
| 932 // Records a log message. The current implementation does NOT recycle these | 965 // 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 | 984 // this, construction of a GlobalActivityTracker will cause all existing |
| 952 // active field trials to be fetched and recorded. | 985 // active field trials to be fetched and recorded. |
| 953 void RecordFieldTrial(const std::string& trial_name, StringPiece group_name); | 986 void RecordFieldTrial(const std::string& trial_name, StringPiece group_name); |
| 954 static void RecordFieldTrialIfEnabled(const std::string& trial_name, | 987 static void RecordFieldTrialIfEnabled(const std::string& trial_name, |
| 955 StringPiece group_name) { | 988 StringPiece group_name) { |
| 956 GlobalActivityTracker* tracker = Get(); | 989 GlobalActivityTracker* tracker = Get(); |
| 957 if (tracker) | 990 if (tracker) |
| 958 tracker->RecordFieldTrial(trial_name, group_name); | 991 tracker->RecordFieldTrial(trial_name, group_name); |
| 959 } | 992 } |
| 960 | 993 |
| 994 // Record exception information for the current thread. |
| 995 ALWAYS_INLINE |
| 996 void RecordException(const void* origin, uint32_t code) { |
| 997 return RecordExceptionImpl(::tracked_objects::GetProgramCounter(), origin, |
| 998 code); |
| 999 } |
| 1000 |
| 961 // Accesses the process data record for storing arbitrary key/value pairs. | 1001 // Accesses the process data record for storing arbitrary key/value pairs. |
| 962 // Updates to this are thread-safe. | 1002 // Updates to this are thread-safe. |
| 963 ActivityUserData& process_data() { return process_data_; } | 1003 ActivityUserData& process_data() { return process_data_; } |
| 964 | 1004 |
| 965 // Accesses the global data record for storing arbitrary key/value pairs. | 1005 // Accesses the global data record for storing arbitrary key/value pairs. |
| 966 // Updates to this are thread-safe. | 1006 // Updates to this are thread-safe. |
| 967 ActivityUserData& global_data() { return global_data_; } | 1007 ActivityUserData& global_data() { return global_data_; } |
| 968 | 1008 |
| 969 private: | 1009 private: |
| 970 friend class GlobalActivityAnalyzer; | 1010 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 | 1108 // Creates a global tracker using a given persistent-memory |allocator| and |
| 1069 // providing the given |stack_depth| to each thread tracker it manages. The | 1109 // providing the given |stack_depth| to each thread tracker it manages. The |
| 1070 // created object is activated so tracking has already started upon return. | 1110 // created object is activated so tracking has already started upon return. |
| 1071 GlobalActivityTracker(std::unique_ptr<PersistentMemoryAllocator> allocator, | 1111 GlobalActivityTracker(std::unique_ptr<PersistentMemoryAllocator> allocator, |
| 1072 int stack_depth); | 1112 int stack_depth); |
| 1073 | 1113 |
| 1074 // Returns the memory used by an activity-tracker managed by this class. | 1114 // Returns the memory used by an activity-tracker managed by this class. |
| 1075 // It is called during the destruction of a ManagedActivityTracker object. | 1115 // It is called during the destruction of a ManagedActivityTracker object. |
| 1076 void ReturnTrackerMemory(ManagedActivityTracker* tracker); | 1116 void ReturnTrackerMemory(ManagedActivityTracker* tracker); |
| 1077 | 1117 |
| 1118 // Records exception information. |
| 1119 void RecordExceptionImpl(const void* pc, const void* origin, uint32_t code); |
| 1120 |
| 1078 // Releases the activity-tracker associcated with thread. It is called | 1121 // Releases the activity-tracker associcated with thread. It is called |
| 1079 // automatically when a thread is joined and thus there is nothing more to | 1122 // automatically when a thread is joined and thus there is nothing more to |
| 1080 // be tracked. |value| is a pointer to a ManagedActivityTracker. | 1123 // be tracked. |value| is a pointer to a ManagedActivityTracker. |
| 1081 static void OnTLSDestroy(void* value); | 1124 static void OnTLSDestroy(void* value); |
| 1082 | 1125 |
| 1083 // Does process-exit work. This can be run on any thread. | 1126 // Does process-exit work. This can be run on any thread. |
| 1084 void CleanupAfterProcess(ProcessId process_id, | 1127 void CleanupAfterProcess(ProcessId process_id, |
| 1085 int64_t exit_stamp, | 1128 int64_t exit_stamp, |
| 1086 int exit_code, | 1129 int exit_code, |
| 1087 std::string&& command_line); | 1130 std::string&& command_line); |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1261 ScopedProcessWaitActivity(const void* program_counter, | 1304 ScopedProcessWaitActivity(const void* program_counter, |
| 1262 const base::Process* process); | 1305 const base::Process* process); |
| 1263 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); | 1306 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); |
| 1264 }; | 1307 }; |
| 1265 #endif | 1308 #endif |
| 1266 | 1309 |
| 1267 } // namespace debug | 1310 } // namespace debug |
| 1268 } // namespace base | 1311 } // namespace base |
| 1269 | 1312 |
| 1270 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ | 1313 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ |
| OLD | NEW |