| 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 |
| 11 #ifndef BASE_DEBUG_ACTIVITY_TRACKER_H_ | 11 #ifndef BASE_DEBUG_ACTIVITY_TRACKER_H_ |
| 12 #define BASE_DEBUG_ACTIVITY_TRACKER_H_ | 12 #define BASE_DEBUG_ACTIVITY_TRACKER_H_ |
| 13 | 13 |
| 14 // std::atomic is undesired due to performance issues when used as global | 14 // std::atomic is undesired due to performance issues when used as global |
| 15 // variables. There are no such instances here. This module uses the | 15 // variables. There are no such instances here. This module uses the |
| 16 // PersistentMemoryAllocator which also uses std::atomic and is written | 16 // PersistentMemoryAllocator which also uses std::atomic and is written |
| 17 // by the same author. | 17 // by the same author. |
| 18 #include <atomic> | 18 #include <atomic> |
| 19 #include <map> | 19 #include <map> |
| 20 #include <memory> | 20 #include <memory> |
| 21 #include <string> | 21 #include <string> |
| 22 #include <vector> | 22 #include <vector> |
| 23 | 23 |
| 24 #include "base/atomicops.h" | 24 #include "base/atomicops.h" |
| 25 #include "base/base_export.h" | 25 #include "base/base_export.h" |
| 26 #include "base/compiler_specific.h" | 26 #include "base/compiler_specific.h" |
| 27 #include "base/gtest_prod_util.h" | 27 #include "base/gtest_prod_util.h" |
| 28 #include "base/location.h" | 28 #include "base/location.h" |
| 29 #include "base/metrics/persistent_memory_allocator.h" | 29 #include "base/metrics/persistent_memory_allocator.h" |
| 30 #include "base/strings/string_piece.h" |
| 30 #include "base/strings/utf_string_conversions.h" | 31 #include "base/strings/utf_string_conversions.h" |
| 31 #include "base/threading/platform_thread.h" | 32 #include "base/threading/platform_thread.h" |
| 32 #include "base/threading/thread_checker.h" | 33 #include "base/threading/thread_checker.h" |
| 33 #include "base/threading/thread_local_storage.h" | 34 #include "base/threading/thread_local_storage.h" |
| 34 | 35 |
| 35 namespace base { | 36 namespace base { |
| 36 | 37 |
| 37 struct PendingTask; | 38 struct PendingTask; |
| 38 | 39 |
| 39 class FilePath; | 40 class FilePath; |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 | 336 |
| 336 ValueType type_; | 337 ValueType type_; |
| 337 uint64_t short_value_; // Used to hold copy of numbers, etc. | 338 uint64_t short_value_; // Used to hold copy of numbers, etc. |
| 338 std::string long_value_; // Used to hold copy of raw/string data. | 339 std::string long_value_; // Used to hold copy of raw/string data. |
| 339 StringPiece ref_value_; // Used to hold reference to external data. | 340 StringPiece ref_value_; // Used to hold reference to external data. |
| 340 }; | 341 }; |
| 341 | 342 |
| 342 using Snapshot = std::map<std::string, TypedValue>; | 343 using Snapshot = std::map<std::string, TypedValue>; |
| 343 | 344 |
| 344 ActivityUserData(void* memory, size_t size); | 345 ActivityUserData(void* memory, size_t size); |
| 345 ~ActivityUserData(); | 346 virtual ~ActivityUserData(); |
| 346 | 347 |
| 347 // Gets the unique ID number for this user data. If this changes then the | 348 // Gets the unique ID number for this user data. If this changes then the |
| 348 // contents have been overwritten by another thread. The return value is | 349 // contents have been overwritten by another thread. The return value is |
| 349 // always non-zero unless it's actually just a data "sink". | 350 // always non-zero unless it's actually just a data "sink". |
| 350 uint32_t id() const { | 351 uint32_t id() const { |
| 351 return memory_ ? id_->load(std::memory_order_relaxed) : 0; | 352 return memory_ ? id_->load(std::memory_order_relaxed) : 0; |
| 352 } | 353 } |
| 353 | 354 |
| 354 // Writes a |value| (as part of a key/value pair) that will be included with | 355 // Writes a |value| (as part of a key/value pair) that will be included with |
| 355 // the activity in any reports. The same |name| can be written multiple times | 356 // the activity in any reports. The same |name| can be written multiple times |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 // Creates a snapshot of the key/value pairs contained within. The returned | 398 // Creates a snapshot of the key/value pairs contained within. The returned |
| 398 // data will be fixed, independent of whatever changes afterward. There is | 399 // data will be fixed, independent of whatever changes afterward. There is |
| 399 // protection against concurrent modification of the values but no protection | 400 // protection against concurrent modification of the values but no protection |
| 400 // against a complete overwrite of the contents; the caller must ensure that | 401 // against a complete overwrite of the contents; the caller must ensure that |
| 401 // the memory segment is not going to be re-initialized while this runs. | 402 // the memory segment is not going to be re-initialized while this runs. |
| 402 bool CreateSnapshot(Snapshot* output_snapshot) const; | 403 bool CreateSnapshot(Snapshot* output_snapshot) const; |
| 403 | 404 |
| 404 // Gets the base memory address used for storing data. | 405 // Gets the base memory address used for storing data. |
| 405 const void* GetBaseAddress(); | 406 const void* GetBaseAddress(); |
| 406 | 407 |
| 408 protected: |
| 409 virtual void Set(StringPiece name, |
| 410 ValueType type, |
| 411 const void* memory, |
| 412 size_t size); |
| 413 |
| 407 private: | 414 private: |
| 408 FRIEND_TEST_ALL_PREFIXES(ActivityTrackerTest, UserDataTest); | 415 FRIEND_TEST_ALL_PREFIXES(ActivityTrackerTest, UserDataTest); |
| 409 | 416 |
| 410 enum : size_t { kMemoryAlignment = sizeof(uint64_t) }; | 417 enum : size_t { kMemoryAlignment = sizeof(uint64_t) }; |
| 411 | 418 |
| 412 // A structure used to reference data held outside of persistent memory. | 419 // A structure used to reference data held outside of persistent memory. |
| 413 struct ReferenceRecord { | 420 struct ReferenceRecord { |
| 414 uint64_t address; | 421 uint64_t address; |
| 415 uint64_t size; | 422 uint64_t size; |
| 416 }; | 423 }; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 430 ValueInfo(ValueInfo&&); | 437 ValueInfo(ValueInfo&&); |
| 431 ~ValueInfo(); | 438 ~ValueInfo(); |
| 432 | 439 |
| 433 StringPiece name; // The "key" of the record. | 440 StringPiece name; // The "key" of the record. |
| 434 ValueType type; // The type of the value. | 441 ValueType type; // The type of the value. |
| 435 void* memory; // Where the "value" is held. | 442 void* memory; // Where the "value" is held. |
| 436 std::atomic<uint16_t>* size_ptr; // Address of the actual size of value. | 443 std::atomic<uint16_t>* size_ptr; // Address of the actual size of value. |
| 437 size_t extent; // The total storage of the value, | 444 size_t extent; // The total storage of the value, |
| 438 }; // typically rounded up for alignment. | 445 }; // typically rounded up for alignment. |
| 439 | 446 |
| 440 void Set(StringPiece name, ValueType type, const void* memory, size_t size); | |
| 441 void SetReference(StringPiece name, | 447 void SetReference(StringPiece name, |
| 442 ValueType type, | 448 ValueType type, |
| 443 const void* memory, | 449 const void* memory, |
| 444 size_t size); | 450 size_t size); |
| 445 | 451 |
| 446 // Loads any data already in the memory segment. This allows for accessing | 452 // Loads any data already in the memory segment. This allows for accessing |
| 447 // records created previously. | 453 // records created previously. |
| 448 void ImportExistingData() const; | 454 void ImportExistingData() const; |
| 449 | 455 |
| 450 // A map of all the values within the memory block, keyed by name for quick | 456 // A map of all the values within the memory block, keyed by name for quick |
| 451 // updates of the values. This is "mutable" because it changes on "const" | 457 // updates of the values. This is "mutable" because it changes on "const" |
| 452 // objects even when the actual data values can't change. | 458 // objects even when the actual data values can't change. |
| 453 mutable std::map<StringPiece, ValueInfo> values_; | 459 mutable std::map<StringPiece, ValueInfo> values_; |
| 454 | 460 |
| 455 // Information about the memory block in which new data can be stored. These | 461 // Information about the memory block in which new data can be stored. These |
| 456 // are "mutable" because they change even on "const" objects that are just | 462 // are "mutable" because they change even on "const" objects that are just |
| 457 // skipping already set values. | 463 // skipping already set values. |
| 458 mutable char* memory_; | 464 mutable char* memory_; |
| 459 mutable size_t available_; | 465 mutable size_t available_; |
| 460 | 466 |
| 461 // A pointer to the unique ID for this instance. | 467 // A pointer to the unique ID for this instance. |
| 462 std::atomic<uint32_t>* const id_; | 468 std::atomic<uint32_t>* const id_; |
| 463 | 469 |
| 464 base::ThreadChecker thread_checker_; | |
| 465 | |
| 466 // This ID is used to create unique indentifiers for user data so that it's | 470 // This ID is used to create unique indentifiers for user data so that it's |
| 467 // possible to tell if the information has been overwritten. | 471 // possible to tell if the information has been overwritten. |
| 468 static StaticAtomicSequenceNumber next_id_; | 472 static StaticAtomicSequenceNumber next_id_; |
| 469 | 473 |
| 470 DISALLOW_COPY_AND_ASSIGN(ActivityUserData); | 474 DISALLOW_COPY_AND_ASSIGN(ActivityUserData); |
| 471 }; | 475 }; |
| 472 | 476 |
| 473 // This class manages tracking a stack of activities for a single thread in | 477 // This class manages tracking a stack of activities for a single thread in |
| 474 // a persistent manner, implementing a bounded-size stack in a fixed-size | 478 // a persistent manner, implementing a bounded-size stack in a fixed-size |
| 475 // memory allocation. In order to support an operational mode where another | 479 // memory allocation. In order to support an operational mode where another |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 777 void ReleaseTrackerForCurrentThreadForTesting(); | 781 void ReleaseTrackerForCurrentThreadForTesting(); |
| 778 | 782 |
| 779 // Records a log message. The current implementation does NOT recycle these | 783 // Records a log message. The current implementation does NOT recycle these |
| 780 // only store critical messages such as FATAL ones. | 784 // only store critical messages such as FATAL ones. |
| 781 void RecordLogMessage(StringPiece message); | 785 void RecordLogMessage(StringPiece message); |
| 782 | 786 |
| 783 // Records a module load/unload event. This is safe to call multiple times | 787 // Records a module load/unload event. This is safe to call multiple times |
| 784 // even with the same information. | 788 // even with the same information. |
| 785 void RecordModuleInfo(const ModuleInfo& info); | 789 void RecordModuleInfo(const ModuleInfo& info); |
| 786 | 790 |
| 791 // Record field trial information. This call is thread-safe. In addition to |
| 792 // this, construction of a GlobalActivityTracker will cause all existing |
| 793 // active field trials to be fetched and recorded. |
| 794 void RecordFieldTrial(const std::string& trial_name, StringPiece group_name); |
| 795 |
| 787 // Accesses the global data record for storing arbitrary key/value pairs. | 796 // Accesses the global data record for storing arbitrary key/value pairs. |
| 788 ActivityUserData& user_data() { return user_data_; } | 797 ActivityUserData& global_data() { return global_data_; } |
| 789 | 798 |
| 790 private: | 799 private: |
| 791 friend class GlobalActivityAnalyzer; | 800 friend class GlobalActivityAnalyzer; |
| 792 friend class ScopedThreadActivity; | 801 friend class ScopedThreadActivity; |
| 793 friend class ActivityTrackerTest; | 802 friend class ActivityTrackerTest; |
| 794 | 803 |
| 795 enum : int { | 804 enum : int { |
| 796 // The maximum number of threads that can be tracked within a process. If | 805 // The maximum number of threads that can be tracked within a process. If |
| 797 // more than this number run concurrently, tracking of new ones may cease. | 806 // more than this number run concurrently, tracking of new ones may cease. |
| 798 kMaxThreadCount = 100, | 807 kMaxThreadCount = 100, |
| 799 kCachedThreadMemories = 10, | 808 kCachedThreadMemories = 10, |
| 800 kCachedUserDataMemories = 10, | 809 kCachedUserDataMemories = 10, |
| 801 }; | 810 }; |
| 802 | 811 |
| 812 // A wrapper around ActivityUserData that is thread-safe and thus can be used |
| 813 // in the global scope without the requirement of being called from only one |
| 814 // thread. |
| 815 class GlobalUserData : public ActivityUserData { |
| 816 public: |
| 817 GlobalUserData(void* memory, size_t size); |
| 818 ~GlobalUserData() override; |
| 819 |
| 820 private: |
| 821 void Set(StringPiece name, |
| 822 ValueType type, |
| 823 const void* memory, |
| 824 size_t size) override; |
| 825 |
| 826 Lock data_lock_; |
| 827 |
| 828 DISALLOW_COPY_AND_ASSIGN(GlobalUserData); |
| 829 }; |
| 830 |
| 803 // State of a module as stored in persistent memory. This supports a single | 831 // State of a module as stored in persistent memory. This supports a single |
| 804 // loading of a module only. If modules are loaded multiple times at | 832 // loading of a module only. If modules are loaded multiple times at |
| 805 // different addresses, only the last will be recorded and an unload will | 833 // different addresses, only the last will be recorded and an unload will |
| 806 // not revert to the information of any other addresses. | 834 // not revert to the information of any other addresses. |
| 807 struct BASE_EXPORT ModuleInfoRecord { | 835 struct BASE_EXPORT ModuleInfoRecord { |
| 808 // SHA1(ModuleInfoRecord): Increment this if structure changes! | 836 // SHA1(ModuleInfoRecord): Increment this if structure changes! |
| 809 static constexpr uint32_t kPersistentTypeId = 0x05DB5F41 + 1; | 837 static constexpr uint32_t kPersistentTypeId = 0x05DB5F41 + 1; |
| 810 | 838 |
| 811 // Expected size for 32/64-bit check by PersistentMemoryAllocator. | 839 // Expected size for 32/64-bit check by PersistentMemoryAllocator. |
| 812 static constexpr size_t kExpectedInstanceSize = 56; | 840 static constexpr size_t kExpectedInstanceSize = 56; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 897 // A caching memory allocator for thread-tracker objects. | 925 // A caching memory allocator for thread-tracker objects. |
| 898 ActivityTrackerMemoryAllocator thread_tracker_allocator_; | 926 ActivityTrackerMemoryAllocator thread_tracker_allocator_; |
| 899 base::Lock thread_tracker_allocator_lock_; | 927 base::Lock thread_tracker_allocator_lock_; |
| 900 | 928 |
| 901 // A caching memory allocator for user data attached to activity data. | 929 // A caching memory allocator for user data attached to activity data. |
| 902 ActivityTrackerMemoryAllocator user_data_allocator_; | 930 ActivityTrackerMemoryAllocator user_data_allocator_; |
| 903 base::Lock user_data_allocator_lock_; | 931 base::Lock user_data_allocator_lock_; |
| 904 | 932 |
| 905 // An object for holding global arbitrary key value pairs. Values must always | 933 // An object for holding global arbitrary key value pairs. Values must always |
| 906 // be written from the main UI thread. | 934 // be written from the main UI thread. |
| 907 ActivityUserData user_data_; | 935 GlobalUserData global_data_; |
| 908 | 936 |
| 909 // A map of global module information, keyed by module path. | 937 // A map of global module information, keyed by module path. |
| 910 std::map<const std::string, ModuleInfoRecord*> modules_; | 938 std::map<const std::string, ModuleInfoRecord*> modules_; |
| 911 base::Lock modules_lock_; | 939 base::Lock modules_lock_; |
| 912 | 940 |
| 913 // The active global activity tracker. | 941 // The active global activity tracker. |
| 914 static subtle::AtomicWord g_tracker_; | 942 static subtle::AtomicWord g_tracker_; |
| 915 | 943 |
| 916 DISALLOW_COPY_AND_ASSIGN(GlobalActivityTracker); | 944 DISALLOW_COPY_AND_ASSIGN(GlobalActivityTracker); |
| 917 }; | 945 }; |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1040 ScopedProcessWaitActivity(const void* program_counter, | 1068 ScopedProcessWaitActivity(const void* program_counter, |
| 1041 const base::Process* process); | 1069 const base::Process* process); |
| 1042 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); | 1070 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); |
| 1043 }; | 1071 }; |
| 1044 #endif | 1072 #endif |
| 1045 | 1073 |
| 1046 } // namespace debug | 1074 } // namespace debug |
| 1047 } // namespace base | 1075 } // namespace base |
| 1048 | 1076 |
| 1049 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ | 1077 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ |
| OLD | NEW |