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 correpsonding Set calls. USE WITH CAUTION! There is no guarantee that | |
manzagop (departed)
2016/12/02 22:13:32
typo: correpsonding
bcwhite
2016/12/08 21:30:56
Done.
| |
319 // the referenced memory is accessible or still contains the information | |
manzagop (departed)
2016/12/02 22:13:32
Also mention it might be from a different process?
bcwhite
2016/12/08 21:30:56
Done.
| |
320 // that was originally considered important. | |
321 StringPiece GetReference() const; | |
322 StringPiece GetStringReference() const; | |
323 | |
324 private: | |
325 friend class ActivityUserData; | |
326 | |
327 ValueType type; | |
328 uint64_t short_value; // Used to hold copy of numbers, etc. | |
329 std::string long_value; // Used to hold copy of raw/string data. | |
330 StringPiece ref_value; // Used to hold reference to external data. | |
331 }; | |
332 | |
333 using Snapshot = std::map<std::string, TypedValue>; | |
334 | |
317 ActivityUserData(void* memory, size_t size); | 335 ActivityUserData(void* memory, size_t size); |
318 ~ActivityUserData(); | 336 ~ActivityUserData(); |
319 | 337 |
338 // Gets the unique ID number for this user data. If this changes then the | |
339 // contents have been overwritten by another thread. The return value is | |
340 // always non-zero unless it's actually just a data "sink". | |
341 uint32_t id() const { | |
342 return memory_ ? id_->load(std::memory_order_relaxed) : 0; | |
343 } | |
344 | |
320 // Writes a |value| (as part of a key/value pair) that will be included with | 345 // 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 | 346 // the activity in any reports. The same |name| can be written multiple times |
322 // with each successive call overwriting the previously stored |value|. For | 347 // with each successive call overwriting the previously stored |value|. For |
323 // raw and string values, the maximum size of successive writes is limited by | 348 // 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. | 349 // the first call. The length of "name" is limited to 255 characters. |
325 // | 350 // |
326 // This information is stored on a "best effort" basis. It may be dropped if | 351 // 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 | 352 // the memory buffer is full or the associated activity is beyond the maximum |
328 // recording depth. | 353 // recording depth. |
329 void Set(StringPiece name, const void* memory, size_t size) { | 354 void Set(StringPiece name, const void* memory, size_t size) { |
330 Set(name, RAW_VALUE, memory, size); | 355 Set(name, RAW_VALUE, memory, size); |
331 } | 356 } |
332 void SetString(StringPiece name, StringPiece value) { | 357 void SetString(StringPiece name, StringPiece value) { |
333 Set(name, STRING_VALUE, value.data(), value.length()); | 358 Set(name, STRING_VALUE, value.data(), value.length()); |
334 } | 359 } |
360 void SetBool(StringPiece name, bool value) { | |
361 char cvalue = value ? 1 : 0; | |
362 Set(name, BOOL_VALUE, &cvalue, sizeof(cvalue)); | |
363 } | |
335 void SetChar(StringPiece name, char value) { | 364 void SetChar(StringPiece name, char value) { |
336 Set(name, CHAR_VALUE, &value, sizeof(value)); | 365 Set(name, CHAR_VALUE, &value, sizeof(value)); |
337 } | 366 } |
338 void SetInt(StringPiece name, int64_t value) { | 367 void SetInt(StringPiece name, int64_t value) { |
339 Set(name, SIGNED_VALUE, &value, sizeof(value)); | 368 Set(name, SIGNED_VALUE, &value, sizeof(value)); |
340 } | 369 } |
341 void SetUint(StringPiece name, uint64_t value) { | 370 void SetUint(StringPiece name, uint64_t value) { |
342 Set(name, UNSIGNED_VALUE, &value, sizeof(value)); | 371 Set(name, UNSIGNED_VALUE, &value, sizeof(value)); |
343 } | 372 } |
344 | 373 |
345 // These function as above but don't actually copy the data into the | 374 // 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 | 375 // 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 | 376 // can be used in conjuction with a memory dump to find certain large pieces |
348 // of information. | 377 // of information. |
349 void SetReference(StringPiece name, const void* memory, size_t size) { | 378 void SetReference(StringPiece name, const void* memory, size_t size) { |
350 SetReference(name, RAW_VALUE_REFERENCE, memory, size); | 379 SetReference(name, RAW_VALUE_REFERENCE, memory, size); |
351 } | 380 } |
352 void SetStringReference(StringPiece name, StringPiece value) { | 381 void SetStringReference(StringPiece name, StringPiece value) { |
353 SetReference(name, STRING_VALUE_REFERENCE, value.data(), value.length()); | 382 SetReference(name, STRING_VALUE_REFERENCE, value.data(), value.length()); |
354 } | 383 } |
355 | 384 |
385 // Creates a snapshot of the key/value pairs contained within. The returned | |
386 // data will be fixed, independent of whatever changes afterward. There is | |
387 // protection against concurrent modification of the values but no protection | |
388 // against a complete overwrite of the contents; the caller must ensure that | |
389 // the memory segment is not going to be re-initialized while this runs. | |
390 bool CreateSnapshot(Snapshot* output_snapshot) const; | |
391 | |
392 // Gets the base memory address used for storing data. | |
393 const void* GetBaseAddress(); | |
394 | |
356 private: | 395 private: |
357 FRIEND_TEST_ALL_PREFIXES(ActivityTrackerTest, UserDataTest); | 396 FRIEND_TEST_ALL_PREFIXES(ActivityTrackerTest, UserDataTest); |
358 | 397 |
359 enum : size_t { kMemoryAlignment = sizeof(uint64_t) }; | 398 enum : size_t { kMemoryAlignment = sizeof(uint64_t) }; |
360 | 399 |
361 // A structure used to reference data held outside of persistent memory. | 400 // A structure used to reference data held outside of persistent memory. |
362 struct ReferenceRecord { | 401 struct ReferenceRecord { |
363 uint64_t address; | 402 uint64_t address; |
364 uint64_t size; | 403 uint64_t size; |
365 }; | 404 }; |
(...skipping 19 matching lines...) Expand all Loading... | |
385 std::atomic<uint16_t>* size_ptr; // Address of the actual size of value. | 424 std::atomic<uint16_t>* size_ptr; // Address of the actual size of value. |
386 size_t extent; // The total storage of the value, | 425 size_t extent; // The total storage of the value, |
387 }; // typically rounded up for alignment. | 426 }; // typically rounded up for alignment. |
388 | 427 |
389 void Set(StringPiece name, ValueType type, const void* memory, size_t size); | 428 void Set(StringPiece name, ValueType type, const void* memory, size_t size); |
390 void SetReference(StringPiece name, | 429 void SetReference(StringPiece name, |
391 ValueType type, | 430 ValueType type, |
392 const void* memory, | 431 const void* memory, |
393 size_t size); | 432 size_t size); |
394 | 433 |
395 // TODO(bcwhite): Add Get() methods for Analyzer to use. | 434 // Loads any data already in the memory segment. This allows for accessing |
435 // records created previously. | |
436 void ImportExistingData() const; | |
396 | 437 |
397 std::map<StringPiece, ValueInfo> values_; | 438 // A map of all the values within the memory block, keyed by name for quick |
439 // updates of the values. This is "mutable" because it changes on "const" | |
440 // objects even when the actual data values can't change. | |
441 mutable std::map<StringPiece, ValueInfo> values_; | |
398 | 442 |
399 char* memory_; | 443 // Information about the memory block in which new data can be stored. These |
400 size_t available_; | 444 // are "mutable" because they change even on "const" objects that are just |
445 // skipping already set values. | |
446 mutable char* memory_; | |
447 mutable size_t available_; | |
448 | |
449 // A pointer to the unique ID for this instance. | |
450 std::atomic<uint32_t>* const id_; | |
401 | 451 |
402 base::ThreadChecker thread_checker_; | 452 base::ThreadChecker thread_checker_; |
403 | 453 |
454 // This ID is used to create unique indentifiers for user data so that it's | |
455 // possible to tell if the information has been overwritten. | |
456 static std::atomic<uint32_t> next_id_; | |
457 | |
404 DISALLOW_COPY_AND_ASSIGN(ActivityUserData); | 458 DISALLOW_COPY_AND_ASSIGN(ActivityUserData); |
405 }; | 459 }; |
406 | 460 |
461 // This structure holds a copy of all the internal data at the moment the | |
462 // "snapshot" operation is done. It is disconnected from the live tracker | |
463 // so that continued operation of the thread will not cause changes here. | |
464 struct BASE_EXPORT ActivitySnapshot { | |
465 // Explicit constructor/destructor are needed because of complex types | |
466 // with non-trivial default constructors and destructors. | |
467 ActivitySnapshot(); | |
468 ~ActivitySnapshot(); | |
469 | |
470 // The name of the thread as set when it was created. The name may be | |
471 // truncated due to internal length limitations. | |
472 std::string thread_name; | |
473 | |
474 // The process and thread IDs. These values have no meaning other than | |
475 // they uniquely identify a running process and a running thread within | |
476 // that process. Thread-IDs can be re-used across different processes | |
477 // and both can be re-used after the process/thread exits. | |
478 int64_t process_id = 0; | |
479 int64_t thread_id = 0; | |
480 | |
481 // The current stack of activities that are underway for this thread. It | |
482 // is limited in its maximum size with later entries being left off. | |
483 std::vector<Activity> activity_stack; | |
484 | |
485 // The current total depth of the activity stack, including those later | |
486 // entries not recorded in the |activity_stack| vector. | |
487 uint32_t activity_stack_depth = 0; | |
488 }; | |
489 | |
407 // This class manages tracking a stack of activities for a single thread in | 490 // 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 | 491 // a persistent manner, implementing a bounded-size stack in a fixed-size |
409 // memory allocation. In order to support an operational mode where another | 492 // memory allocation. In order to support an operational mode where another |
410 // thread is analyzing this data in real-time, atomic operations are used | 493 // thread is analyzing this data in real-time, atomic operations are used |
411 // where necessary to guarantee a consistent view from the outside. | 494 // where necessary to guarantee a consistent view from the outside. |
412 // | 495 // |
413 // This class is not generally used directly but instead managed by the | 496 // This class is not generally used directly but instead managed by the |
414 // GlobalActivityTracker instance and updated using Scoped*Activity local | 497 // GlobalActivityTracker instance and updated using Scoped*Activity local |
415 // objects. | 498 // objects. |
416 class BASE_EXPORT ThreadActivityTracker { | 499 class BASE_EXPORT ThreadActivityTracker { |
(...skipping 14 matching lines...) Expand all Loading... | |
431 ScopedActivity(ThreadActivityTracker* tracker, | 514 ScopedActivity(ThreadActivityTracker* tracker, |
432 const void* program_counter, | 515 const void* program_counter, |
433 const void* origin, | 516 const void* origin, |
434 Activity::Type type, | 517 Activity::Type type, |
435 const ActivityData& data); | 518 const ActivityData& data); |
436 ~ScopedActivity(); | 519 ~ScopedActivity(); |
437 | 520 |
438 // Changes some basic metadata about the activity. | 521 // Changes some basic metadata about the activity. |
439 void ChangeTypeAndData(Activity::Type type, const ActivityData& data); | 522 void ChangeTypeAndData(Activity::Type type, const ActivityData& data); |
440 | 523 |
441 // Returns an object for manipulating user data. | 524 protected: |
442 ActivityUserData& user_data(); | |
443 | |
444 private: | |
445 // The thread tracker to which this object reports. It can be null if | 525 // The thread tracker to which this object reports. It can be null if |
446 // activity tracking is not (yet) enabled. | 526 // activity tracking is not (yet) enabled. |
447 ThreadActivityTracker* const tracker_; | 527 ThreadActivityTracker* const tracker_; |
448 | 528 |
449 // An identifier that indicates a specific activity on the stack. | 529 // An identifier that indicates a specific activity on the stack. |
450 ActivityId activity_id_; | 530 ActivityId activity_id_; |
451 | 531 |
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); | 532 DISALLOW_COPY_AND_ASSIGN(ScopedActivity); |
456 }; | 533 }; |
457 | 534 |
458 // A ThreadActivityTracker runs on top of memory that is managed externally. | 535 // 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 | 536 // It must be large enough for the internal header and a few Activity |
460 // blocks. See SizeForStackDepth(). | 537 // blocks. See SizeForStackDepth(). |
461 ThreadActivityTracker(void* base, size_t size); | 538 ThreadActivityTracker(void* base, size_t size); |
462 virtual ~ThreadActivityTracker(); | 539 virtual ~ThreadActivityTracker(); |
463 | 540 |
464 // Indicates that an activity has started from a given |origin| address in | 541 // 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. | 565 // unchanged. The type, if changed, must remain in the same category. |
489 // Changing both is not atomic so a snapshot operation could occur between | 566 // 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. | 567 // the update of |type| and |data| or between update of |data| fields. |
491 void ChangeActivity(ActivityId id, | 568 void ChangeActivity(ActivityId id, |
492 Activity::Type type, | 569 Activity::Type type, |
493 const ActivityData& data); | 570 const ActivityData& data); |
494 | 571 |
495 // Indicates that an activity has completed. | 572 // Indicates that an activity has completed. |
496 void PopActivity(ActivityId id); | 573 void PopActivity(ActivityId id); |
497 | 574 |
498 // Returns an object capable of storing arbitrary user data. | 575 // Sets the user-data information for an activity. |
499 std::unique_ptr<ActivityUserData> GetUserData(ActivityId id); | 576 std::unique_ptr<ActivityUserData> GetUserData( |
577 ActivityId id, | |
578 ActivityTrackerMemoryAllocator* allocator); | |
579 | |
580 // Returns if there is true use-data associated with a given ActivityId since | |
581 // it's possible than any returned object is just a sink. | |
582 bool HasUserData(ActivityId id); | |
583 | |
584 // Release the user-data information for an activity. | |
585 void ReleaseUserData(ActivityId id, | |
586 ActivityTrackerMemoryAllocator* allocator); | |
500 | 587 |
501 // Returns whether the current data is valid or not. It is not valid if | 588 // 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. | 589 // corruption has been detected in the header or other data structures. |
503 bool IsValid() const; | 590 bool IsValid() const; |
504 | 591 |
505 // Gets a copy of the tracker contents for analysis. Returns false if a | 592 // 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 | 593 // snapshot was not possible, perhaps because the data is not valid; the |
507 // contents of |output_snapshot| are undefined in that case. The current | 594 // contents of |output_snapshot| are undefined in that case. The current |
508 // implementation does not support concurrent snapshot operations. | 595 // implementation does not support concurrent snapshot operations. |
509 bool Snapshot(ActivitySnapshot* output_snapshot) const; | 596 bool CreateSnapshot(ActivitySnapshot* output_snapshot) const; |
510 | 597 |
511 // Calculates the memory size required for a given stack depth, including | 598 // Calculates the memory size required for a given stack depth, including |
512 // the internal header structure for the stack. | 599 // the internal header structure for the stack. |
513 static size_t SizeForStackDepth(int stack_depth); | 600 static size_t SizeForStackDepth(int stack_depth); |
514 | 601 |
515 private: | 602 private: |
516 friend class ActivityTrackerTest; | 603 friend class ActivityTrackerTest; |
517 | 604 |
518 Header* const header_; // Pointer to the Header structure. | 605 Header* const header_; // Pointer to the Header structure. |
519 Activity* const stack_; // The stack of activities. | 606 Activity* const stack_; // The stack of activities. |
(...skipping 12 matching lines...) Expand all Loading... | |
532 // for the data to be analyzed by a parallel process or even post-mortem. | 619 // for the data to be analyzed by a parallel process or even post-mortem. |
533 class BASE_EXPORT GlobalActivityTracker { | 620 class BASE_EXPORT GlobalActivityTracker { |
534 public: | 621 public: |
535 // Type identifiers used when storing in persistent memory so they can be | 622 // 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 | 623 // 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 | 624 // 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 | 625 // 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 | 626 // will be safely ignored. These are public so that an external process |
540 // can recognize records of this type within an allocator. | 627 // can recognize records of this type within an allocator. |
541 enum : uint32_t { | 628 enum : uint32_t { |
542 kTypeIdActivityTracker = 0x5D7381AF + 3, // SHA1(ActivityTracker) v3 | 629 kTypeIdActivityTracker = 0x5D7381AF + 3, // SHA1(ActivityTracker) v3 |
543 kTypeIdUserDataRecord = 0x615EDDD7 + 1, // SHA1(UserDataRecord) v1 | 630 kTypeIdUserDataRecord = 0x615EDDD7 + 2, // SHA1(UserDataRecord) v2 |
544 kTypeIdGlobalDataRecord = 0xAFE61ABE + 1, // SHA1(GlobalDataRecord) v1 | 631 kTypeIdGlobalDataRecord = kTypeIdUserDataRecord + 0x5F1184F7, // Global |
545 | 632 |
546 kTypeIdActivityTrackerFree = ~kTypeIdActivityTracker, | 633 kTypeIdActivityTrackerFree = ~kTypeIdActivityTracker, |
547 kTypeIdUserDataRecordFree = ~kTypeIdUserDataRecord, | 634 kTypeIdUserDataRecordFree = ~kTypeIdUserDataRecord, |
548 }; | 635 }; |
549 | 636 |
550 // This is a thin wrapper around the thread-tracker's ScopedActivity that | 637 // This is a thin wrapper around the thread-tracker's ScopedActivity that |
551 // accesses the global tracker to provide some of the information, notably | 638 // accesses the global tracker to provide some of the information, notably |
552 // which thread-tracker to use. It is safe to create even if activity | 639 // which thread-tracker to use. It is safe to create even if activity |
553 // tracking is not enabled. | 640 // tracking is not enabled. |
554 class BASE_EXPORT ScopedThreadActivity | 641 class BASE_EXPORT ScopedThreadActivity |
555 : public ThreadActivityTracker::ScopedActivity { | 642 : public ThreadActivityTracker::ScopedActivity { |
556 public: | 643 public: |
557 ScopedThreadActivity(const void* program_counter, | 644 ScopedThreadActivity(const void* program_counter, |
558 const void* origin, | 645 const void* origin, |
559 Activity::Type type, | 646 Activity::Type type, |
560 const ActivityData& data, | 647 const ActivityData& data, |
561 bool lock_allowed) | 648 bool lock_allowed); |
562 : ThreadActivityTracker::ScopedActivity( | 649 ~ScopedThreadActivity(); |
563 GetOrCreateTracker(lock_allowed), | 650 |
564 program_counter, | 651 // Returns an object for manipulating user data. |
565 origin, | 652 ActivityUserData& user_data(); |
566 type, | |
567 data) {} | |
568 | 653 |
569 private: | 654 private: |
570 // Gets (or creates) a tracker for the current thread. If locking is not | 655 // Gets (or creates) a tracker for the current thread. If locking is not |
571 // allowed (because a lock is being tracked which would cause recursion) | 656 // allowed (because a lock is being tracked which would cause recursion) |
572 // then the attempt to create one if none found will be skipped. Once | 657 // then the attempt to create one if none found will be skipped. Once |
573 // the tracker for this thread has been created for other reasons, locks | 658 // the tracker for this thread has been created for other reasons, locks |
574 // will be tracked. The thread-tracker uses locks. | 659 // will be tracked. The thread-tracker uses locks. |
575 static ThreadActivityTracker* GetOrCreateTracker(bool lock_allowed) { | 660 static ThreadActivityTracker* GetOrCreateTracker(bool lock_allowed) { |
576 GlobalActivityTracker* global_tracker = Get(); | 661 GlobalActivityTracker* global_tracker = Get(); |
577 if (!global_tracker) | 662 if (!global_tracker) |
578 return nullptr; | 663 return nullptr; |
579 if (lock_allowed) | 664 if (lock_allowed) |
580 return global_tracker->GetOrCreateTrackerForCurrentThread(); | 665 return global_tracker->GetOrCreateTrackerForCurrentThread(); |
581 else | 666 else |
582 return global_tracker->GetTrackerForCurrentThread(); | 667 return global_tracker->GetTrackerForCurrentThread(); |
583 } | 668 } |
584 | 669 |
670 // An object that manages additional user data, created only upon request. | |
671 std::unique_ptr<ActivityUserData> user_data_; | |
672 | |
585 DISALLOW_COPY_AND_ASSIGN(ScopedThreadActivity); | 673 DISALLOW_COPY_AND_ASSIGN(ScopedThreadActivity); |
586 }; | 674 }; |
587 | 675 |
588 ~GlobalActivityTracker(); | 676 ~GlobalActivityTracker(); |
589 | 677 |
590 // Creates a global tracker using a given persistent-memory |allocator| and | 678 // Creates a global tracker using a given persistent-memory |allocator| and |
591 // providing the given |stack_depth| to each thread tracker it manages. The | 679 // providing the given |stack_depth| to each thread tracker it manages. The |
592 // created object is activated so tracking will begin immediately upon return. | 680 // created object is activated so tracking will begin immediately upon return. |
593 static void CreateWithAllocator( | 681 static void CreateWithAllocator( |
594 std::unique_ptr<PersistentMemoryAllocator> allocator, | 682 std::unique_ptr<PersistentMemoryAllocator> allocator, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
638 return tracker; | 726 return tracker; |
639 return CreateTrackerForCurrentThread(); | 727 return CreateTrackerForCurrentThread(); |
640 } | 728 } |
641 | 729 |
642 // Creates an activity-tracker for the current thread. | 730 // Creates an activity-tracker for the current thread. |
643 ThreadActivityTracker* CreateTrackerForCurrentThread(); | 731 ThreadActivityTracker* CreateTrackerForCurrentThread(); |
644 | 732 |
645 // Releases the activity-tracker for the current thread (for testing only). | 733 // Releases the activity-tracker for the current thread (for testing only). |
646 void ReleaseTrackerForCurrentThreadForTesting(); | 734 void ReleaseTrackerForCurrentThreadForTesting(); |
647 | 735 |
648 // Gets a reference to memory for holding user-defined activity data. If | |
649 // the reference is valid, it's memory will be returned. If not, then a | |
650 // new reference will be created (and stored) and that memory returned. | |
651 void* GetUserDataMemory(PersistentMemoryAllocator::Reference* reference); | |
652 | |
653 // Releases memory for user-defined activity data. | |
654 void ReleaseUserDataMemory(PersistentMemoryAllocator::Reference* reference); | |
655 | |
656 // Accesses the global data record for storing arbitrary key/value pairs. | 736 // Accesses the global data record for storing arbitrary key/value pairs. |
657 ActivityUserData& user_data() { return user_data_; } | 737 ActivityUserData& user_data() { return user_data_; } |
658 | 738 |
659 private: | 739 private: |
740 friend class ScopedThreadActivity; | |
660 friend class ActivityTrackerTest; | 741 friend class ActivityTrackerTest; |
661 | 742 |
662 enum : int { | 743 enum : int { |
663 // The maximum number of threads that can be tracked within a process. If | 744 // The maximum number of threads that can be tracked within a process. If |
664 // more than this number run concurrently, tracking of new ones may cease. | 745 // more than this number run concurrently, tracking of new ones may cease. |
665 kMaxThreadCount = 100, | 746 kMaxThreadCount = 100, |
666 kCachedThreadMemories = 10, | 747 kCachedThreadMemories = 10, |
667 kCachedUserDataMemories = 10, | 748 kCachedUserDataMemories = 10, |
668 }; | 749 }; |
669 | 750 |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
858 ScopedProcessWaitActivity(const void* program_counter, | 939 ScopedProcessWaitActivity(const void* program_counter, |
859 const base::Process* process); | 940 const base::Process* process); |
860 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); | 941 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); |
861 }; | 942 }; |
862 #endif | 943 #endif |
863 | 944 |
864 } // namespace debug | 945 } // namespace debug |
865 } // namespace base | 946 } // namespace base |
866 | 947 |
867 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ | 948 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ |
OLD | NEW |