| 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 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 bool make_iterable); | 148 bool make_iterable); |
| 149 ~ActivityTrackerMemoryAllocator(); | 149 ~ActivityTrackerMemoryAllocator(); |
| 150 | 150 |
| 151 // Gets a reference to an object of the configured type. This can return | 151 // Gets a reference to an object of the configured type. This can return |
| 152 // a null reference if it was not possible to allocate the memory. | 152 // a null reference if it was not possible to allocate the memory. |
| 153 Reference GetObjectReference(); | 153 Reference GetObjectReference(); |
| 154 | 154 |
| 155 // Returns an object to the "free" pool. | 155 // Returns an object to the "free" pool. |
| 156 void ReleaseObjectReference(Reference ref); | 156 void ReleaseObjectReference(Reference ref); |
| 157 | 157 |
| 158 // Helper function to access an object allocated using this instance. |
| 159 template <typename T> |
| 160 T* GetAsObject(Reference ref) { |
| 161 return allocator_->GetAsObject<T>(ref, object_type_); |
| 162 } |
| 163 |
| 164 // Similar to GetAsObject() but converts references to arrays of objects. |
| 165 template <typename T> |
| 166 T* GetAsArray(Reference ref, size_t count) { |
| 167 return allocator_->GetAsArray<T>(ref, object_type_, count); |
| 168 } |
| 169 |
| 158 // The current "used size" of the internal cache, visible for testing. | 170 // The current "used size" of the internal cache, visible for testing. |
| 159 size_t cache_used() const { return cache_used_; } | 171 size_t cache_used() const { return cache_used_; } |
| 160 | 172 |
| 161 private: | 173 private: |
| 162 PersistentMemoryAllocator* const allocator_; | 174 PersistentMemoryAllocator* const allocator_; |
| 163 const uint32_t object_type_; | 175 const uint32_t object_type_; |
| 164 const uint32_t object_free_type_; | 176 const uint32_t object_free_type_; |
| 165 const size_t object_size_; | 177 const size_t object_size_; |
| 166 const size_t cache_size_; | 178 const size_t cache_size_; |
| 167 const bool make_iterable_; | 179 const bool make_iterable_; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 // it null. | 249 // it null. |
| 238 uint64_t origin_address; | 250 uint64_t origin_address; |
| 239 | 251 |
| 240 // Array of program-counters that make up the top of the call stack. | 252 // Array of program-counters that make up the top of the call stack. |
| 241 // Despite the fixed size, this list is always null-terminated. Entries | 253 // Despite the fixed size, this list is always null-terminated. Entries |
| 242 // after the terminator have no meaning and may or may not also be null. | 254 // after the terminator have no meaning and may or may not also be null. |
| 243 // The list will be completely empty if call-stack collection is not | 255 // The list will be completely empty if call-stack collection is not |
| 244 // enabled. | 256 // enabled. |
| 245 uint64_t call_stack[kActivityCallStackSize]; | 257 uint64_t call_stack[kActivityCallStackSize]; |
| 246 | 258 |
| 247 // Reference to arbitrary user data within the persistent memory segment. | 259 // Reference to arbitrary user data within the persistent memory segment |
| 248 uint32_t user_data; | 260 // and a unique identifier for it. |
| 261 uint32_t user_data_ref; |
| 262 uint32_t user_data_id; |
| 249 | 263 |
| 250 // The (enumerated) type of the activity. This defines what fields of the | 264 // The (enumerated) type of the activity. This defines what fields of the |
| 251 // |data| record are valid. | 265 // |data| record are valid. |
| 252 uint8_t activity_type; | 266 uint8_t activity_type; |
| 253 | 267 |
| 254 // Padding to ensure that the next member begins on a 64-bit boundary | 268 // Padding to ensure that the next member begins on a 64-bit boundary |
| 255 // even on 32-bit builds which ensures inter-operability between CPU | 269 // even on 32-bit builds which ensures inter-operability between CPU |
| 256 // architectures. New fields can be taken from this space. | 270 // architectures. New fields can be taken from this space. |
| 257 uint8_t padding[3]; | 271 uint8_t padding[7]; |
| 258 | 272 |
| 259 // Information specific to the |activity_type|. | 273 // Information specific to the |activity_type|. |
| 260 ActivityData data; | 274 ActivityData data; |
| 261 | 275 |
| 262 static void FillFrom(Activity* activity, | 276 static void FillFrom(Activity* activity, |
| 263 const void* program_counter, | 277 const void* program_counter, |
| 264 const void* origin, | 278 const void* origin, |
| 265 Type type, | 279 Type type, |
| 266 const ActivityData& data); | 280 const ActivityData& data); |
| 267 }; | 281 }; |
| 268 | 282 |
| 269 // This structure holds a copy of all the internal data at the moment the | |
| 270 // "snapshot" operation is done. It is disconnected from the live tracker | |
| 271 // so that continued operation of the thread will not cause changes here. | |
| 272 struct BASE_EXPORT ActivitySnapshot { | |
| 273 // Explicit constructor/destructor are needed because of complex types | |
| 274 // with non-trivial default constructors and destructors. | |
| 275 ActivitySnapshot(); | |
| 276 ~ActivitySnapshot(); | |
| 277 | |
| 278 // The name of the thread as set when it was created. The name may be | |
| 279 // truncated due to internal length limitations. | |
| 280 std::string thread_name; | |
| 281 | |
| 282 // The process and thread IDs. These values have no meaning other than | |
| 283 // they uniquely identify a running process and a running thread within | |
| 284 // that process. Thread-IDs can be re-used across different processes | |
| 285 // and both can be re-used after the process/thread exits. | |
| 286 int64_t process_id = 0; | |
| 287 int64_t thread_id = 0; | |
| 288 | |
| 289 // The current stack of activities that are underway for this thread. It | |
| 290 // is limited in its maximum size with later entries being left off. | |
| 291 std::vector<Activity> activity_stack; | |
| 292 | |
| 293 // The current total depth of the activity stack, including those later | |
| 294 // entries not recorded in the |activity_stack| vector. | |
| 295 uint32_t activity_stack_depth = 0; | |
| 296 }; | |
| 297 | |
| 298 // This class manages arbitrary user data that can be associated with activities | 283 // This class manages arbitrary user data that can be associated with activities |
| 299 // done by a thread by supporting key/value pairs of any type. This can provide | 284 // done by a thread by supporting key/value pairs of any type. This can provide |
| 300 // additional information during debugging. It is also used to store arbitrary | 285 // additional information during debugging. It is also used to store arbitrary |
| 301 // global data. All updates must be done from the same thread. | 286 // global data. All updates must be done from the same thread. |
| 302 class BASE_EXPORT ActivityUserData { | 287 class BASE_EXPORT ActivityUserData { |
| 288 public: |
| 303 // List of known value type. REFERENCE types must immediately follow the non- | 289 // List of known value type. REFERENCE types must immediately follow the non- |
| 304 // external types. | 290 // external types. |
| 305 enum ValueType : uint8_t { | 291 enum ValueType : uint8_t { |
| 306 END_OF_VALUES = 0, | 292 END_OF_VALUES = 0, |
| 307 RAW_VALUE, | 293 RAW_VALUE, |
| 308 RAW_VALUE_REFERENCE, | 294 RAW_VALUE_REFERENCE, |
| 309 STRING_VALUE, | 295 STRING_VALUE, |
| 310 STRING_VALUE_REFERENCE, | 296 STRING_VALUE_REFERENCE, |
| 311 CHAR_VALUE, | 297 CHAR_VALUE, |
| 298 BOOL_VALUE, |
| 312 SIGNED_VALUE, | 299 SIGNED_VALUE, |
| 313 UNSIGNED_VALUE, | 300 UNSIGNED_VALUE, |
| 314 }; | 301 }; |
| 315 | 302 |
| 316 public: | 303 class BASE_EXPORT TypedValue { |
| 304 public: |
| 305 TypedValue(); |
| 306 TypedValue(const TypedValue& other); |
| 307 ~TypedValue(); |
| 308 |
| 309 // These methods return the extracted value in the correct format. |
| 310 StringPiece Get() const; |
| 311 StringPiece GetString() const; |
| 312 bool GetBool() const; |
| 313 char GetChar() const; |
| 314 int64_t GetInt() const; |
| 315 uint64_t GetUint() const; |
| 316 |
| 317 // These methods return references to process memory as originally provided |
| 318 // to corresponding Set calls. USE WITH CAUTION! There is no guarantee that |
| 319 // the referenced memory is assessible or useful. It's possible that: |
| 320 // - the memory was free'd and reallocated for a different purpose |
| 321 // - the memory has been released back to the OS |
| 322 // - the memory belongs to a different process's address space |
| 323 // Dereferencing the returned StringPiece when the memory is not accessible |
| 324 // will cause the program to SEGV! |
| 325 StringPiece GetReference() const; |
| 326 StringPiece GetStringReference() const; |
| 327 |
| 328 private: |
| 329 friend class ActivityUserData; |
| 330 |
| 331 ValueType type; |
| 332 uint64_t short_value; // Used to hold copy of numbers, etc. |
| 333 std::string long_value; // Used to hold copy of raw/string data. |
| 334 StringPiece ref_value; // Used to hold reference to external data. |
| 335 }; |
| 336 |
| 337 using Snapshot = std::map<std::string, TypedValue>; |
| 338 |
| 317 ActivityUserData(void* memory, size_t size); | 339 ActivityUserData(void* memory, size_t size); |
| 318 ~ActivityUserData(); | 340 ~ActivityUserData(); |
| 319 | 341 |
| 342 // Gets the unique ID number for this user data. If this changes then the |
| 343 // contents have been overwritten by another thread. The return value is |
| 344 // always non-zero unless it's actually just a data "sink". |
| 345 uint32_t id() const { |
| 346 return memory_ ? id_->load(std::memory_order_relaxed) : 0; |
| 347 } |
| 348 |
| 320 // Writes a |value| (as part of a key/value pair) that will be included with | 349 // Writes a |value| (as part of a key/value pair) that will be included with |
| 321 // the activity in any reports. The same |name| can be written multiple times | 350 // the activity in any reports. The same |name| can be written multiple times |
| 322 // with each successive call overwriting the previously stored |value|. For | 351 // with each successive call overwriting the previously stored |value|. For |
| 323 // raw and string values, the maximum size of successive writes is limited by | 352 // raw and string values, the maximum size of successive writes is limited by |
| 324 // the first call. The length of "name" is limited to 255 characters. | 353 // the first call. The length of "name" is limited to 255 characters. |
| 325 // | 354 // |
| 326 // This information is stored on a "best effort" basis. It may be dropped if | 355 // This information is stored on a "best effort" basis. It may be dropped if |
| 327 // the memory buffer is full or the associated activity is beyond the maximum | 356 // the memory buffer is full or the associated activity is beyond the maximum |
| 328 // recording depth. | 357 // recording depth. |
| 329 void Set(StringPiece name, const void* memory, size_t size) { | 358 void Set(StringPiece name, const void* memory, size_t size) { |
| 330 Set(name, RAW_VALUE, memory, size); | 359 Set(name, RAW_VALUE, memory, size); |
| 331 } | 360 } |
| 332 void SetString(StringPiece name, StringPiece value) { | 361 void SetString(StringPiece name, StringPiece value) { |
| 333 Set(name, STRING_VALUE, value.data(), value.length()); | 362 Set(name, STRING_VALUE, value.data(), value.length()); |
| 334 } | 363 } |
| 364 void SetBool(StringPiece name, bool value) { |
| 365 char cvalue = value ? 1 : 0; |
| 366 Set(name, BOOL_VALUE, &cvalue, sizeof(cvalue)); |
| 367 } |
| 335 void SetChar(StringPiece name, char value) { | 368 void SetChar(StringPiece name, char value) { |
| 336 Set(name, CHAR_VALUE, &value, sizeof(value)); | 369 Set(name, CHAR_VALUE, &value, sizeof(value)); |
| 337 } | 370 } |
| 338 void SetInt(StringPiece name, int64_t value) { | 371 void SetInt(StringPiece name, int64_t value) { |
| 339 Set(name, SIGNED_VALUE, &value, sizeof(value)); | 372 Set(name, SIGNED_VALUE, &value, sizeof(value)); |
| 340 } | 373 } |
| 341 void SetUint(StringPiece name, uint64_t value) { | 374 void SetUint(StringPiece name, uint64_t value) { |
| 342 Set(name, UNSIGNED_VALUE, &value, sizeof(value)); | 375 Set(name, UNSIGNED_VALUE, &value, sizeof(value)); |
| 343 } | 376 } |
| 344 | 377 |
| 345 // These function as above but don't actually copy the data into the | 378 // These function as above but don't actually copy the data into the |
| 346 // persistent memory. They store unaltered pointers along with a size. These | 379 // persistent memory. They store unaltered pointers along with a size. These |
| 347 // can be used in conjuction with a memory dump to find certain large pieces | 380 // can be used in conjuction with a memory dump to find certain large pieces |
| 348 // of information. | 381 // of information. |
| 349 void SetReference(StringPiece name, const void* memory, size_t size) { | 382 void SetReference(StringPiece name, const void* memory, size_t size) { |
| 350 SetReference(name, RAW_VALUE_REFERENCE, memory, size); | 383 SetReference(name, RAW_VALUE_REFERENCE, memory, size); |
| 351 } | 384 } |
| 352 void SetStringReference(StringPiece name, StringPiece value) { | 385 void SetStringReference(StringPiece name, StringPiece value) { |
| 353 SetReference(name, STRING_VALUE_REFERENCE, value.data(), value.length()); | 386 SetReference(name, STRING_VALUE_REFERENCE, value.data(), value.length()); |
| 354 } | 387 } |
| 355 | 388 |
| 389 // Creates a snapshot of the key/value pairs contained within. The returned |
| 390 // data will be fixed, independent of whatever changes afterward. There is |
| 391 // protection against concurrent modification of the values but no protection |
| 392 // against a complete overwrite of the contents; the caller must ensure that |
| 393 // the memory segment is not going to be re-initialized while this runs. |
| 394 bool CreateSnapshot(Snapshot* output_snapshot) const; |
| 395 |
| 396 // Gets the base memory address used for storing data. |
| 397 const void* GetBaseAddress(); |
| 398 |
| 356 private: | 399 private: |
| 357 FRIEND_TEST_ALL_PREFIXES(ActivityTrackerTest, UserDataTest); | 400 FRIEND_TEST_ALL_PREFIXES(ActivityTrackerTest, UserDataTest); |
| 358 | 401 |
| 359 enum : size_t { kMemoryAlignment = sizeof(uint64_t) }; | 402 enum : size_t { kMemoryAlignment = sizeof(uint64_t) }; |
| 360 | 403 |
| 361 // A structure used to reference data held outside of persistent memory. | 404 // A structure used to reference data held outside of persistent memory. |
| 362 struct ReferenceRecord { | 405 struct ReferenceRecord { |
| 363 uint64_t address; | 406 uint64_t address; |
| 364 uint64_t size; | 407 uint64_t size; |
| 365 }; | 408 }; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 385 std::atomic<uint16_t>* size_ptr; // Address of the actual size of value. | 428 std::atomic<uint16_t>* size_ptr; // Address of the actual size of value. |
| 386 size_t extent; // The total storage of the value, | 429 size_t extent; // The total storage of the value, |
| 387 }; // typically rounded up for alignment. | 430 }; // typically rounded up for alignment. |
| 388 | 431 |
| 389 void Set(StringPiece name, ValueType type, const void* memory, size_t size); | 432 void Set(StringPiece name, ValueType type, const void* memory, size_t size); |
| 390 void SetReference(StringPiece name, | 433 void SetReference(StringPiece name, |
| 391 ValueType type, | 434 ValueType type, |
| 392 const void* memory, | 435 const void* memory, |
| 393 size_t size); | 436 size_t size); |
| 394 | 437 |
| 395 // TODO(bcwhite): Add Get() methods for Analyzer to use. | 438 // Loads any data already in the memory segment. This allows for accessing |
| 439 // records created previously. |
| 440 void ImportExistingData() const; |
| 396 | 441 |
| 397 std::map<StringPiece, ValueInfo> values_; | 442 // A map of all the values within the memory block, keyed by name for quick |
| 443 // updates of the values. This is "mutable" because it changes on "const" |
| 444 // objects even when the actual data values can't change. |
| 445 mutable std::map<StringPiece, ValueInfo> values_; |
| 398 | 446 |
| 399 char* memory_; | 447 // Information about the memory block in which new data can be stored. These |
| 400 size_t available_; | 448 // are "mutable" because they change even on "const" objects that are just |
| 449 // skipping already set values. |
| 450 mutable char* memory_; |
| 451 mutable size_t available_; |
| 452 |
| 453 // A pointer to the unique ID for this instance. |
| 454 std::atomic<uint32_t>* const id_; |
| 401 | 455 |
| 402 base::ThreadChecker thread_checker_; | 456 base::ThreadChecker thread_checker_; |
| 403 | 457 |
| 458 // This ID is used to create unique indentifiers for user data so that it's |
| 459 // possible to tell if the information has been overwritten. |
| 460 static std::atomic<uint32_t> next_id_; |
| 461 |
| 404 DISALLOW_COPY_AND_ASSIGN(ActivityUserData); | 462 DISALLOW_COPY_AND_ASSIGN(ActivityUserData); |
| 405 }; | 463 }; |
| 406 | 464 |
| 407 // This class manages tracking a stack of activities for a single thread in | 465 // This class manages tracking a stack of activities for a single thread in |
| 408 // a persistent manner, implementing a bounded-size stack in a fixed-size | 466 // a persistent manner, implementing a bounded-size stack in a fixed-size |
| 409 // memory allocation. In order to support an operational mode where another | 467 // memory allocation. In order to support an operational mode where another |
| 410 // thread is analyzing this data in real-time, atomic operations are used | 468 // thread is analyzing this data in real-time, atomic operations are used |
| 411 // where necessary to guarantee a consistent view from the outside. | 469 // where necessary to guarantee a consistent view from the outside. |
| 412 // | 470 // |
| 413 // This class is not generally used directly but instead managed by the | 471 // This class is not generally used directly but instead managed by the |
| 414 // GlobalActivityTracker instance and updated using Scoped*Activity local | 472 // GlobalActivityTracker instance and updated using Scoped*Activity local |
| 415 // objects. | 473 // objects. |
| 416 class BASE_EXPORT ThreadActivityTracker { | 474 class BASE_EXPORT ThreadActivityTracker { |
| 417 public: | 475 public: |
| 476 using ActivityId = uint32_t; |
| 477 |
| 418 // This structure contains all the common information about the thread so | 478 // This structure contains all the common information about the thread so |
| 419 // it doesn't have to be repeated in every entry on the stack. It is defined | 479 // it doesn't have to be repeated in every entry on the stack. It is defined |
| 420 // and used completely within the .cc file. | 480 // and used completely within the .cc file. |
| 421 struct Header; | 481 struct Header; |
| 422 | 482 |
| 423 using ActivityId = uint32_t; | 483 // This structure holds a copy of all the internal data at the moment the |
| 484 // "snapshot" operation is done. It is disconnected from the live tracker |
| 485 // so that continued operation of the thread will not cause changes here. |
| 486 struct BASE_EXPORT Snapshot { |
| 487 // Explicit constructor/destructor are needed because of complex types |
| 488 // with non-trivial default constructors and destructors. |
| 489 Snapshot(); |
| 490 ~Snapshot(); |
| 491 |
| 492 // The name of the thread as set when it was created. The name may be |
| 493 // truncated due to internal length limitations. |
| 494 std::string thread_name; |
| 495 |
| 496 // The process and thread IDs. These values have no meaning other than |
| 497 // they uniquely identify a running process and a running thread within |
| 498 // that process. Thread-IDs can be re-used across different processes |
| 499 // and both can be re-used after the process/thread exits. |
| 500 int64_t process_id = 0; |
| 501 int64_t thread_id = 0; |
| 502 |
| 503 // The current stack of activities that are underway for this thread. It |
| 504 // is limited in its maximum size with later entries being left off. |
| 505 std::vector<Activity> activity_stack; |
| 506 |
| 507 // The current total depth of the activity stack, including those later |
| 508 // entries not recorded in the |activity_stack| vector. |
| 509 uint32_t activity_stack_depth = 0; |
| 510 }; |
| 424 | 511 |
| 425 // This is the base class for having the compiler manage an activity on the | 512 // This is the base class for having the compiler manage an activity on the |
| 426 // tracker's stack. It does nothing but call methods on the passed |tracker| | 513 // tracker's stack. It does nothing but call methods on the passed |tracker| |
| 427 // if it is not null, making it safe (and cheap) to create these objects | 514 // if it is not null, making it safe (and cheap) to create these objects |
| 428 // even if activity tracking is not enabled. | 515 // even if activity tracking is not enabled. |
| 429 class BASE_EXPORT ScopedActivity { | 516 class BASE_EXPORT ScopedActivity { |
| 430 public: | 517 public: |
| 431 ScopedActivity(ThreadActivityTracker* tracker, | 518 ScopedActivity(ThreadActivityTracker* tracker, |
| 432 const void* program_counter, | 519 const void* program_counter, |
| 433 const void* origin, | 520 const void* origin, |
| 434 Activity::Type type, | 521 Activity::Type type, |
| 435 const ActivityData& data); | 522 const ActivityData& data); |
| 436 ~ScopedActivity(); | 523 ~ScopedActivity(); |
| 437 | 524 |
| 438 // Changes some basic metadata about the activity. | 525 // Changes some basic metadata about the activity. |
| 439 void ChangeTypeAndData(Activity::Type type, const ActivityData& data); | 526 void ChangeTypeAndData(Activity::Type type, const ActivityData& data); |
| 440 | 527 |
| 441 // Returns an object for manipulating user data. | 528 protected: |
| 442 ActivityUserData& user_data(); | |
| 443 | |
| 444 private: | |
| 445 // The thread tracker to which this object reports. It can be null if | 529 // The thread tracker to which this object reports. It can be null if |
| 446 // activity tracking is not (yet) enabled. | 530 // activity tracking is not (yet) enabled. |
| 447 ThreadActivityTracker* const tracker_; | 531 ThreadActivityTracker* const tracker_; |
| 448 | 532 |
| 449 // An identifier that indicates a specific activity on the stack. | 533 // An identifier that indicates a specific activity on the stack. |
| 450 ActivityId activity_id_; | 534 ActivityId activity_id_; |
| 451 | 535 |
| 452 // An object that manages additional user data, created only upon request. | |
| 453 std::unique_ptr<ActivityUserData> user_data_; | |
| 454 | |
| 455 DISALLOW_COPY_AND_ASSIGN(ScopedActivity); | 536 DISALLOW_COPY_AND_ASSIGN(ScopedActivity); |
| 456 }; | 537 }; |
| 457 | 538 |
| 458 // A ThreadActivityTracker runs on top of memory that is managed externally. | 539 // A ThreadActivityTracker runs on top of memory that is managed externally. |
| 459 // It must be large enough for the internal header and a few Activity | 540 // It must be large enough for the internal header and a few Activity |
| 460 // blocks. See SizeForStackDepth(). | 541 // blocks. See SizeForStackDepth(). |
| 461 ThreadActivityTracker(void* base, size_t size); | 542 ThreadActivityTracker(void* base, size_t size); |
| 462 virtual ~ThreadActivityTracker(); | 543 virtual ~ThreadActivityTracker(); |
| 463 | 544 |
| 464 // Indicates that an activity has started from a given |origin| address in | 545 // Indicates that an activity has started from a given |origin| address in |
| (...skipping 23 matching lines...) Expand all Loading... |
| 488 // unchanged. The type, if changed, must remain in the same category. | 569 // unchanged. The type, if changed, must remain in the same category. |
| 489 // Changing both is not atomic so a snapshot operation could occur between | 570 // Changing both is not atomic so a snapshot operation could occur between |
| 490 // the update of |type| and |data| or between update of |data| fields. | 571 // the update of |type| and |data| or between update of |data| fields. |
| 491 void ChangeActivity(ActivityId id, | 572 void ChangeActivity(ActivityId id, |
| 492 Activity::Type type, | 573 Activity::Type type, |
| 493 const ActivityData& data); | 574 const ActivityData& data); |
| 494 | 575 |
| 495 // Indicates that an activity has completed. | 576 // Indicates that an activity has completed. |
| 496 void PopActivity(ActivityId id); | 577 void PopActivity(ActivityId id); |
| 497 | 578 |
| 498 // Returns an object capable of storing arbitrary user data. | 579 // Sets the user-data information for an activity. |
| 499 std::unique_ptr<ActivityUserData> GetUserData(ActivityId id); | 580 std::unique_ptr<ActivityUserData> GetUserData( |
| 581 ActivityId id, |
| 582 ActivityTrackerMemoryAllocator* allocator); |
| 583 |
| 584 // Returns if there is true use-data associated with a given ActivityId since |
| 585 // it's possible than any returned object is just a sink. |
| 586 bool HasUserData(ActivityId id); |
| 587 |
| 588 // Release the user-data information for an activity. |
| 589 void ReleaseUserData(ActivityId id, |
| 590 ActivityTrackerMemoryAllocator* allocator); |
| 500 | 591 |
| 501 // Returns whether the current data is valid or not. It is not valid if | 592 // Returns whether the current data is valid or not. It is not valid if |
| 502 // corruption has been detected in the header or other data structures. | 593 // corruption has been detected in the header or other data structures. |
| 503 bool IsValid() const; | 594 bool IsValid() const; |
| 504 | 595 |
| 505 // Gets a copy of the tracker contents for analysis. Returns false if a | 596 // Gets a copy of the tracker contents for analysis. Returns false if a |
| 506 // snapshot was not possible, perhaps because the data is not valid; the | 597 // snapshot was not possible, perhaps because the data is not valid; the |
| 507 // contents of |output_snapshot| are undefined in that case. The current | 598 // contents of |output_snapshot| are undefined in that case. The current |
| 508 // implementation does not support concurrent snapshot operations. | 599 // implementation does not support concurrent snapshot operations. |
| 509 bool Snapshot(ActivitySnapshot* output_snapshot) const; | 600 bool CreateSnapshot(Snapshot* output_snapshot) const; |
| 510 | 601 |
| 511 // Calculates the memory size required for a given stack depth, including | 602 // Calculates the memory size required for a given stack depth, including |
| 512 // the internal header structure for the stack. | 603 // the internal header structure for the stack. |
| 513 static size_t SizeForStackDepth(int stack_depth); | 604 static size_t SizeForStackDepth(int stack_depth); |
| 514 | 605 |
| 515 private: | 606 private: |
| 516 friend class ActivityTrackerTest; | 607 friend class ActivityTrackerTest; |
| 517 | 608 |
| 518 Header* const header_; // Pointer to the Header structure. | 609 Header* const header_; // Pointer to the Header structure. |
| 519 Activity* const stack_; // The stack of activities. | 610 Activity* const stack_; // The stack of activities. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 533 class BASE_EXPORT GlobalActivityTracker { | 624 class BASE_EXPORT GlobalActivityTracker { |
| 534 public: | 625 public: |
| 535 // Type identifiers used when storing in persistent memory so they can be | 626 // Type identifiers used when storing in persistent memory so they can be |
| 536 // identified during extraction; the first 4 bytes of the SHA1 of the name | 627 // identified during extraction; the first 4 bytes of the SHA1 of the name |
| 537 // is used as a unique integer. A "version number" is added to the base | 628 // is used as a unique integer. A "version number" is added to the base |
| 538 // so that, if the structure of that object changes, stored older versions | 629 // so that, if the structure of that object changes, stored older versions |
| 539 // will be safely ignored. These are public so that an external process | 630 // will be safely ignored. These are public so that an external process |
| 540 // can recognize records of this type within an allocator. | 631 // can recognize records of this type within an allocator. |
| 541 enum : uint32_t { | 632 enum : uint32_t { |
| 542 kTypeIdActivityTracker = 0x5D7381AF + 3, // SHA1(ActivityTracker) v3 | 633 kTypeIdActivityTracker = 0x5D7381AF + 3, // SHA1(ActivityTracker) v3 |
| 543 kTypeIdUserDataRecord = 0x615EDDD7 + 1, // SHA1(UserDataRecord) v1 | 634 kTypeIdUserDataRecord = 0x615EDDD7 + 2, // SHA1(UserDataRecord) v2 |
| 544 kTypeIdGlobalDataRecord = 0xAFE61ABE + 1, // SHA1(GlobalDataRecord) v1 | |
| 545 kTypeIdGlobalLogMessage = 0x4CF434F9 + 1, // SHA1(GlobalLogMessage) v1 | 635 kTypeIdGlobalLogMessage = 0x4CF434F9 + 1, // SHA1(GlobalLogMessage) v1 |
| 636 kTypeIdGlobalDataRecord = kTypeIdUserDataRecord + 1000, |
| 546 | 637 |
| 547 kTypeIdActivityTrackerFree = ~kTypeIdActivityTracker, | 638 kTypeIdActivityTrackerFree = ~kTypeIdActivityTracker, |
| 548 kTypeIdUserDataRecordFree = ~kTypeIdUserDataRecord, | 639 kTypeIdUserDataRecordFree = ~kTypeIdUserDataRecord, |
| 549 }; | 640 }; |
| 550 | 641 |
| 551 // This is a thin wrapper around the thread-tracker's ScopedActivity that | 642 // This is a thin wrapper around the thread-tracker's ScopedActivity that |
| 552 // accesses the global tracker to provide some of the information, notably | 643 // accesses the global tracker to provide some of the information, notably |
| 553 // which thread-tracker to use. It is safe to create even if activity | 644 // which thread-tracker to use. It is safe to create even if activity |
| 554 // tracking is not enabled. | 645 // tracking is not enabled. |
| 555 class BASE_EXPORT ScopedThreadActivity | 646 class BASE_EXPORT ScopedThreadActivity |
| 556 : public ThreadActivityTracker::ScopedActivity { | 647 : public ThreadActivityTracker::ScopedActivity { |
| 557 public: | 648 public: |
| 558 ScopedThreadActivity(const void* program_counter, | 649 ScopedThreadActivity(const void* program_counter, |
| 559 const void* origin, | 650 const void* origin, |
| 560 Activity::Type type, | 651 Activity::Type type, |
| 561 const ActivityData& data, | 652 const ActivityData& data, |
| 562 bool lock_allowed) | 653 bool lock_allowed); |
| 563 : ThreadActivityTracker::ScopedActivity( | 654 ~ScopedThreadActivity(); |
| 564 GetOrCreateTracker(lock_allowed), | 655 |
| 565 program_counter, | 656 // Returns an object for manipulating user data. |
| 566 origin, | 657 ActivityUserData& user_data(); |
| 567 type, | |
| 568 data) {} | |
| 569 | 658 |
| 570 private: | 659 private: |
| 571 // Gets (or creates) a tracker for the current thread. If locking is not | 660 // Gets (or creates) a tracker for the current thread. If locking is not |
| 572 // allowed (because a lock is being tracked which would cause recursion) | 661 // allowed (because a lock is being tracked which would cause recursion) |
| 573 // then the attempt to create one if none found will be skipped. Once | 662 // then the attempt to create one if none found will be skipped. Once |
| 574 // the tracker for this thread has been created for other reasons, locks | 663 // the tracker for this thread has been created for other reasons, locks |
| 575 // will be tracked. The thread-tracker uses locks. | 664 // will be tracked. The thread-tracker uses locks. |
| 576 static ThreadActivityTracker* GetOrCreateTracker(bool lock_allowed) { | 665 static ThreadActivityTracker* GetOrCreateTracker(bool lock_allowed) { |
| 577 GlobalActivityTracker* global_tracker = Get(); | 666 GlobalActivityTracker* global_tracker = Get(); |
| 578 if (!global_tracker) | 667 if (!global_tracker) |
| 579 return nullptr; | 668 return nullptr; |
| 580 if (lock_allowed) | 669 if (lock_allowed) |
| 581 return global_tracker->GetOrCreateTrackerForCurrentThread(); | 670 return global_tracker->GetOrCreateTrackerForCurrentThread(); |
| 582 else | 671 else |
| 583 return global_tracker->GetTrackerForCurrentThread(); | 672 return global_tracker->GetTrackerForCurrentThread(); |
| 584 } | 673 } |
| 585 | 674 |
| 675 // An object that manages additional user data, created only upon request. |
| 676 std::unique_ptr<ActivityUserData> user_data_; |
| 677 |
| 586 DISALLOW_COPY_AND_ASSIGN(ScopedThreadActivity); | 678 DISALLOW_COPY_AND_ASSIGN(ScopedThreadActivity); |
| 587 }; | 679 }; |
| 588 | 680 |
| 589 ~GlobalActivityTracker(); | 681 ~GlobalActivityTracker(); |
| 590 | 682 |
| 591 // Creates a global tracker using a given persistent-memory |allocator| and | 683 // Creates a global tracker using a given persistent-memory |allocator| and |
| 592 // providing the given |stack_depth| to each thread tracker it manages. The | 684 // providing the given |stack_depth| to each thread tracker it manages. The |
| 593 // created object is activated so tracking will begin immediately upon return. | 685 // created object is activated so tracking will begin immediately upon return. |
| 594 static void CreateWithAllocator( | 686 static void CreateWithAllocator( |
| 595 std::unique_ptr<PersistentMemoryAllocator> allocator, | 687 std::unique_ptr<PersistentMemoryAllocator> allocator, |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 639 return tracker; | 731 return tracker; |
| 640 return CreateTrackerForCurrentThread(); | 732 return CreateTrackerForCurrentThread(); |
| 641 } | 733 } |
| 642 | 734 |
| 643 // Creates an activity-tracker for the current thread. | 735 // Creates an activity-tracker for the current thread. |
| 644 ThreadActivityTracker* CreateTrackerForCurrentThread(); | 736 ThreadActivityTracker* CreateTrackerForCurrentThread(); |
| 645 | 737 |
| 646 // Releases the activity-tracker for the current thread (for testing only). | 738 // Releases the activity-tracker for the current thread (for testing only). |
| 647 void ReleaseTrackerForCurrentThreadForTesting(); | 739 void ReleaseTrackerForCurrentThreadForTesting(); |
| 648 | 740 |
| 649 // Gets a reference to memory for holding user-defined activity data. If | |
| 650 // the reference is valid, it's memory will be returned. If not, then a | |
| 651 // new reference will be created (and stored) and that memory returned. | |
| 652 void* GetUserDataMemory(PersistentMemoryAllocator::Reference* reference); | |
| 653 | |
| 654 // Releases memory for user-defined activity data. | |
| 655 void ReleaseUserDataMemory(PersistentMemoryAllocator::Reference* reference); | |
| 656 | |
| 657 // Records a log message. The current implementation does NOT recycle these | 741 // Records a log message. The current implementation does NOT recycle these |
| 658 // only store critical messages such as FATAL ones. | 742 // only store critical messages such as FATAL ones. |
| 659 void RecordLogMessage(StringPiece message); | 743 void RecordLogMessage(StringPiece message); |
| 660 | 744 |
| 661 // Accesses the global data record for storing arbitrary key/value pairs. | 745 // Accesses the global data record for storing arbitrary key/value pairs. |
| 662 ActivityUserData& user_data() { return user_data_; } | 746 ActivityUserData& user_data() { return user_data_; } |
| 663 | 747 |
| 664 private: | 748 private: |
| 749 friend class ScopedThreadActivity; |
| 665 friend class ActivityTrackerTest; | 750 friend class ActivityTrackerTest; |
| 666 | 751 |
| 667 enum : int { | 752 enum : int { |
| 668 // The maximum number of threads that can be tracked within a process. If | 753 // The maximum number of threads that can be tracked within a process. If |
| 669 // more than this number run concurrently, tracking of new ones may cease. | 754 // more than this number run concurrently, tracking of new ones may cease. |
| 670 kMaxThreadCount = 100, | 755 kMaxThreadCount = 100, |
| 671 kCachedThreadMemories = 10, | 756 kCachedThreadMemories = 10, |
| 672 kCachedUserDataMemories = 10, | 757 kCachedUserDataMemories = 10, |
| 673 }; | 758 }; |
| 674 | 759 |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 863 ScopedProcessWaitActivity(const void* program_counter, | 948 ScopedProcessWaitActivity(const void* program_counter, |
| 864 const base::Process* process); | 949 const base::Process* process); |
| 865 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); | 950 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); |
| 866 }; | 951 }; |
| 867 #endif | 952 #endif |
| 868 | 953 |
| 869 } // namespace debug | 954 } // namespace debug |
| 870 } // namespace base | 955 } // namespace base |
| 871 | 956 |
| 872 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ | 957 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ |
| OLD | NEW |