Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(698)

Side by Side Diff: base/debug/activity_tracker.h

Issue 2511043003: Support for extracting user-data from activity tracking. (Closed)
Patch Set: rebased Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/debug/activity_analyzer_unittest.cc ('k') | base/debug/activity_tracker.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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_
OLDNEW
« no previous file with comments | « base/debug/activity_analyzer_unittest.cc ('k') | base/debug/activity_tracker.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698