Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Activity tracking provides a low-overhead method of collecting information | 5 // Activity tracking provides a low-overhead method of collecting information |
| 6 // about the state of the application for analysis both while it is running | 6 // about the state of the application for analysis both while it is running |
| 7 // and after it has terminated unexpectedly. Its primary purpose is to help | 7 // and after it has terminated unexpectedly. Its primary purpose is to help |
| 8 // locate reasons the browser becomes unresponsive by providing insight into | 8 // locate reasons the browser becomes unresponsive by providing insight into |
| 9 // what all the various threads and processes are (or were) doing. | 9 // what all the various threads and processes are (or were) doing. |
| 10 | 10 |
| 11 #ifndef BASE_DEBUG_ACTIVITY_TRACKER_H_ | 11 #ifndef BASE_DEBUG_ACTIVITY_TRACKER_H_ |
| 12 #define BASE_DEBUG_ACTIVITY_TRACKER_H_ | 12 #define BASE_DEBUG_ACTIVITY_TRACKER_H_ |
| 13 | 13 |
| 14 // std::atomic is undesired due to performance issues when used as global | 14 // std::atomic is undesired due to performance issues when used as global |
| 15 // variables. There are no such instances here. This module uses the | 15 // variables. There are no such instances here. This module uses the |
| 16 // PersistentMemoryAllocator which also uses std::atomic and is written | 16 // PersistentMemoryAllocator which also uses std::atomic and is written |
| 17 // by the same author. | 17 // by the same author. |
| 18 #include <atomic> | 18 #include <atomic> |
| 19 #include <map> | |
| 19 #include <memory> | 20 #include <memory> |
| 20 #include <string> | 21 #include <string> |
| 21 #include <vector> | 22 #include <vector> |
| 22 | 23 |
| 23 #include "base/base_export.h" | 24 #include "base/base_export.h" |
| 25 #include "base/gtest_prod_util.h" | |
| 24 #include "base/location.h" | 26 #include "base/location.h" |
| 25 #include "base/metrics/persistent_memory_allocator.h" | 27 #include "base/metrics/persistent_memory_allocator.h" |
| 26 #include "base/threading/platform_thread.h" | 28 #include "base/threading/platform_thread.h" |
| 27 #include "base/threading/thread_checker.h" | 29 #include "base/threading/thread_checker.h" |
| 28 #include "base/threading/thread_local_storage.h" | 30 #include "base/threading/thread_local_storage.h" |
| 29 | 31 |
| 30 namespace base { | 32 namespace base { |
| 31 | 33 |
| 32 struct PendingTask; | 34 struct PendingTask; |
| 33 | 35 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 129 // A helper class that is used for managing memory allocations within a | 131 // A helper class that is used for managing memory allocations within a |
| 130 // persistent memory allocator. Instances of this class are NOT thread-safe. | 132 // persistent memory allocator. Instances of this class are NOT thread-safe. |
| 131 // Use from a single thread or protect access with a lock. | 133 // Use from a single thread or protect access with a lock. |
| 132 class ActivityTrackerMemoryAllocator { | 134 class ActivityTrackerMemoryAllocator { |
| 133 public: | 135 public: |
| 134 using Reference = PersistentMemoryAllocator::Reference; | 136 using Reference = PersistentMemoryAllocator::Reference; |
| 135 | 137 |
| 136 // Creates a instance for allocating objects of a fixed |object_type|, a | 138 // Creates a instance for allocating objects of a fixed |object_type|, a |
| 137 // corresponding |object_free| type, and the |object_size|. An internal | 139 // corresponding |object_free| type, and the |object_size|. An internal |
| 138 // cache of the last |cache_size| released references will be kept for | 140 // cache of the last |cache_size| released references will be kept for |
| 139 // quick future fetches. | 141 // quick future fetches. If |make_iterable| then allocated objects will |
| 142 // be marked "iterable" in the allocator. | |
| 140 ActivityTrackerMemoryAllocator(PersistentMemoryAllocator* allocator, | 143 ActivityTrackerMemoryAllocator(PersistentMemoryAllocator* allocator, |
| 141 uint32_t object_type, | 144 uint32_t object_type, |
| 142 uint32_t object_free_type, | 145 uint32_t object_free_type, |
| 143 size_t object_size, | 146 size_t object_size, |
| 144 size_t cache_size); | 147 size_t cache_size, |
| 148 bool make_iterable); | |
| 145 ~ActivityTrackerMemoryAllocator(); | 149 ~ActivityTrackerMemoryAllocator(); |
| 146 | 150 |
| 147 // 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 |
| 148 // 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. |
| 149 Reference GetObjectReference(); | 153 Reference GetObjectReference(); |
| 150 | 154 |
| 151 // Returns an object to the "free" pool. | 155 // Returns an object to the "free" pool. |
| 152 void ReleaseObjectReference(Reference ref); | 156 void ReleaseObjectReference(Reference ref); |
| 153 | 157 |
| 154 // The current "used size" of the internal cache, visible for testing. | 158 // The current "used size" of the internal cache, visible for testing. |
| 155 size_t cache_used() const { return cache_used_; } | 159 size_t cache_used() const { return cache_used_; } |
| 156 | 160 |
| 157 private: | 161 private: |
| 158 PersistentMemoryAllocator* const allocator_; | 162 PersistentMemoryAllocator* const allocator_; |
| 159 const uint32_t object_type_; | 163 const uint32_t object_type_; |
| 160 const uint32_t object_free_type_; | 164 const uint32_t object_free_type_; |
| 161 const size_t object_size_; | 165 const size_t object_size_; |
| 162 const size_t cache_size_; | 166 const size_t cache_size_; |
| 167 const bool make_iterable_; | |
| 163 | 168 |
| 164 // An iterator for going through persistent memory looking for free'd objects. | 169 // An iterator for going through persistent memory looking for free'd objects. |
| 165 PersistentMemoryAllocator::Iterator iterator_; | 170 PersistentMemoryAllocator::Iterator iterator_; |
| 166 | 171 |
| 167 // The cache of released object memories. | 172 // The cache of released object memories. |
| 168 std::unique_ptr<Reference[]> cache_values_; | 173 std::unique_ptr<Reference[]> cache_values_; |
| 169 size_t cache_used_; | 174 size_t cache_used_; |
| 170 | 175 |
| 171 DISALLOW_COPY_AND_ASSIGN(ActivityTrackerMemoryAllocator); | 176 DISALLOW_COPY_AND_ASSIGN(ActivityTrackerMemoryAllocator); |
| 172 }; | 177 }; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 229 // it null. | 234 // it null. |
| 230 uint64_t origin_address; | 235 uint64_t origin_address; |
| 231 | 236 |
| 232 // Array of program-counters that make up the top of the call stack. | 237 // Array of program-counters that make up the top of the call stack. |
| 233 // Despite the fixed size, this list is always null-terminated. Entries | 238 // Despite the fixed size, this list is always null-terminated. Entries |
| 234 // after the terminator have no meaning and may or may not also be null. | 239 // after the terminator have no meaning and may or may not also be null. |
| 235 // The list will be completely empty if call-stack collection is not | 240 // The list will be completely empty if call-stack collection is not |
| 236 // enabled. | 241 // enabled. |
| 237 uint64_t call_stack[kActivityCallStackSize]; | 242 uint64_t call_stack[kActivityCallStackSize]; |
| 238 | 243 |
| 244 // Reference to arbitrary user data within the persistent memory segment. | |
| 245 uint32_t user_data; | |
| 246 | |
| 239 // The (enumerated) type of the activity. This defines what fields of the | 247 // The (enumerated) type of the activity. This defines what fields of the |
| 240 // |data| record are valid. | 248 // |data| record are valid. |
| 241 uint8_t activity_type; | 249 uint8_t activity_type; |
| 242 | 250 |
| 243 // Padding to ensure that the next member begins on a 64-bit boundary | 251 // Padding to ensure that the next member begins on a 64-bit boundary |
| 244 // even on 32-bit builds which ensures inter-operability between CPU | 252 // even on 32-bit builds which ensures inter-operability between CPU |
| 245 // architectures. New fields can be taken from this space. | 253 // architectures. New fields can be taken from this space. |
| 246 uint8_t padding[7]; | 254 uint8_t padding[3]; |
| 247 | 255 |
| 248 // Information specific to the |activity_type|. | 256 // Information specific to the |activity_type|. |
| 249 ActivityData data; | 257 ActivityData data; |
| 250 | 258 |
| 251 static void FillFrom(Activity* activity, | 259 static void FillFrom(Activity* activity, |
| 252 const void* origin, | 260 const void* origin, |
| 253 Type type, | 261 Type type, |
| 254 const ActivityData& data); | 262 const ActivityData& data); |
| 255 }; | 263 }; |
| 256 | 264 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 277 // The current stack of activities that are underway for this thread. It | 285 // The current stack of activities that are underway for this thread. It |
| 278 // is limited in its maximum size with later entries being left off. | 286 // is limited in its maximum size with later entries being left off. |
| 279 std::vector<Activity> activity_stack; | 287 std::vector<Activity> activity_stack; |
| 280 | 288 |
| 281 // The current total depth of the activity stack, including those later | 289 // The current total depth of the activity stack, including those later |
| 282 // entries not recorded in the |activity_stack| vector. | 290 // entries not recorded in the |activity_stack| vector. |
| 283 uint32_t activity_stack_depth = 0; | 291 uint32_t activity_stack_depth = 0; |
| 284 }; | 292 }; |
| 285 | 293 |
| 286 | 294 |
| 295 class BASE_EXPORT ActivityUserData { | |
|
manzagop (departed)
2016/11/11 17:01:42
nit: mention it's meant to be used on a single thr
manzagop (departed)
2016/11/11 17:01:42
Does this need atomic operations as well (to ensur
manzagop (departed)
2016/11/11 17:01:42
nit: class comment, perhaps with a high level ment
bcwhite
2016/11/14 15:08:42
Done.
bcwhite
2016/11/14 15:08:42
Done.
bcwhite
2016/11/14 15:08:42
Good point. I've gotten in to thinking only of th
| |
| 296 // List of known value type. EXTERNAL types must immediately follow the non- | |
| 297 // external types. | |
| 298 enum ValueType : uint8_t { | |
| 299 EMPTY_VALUE, | |
| 300 RAW_VALUE, | |
| 301 EXTERNAL_RAW_VALUE, | |
|
manzagop (departed)
2016/11/11 17:01:42
Would RAW_VALUE_REFERENCE be more descriptive? I w
bcwhite
2016/11/14 15:08:42
I think that's better.
| |
| 302 STRING_VALUE, | |
| 303 EXTERNAL_STRING_VALUE, | |
| 304 CHAR_VALUE, | |
| 305 SIGNED_VALUE, | |
| 306 UNSIGNED_VALUE, | |
| 307 }; | |
| 308 | |
| 309 public: | |
| 310 ActivityUserData(void* memory, size_t size); | |
| 311 ~ActivityUserData(); | |
| 312 | |
| 313 // Write the value (as part of a key/value pair) that will be included with | |
| 314 // the activity in any reports. The same |name| can be written multiple times | |
| 315 // with each successive call overwriting the previous value. The maximum size | |
|
manzagop (departed)
2016/11/11 17:01:42
nit: I think it could be clearer that it's the val
bcwhite
2016/11/14 15:08:42
Done.
| |
| 316 // (for raw and string values) is limited by the first call, however. | |
|
manzagop (departed)
2016/11/11 17:01:42
Mention @pre name.length() <= std::numeric_limits<
manzagop (departed)
2016/11/11 17:01:42
Mention that if memory is lacking, the value may b
bcwhite
2016/11/14 15:08:42
Done.
bcwhite
2016/11/14 15:08:42
Done.
| |
| 317 void Set(StringPiece name, const void* memory, size_t size) { | |
| 318 Set(name, RAW_VALUE, memory, size); | |
| 319 } | |
| 320 void SetString(StringPiece name, StringPiece value) { | |
| 321 Set(name, STRING_VALUE, value.data(), value.length()); | |
| 322 } | |
| 323 void SetChar(StringPiece name, char value) { | |
| 324 Set(name, CHAR_VALUE, &value, sizeof(value)); | |
| 325 } | |
| 326 void SetInt(StringPiece name, int64_t value) { | |
| 327 Set(name, SIGNED_VALUE, &value, sizeof(value)); | |
| 328 } | |
| 329 void SetUint(StringPiece name, uint64_t value) { | |
| 330 Set(name, UNSIGNED_VALUE, &value, sizeof(value)); | |
| 331 } | |
| 332 | |
| 333 // These function as above but don't actually copy the data into the | |
| 334 // persistent memory. The store unaltered pointers along with a size that | |
|
manzagop (departed)
2016/11/11 17:01:42
typo: The -> They
bcwhite
2016/11/14 15:08:43
Done.
| |
| 335 // can be used in conjuction with a memory dump to find certain pieces of | |
| 336 // information. | |
| 337 void SetExternal(StringPiece name, const void* memory, size_t size) { | |
| 338 SetExternal(name, EXTERNAL_RAW_VALUE, memory, size); | |
| 339 } | |
| 340 void SetExternalString(StringPiece name, StringPiece value) { | |
| 341 SetExternal(name, EXTERNAL_RAW_VALUE, value.data(), value.length()); | |
| 342 } | |
| 343 | |
| 344 private: | |
| 345 FRIEND_TEST_ALL_PREFIXES(ActivityTrackerTest, UserDataTest); | |
| 346 | |
| 347 enum : size_t { kMemoryAlignment = sizeof(uint64_t) }; | |
| 348 | |
| 349 struct ValueInfo { | |
| 350 ValueInfo(); | |
| 351 ValueInfo(ValueInfo&&); | |
| 352 ~ValueInfo(); | |
| 353 | |
| 354 StringPiece name; | |
| 355 void* memory; | |
| 356 size_t size; | |
| 357 size_t extent; | |
|
manzagop (departed)
2016/11/11 17:01:42
I wasn't sure which of size/extent was which witho
bcwhite
2016/11/14 15:08:43
Done.
| |
| 358 ValueType type; | |
| 359 }; | |
| 360 | |
| 361 struct Header { | |
| 362 uint8_t type; | |
| 363 uint8_t name_size; | |
| 364 uint16_t value_size; | |
|
manzagop (departed)
2016/11/11 17:01:42
Is this the size or the extent?
bcwhite
2016/11/14 15:08:42
Size. Comments added.
| |
| 365 uint16_t record_size; | |
|
manzagop (departed)
2016/11/11 17:01:42
Comment on whether inclusive of header size?
bcwhite
2016/11/14 15:08:42
Inclusive.
| |
| 366 }; | |
| 367 | |
| 368 struct ExternalRecord { | |
| 369 uint64_t address; | |
| 370 uint64_t size; | |
| 371 }; | |
| 372 | |
| 373 void Set(StringPiece name, ValueType type, const void* memory, size_t size); | |
| 374 void SetExternal(StringPiece name, | |
| 375 ValueType type, | |
| 376 const void* memory, | |
| 377 size_t size); | |
| 378 | |
| 379 // TODO(bcwhite): Add Get() methods for Analyzer to use. | |
| 380 | |
| 381 std::map<StringPiece, ValueInfo> values_; | |
| 382 | |
| 383 char* memory_; | |
| 384 size_t available_; | |
| 385 | |
| 386 base::ThreadChecker thread_checker_; | |
| 387 | |
| 388 DISALLOW_COPY_AND_ASSIGN(ActivityUserData); | |
| 389 }; | |
| 390 | |
| 391 | |
| 287 // This class manages tracking a stack of activities for a single thread in | 392 // This class manages tracking a stack of activities for a single thread in |
| 288 // a persistent manner, implementing a bounded-size stack in a fixed-size | 393 // a persistent manner, implementing a bounded-size stack in a fixed-size |
| 289 // memory allocation. In order to support an operational mode where another | 394 // memory allocation. In order to support an operational mode where another |
| 290 // thread is analyzing this data in real-time, atomic operations are used | 395 // thread is analyzing this data in real-time, atomic operations are used |
| 291 // where necessary to guarantee a consistent view from the outside. | 396 // where necessary to guarantee a consistent view from the outside. |
| 292 // | 397 // |
| 293 // This class is not generally used directly but instead managed by the | 398 // This class is not generally used directly but instead managed by the |
| 294 // GlobalActivityTracker instance and updated using Scoped*Activity local | 399 // GlobalActivityTracker instance and updated using Scoped*Activity local |
| 295 // objects. | 400 // objects. |
| 296 class BASE_EXPORT ThreadActivityTracker { | 401 class BASE_EXPORT ThreadActivityTracker { |
| 297 public: | 402 public: |
| 403 using ActivityId = uint32_t; | |
| 404 | |
| 298 // This is the base class for having the compiler manage an activity on the | 405 // This is the base class for having the compiler manage an activity on the |
| 299 // tracker's stack. It does nothing but call methods on the passed |tracker| | 406 // tracker's stack. It does nothing but call methods on the passed |tracker| |
| 300 // if it is not null, making it safe (and cheap) to create these objects | 407 // if it is not null, making it safe (and cheap) to create these objects |
| 301 // even if activity tracking is not enabled. | 408 // even if activity tracking is not enabled. |
| 302 class BASE_EXPORT ScopedActivity { | 409 class BASE_EXPORT ScopedActivity { |
| 303 public: | 410 public: |
| 304 ScopedActivity(ThreadActivityTracker* tracker, | 411 ScopedActivity(ThreadActivityTracker* tracker, |
| 305 const void* origin, | 412 const void* origin, |
| 306 Activity::Type type, | 413 Activity::Type type, |
| 307 const ActivityData& data) | 414 const ActivityData& data); |
| 308 : tracker_(tracker) { | 415 ~ScopedActivity(); |
| 309 if (tracker_) | |
| 310 tracker_->PushActivity(origin, type, data); | |
| 311 } | |
| 312 | 416 |
| 313 ~ScopedActivity() { | 417 // Changes some basic metadata about the activity. |
| 314 if (tracker_) | 418 void ChangeTypeAndData(Activity::Type type, const ActivityData& data); |
| 315 tracker_->PopActivity(); | |
| 316 } | |
| 317 | 419 |
| 318 void ChangeTypeAndData(Activity::Type type, const ActivityData& data) { | 420 // Returns an object for manipulating user data. |
| 319 if (tracker_) | 421 ActivityUserData& user_data(); |
| 320 tracker_->ChangeActivity(type, data); | |
| 321 } | |
| 322 | 422 |
| 323 private: | 423 private: |
| 324 // The thread tracker to which this object reports. It can be null if | 424 // The thread tracker to which this object reports. It can be null if |
| 325 // activity tracking is not (yet) enabled. | 425 // activity tracking is not (yet) enabled. |
| 326 ThreadActivityTracker* const tracker_; | 426 ThreadActivityTracker* const tracker_; |
| 327 | 427 |
| 428 // An identifier that indicates a specific activity on the stack. | |
| 429 ActivityId activity_id_; | |
| 430 | |
| 431 // An object that manages additional user data, created only upon request. | |
| 432 std::unique_ptr<ActivityUserData> user_data_; | |
| 433 | |
| 328 DISALLOW_COPY_AND_ASSIGN(ScopedActivity); | 434 DISALLOW_COPY_AND_ASSIGN(ScopedActivity); |
| 329 }; | 435 }; |
| 330 | 436 |
| 331 // A ThreadActivityTracker runs on top of memory that is managed externally. | 437 // A ThreadActivityTracker runs on top of memory that is managed externally. |
| 332 // It must be large enough for the internal header and a few Activity | 438 // It must be large enough for the internal header and a few Activity |
| 333 // blocks. See SizeForStackDepth(). | 439 // blocks. See SizeForStackDepth(). |
| 334 ThreadActivityTracker(void* base, size_t size); | 440 ThreadActivityTracker(void* base, size_t size); |
| 335 virtual ~ThreadActivityTracker(); | 441 virtual ~ThreadActivityTracker(); |
| 336 | 442 |
| 337 // Indicates that an activity has started from a given |origin| address in | 443 // Indicates that an activity has started from a given |origin| address in |
| 338 // the code, though it can be null if the creator's address is not known. | 444 // the code, though it can be null if the creator's address is not known. |
| 339 // The |type| and |data| describe the activity. | 445 // The |type| and |data| describe the activity. Returned is an ID that can |
| 340 void PushActivity(const void* origin, | 446 // be used to adjust the pushed activity. |
| 341 Activity::Type type, | 447 ActivityId PushActivity(const void* origin, |
| 342 const ActivityData& data); | 448 Activity::Type type, |
| 449 const ActivityData& data); | |
| 343 | 450 |
| 344 // Changes the activity |type| and |data| of the top-most entry on the stack. | 451 // Changes the activity |type| and |data| of the top-most entry on the stack. |
| 345 // This is useful if the information has changed and it is desireable to | 452 // This is useful if the information has changed and it is desireable to |
| 346 // track that change without creating a new stack entry. If the type is | 453 // track that change without creating a new stack entry. If the type is |
| 347 // ACT_NULL or the data is kNullActivityData then that value will remain | 454 // ACT_NULL or the data is kNullActivityData then that value will remain |
| 348 // unchanged. The type, if changed, must remain in the same category. | 455 // unchanged. The type, if changed, must remain in the same category. |
| 349 // Changing both is not atomic so a snapshot operation could occur between | 456 // Changing both is not atomic so a snapshot operation could occur between |
| 350 // the update of |type| and |data| or between update of |data| fields. | 457 // the update of |type| and |data| or between update of |data| fields. |
| 351 void ChangeActivity(Activity::Type type, const ActivityData& data); | 458 void ChangeActivity(ActivityId id, |
| 459 Activity::Type type, | |
| 460 const ActivityData& data); | |
| 352 | 461 |
| 353 // Indicates that an activity has completed. | 462 // Indicates that an activity has completed. |
| 354 void PopActivity(); | 463 void PopActivity(ActivityId id); |
| 464 | |
| 465 // Returns an object capable of storing arbitrary user data. | |
| 466 std::unique_ptr<ActivityUserData> GetUserData(ActivityId id); | |
| 355 | 467 |
| 356 // Returns whether the current data is valid or not. It is not valid if | 468 // Returns whether the current data is valid or not. It is not valid if |
| 357 // corruption has been detected in the header or other data structures. | 469 // corruption has been detected in the header or other data structures. |
| 358 bool IsValid() const; | 470 bool IsValid() const; |
| 359 | 471 |
| 360 // Gets a copy of the tracker contents for analysis. Returns false if a | 472 // Gets a copy of the tracker contents for analysis. Returns false if a |
| 361 // snapshot was not possible, perhaps because the data is not valid; the | 473 // snapshot was not possible, perhaps because the data is not valid; the |
| 362 // contents of |output_snapshot| are undefined in that case. The current | 474 // contents of |output_snapshot| are undefined in that case. The current |
| 363 // implementation does not support concurrent snapshot operations. | 475 // implementation does not support concurrent snapshot operations. |
| 364 bool Snapshot(ActivitySnapshot* output_snapshot) const; | 476 bool Snapshot(ActivitySnapshot* output_snapshot) const; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 392 // for the data to be analyzed by a parallel process or even post-mortem. | 504 // for the data to be analyzed by a parallel process or even post-mortem. |
| 393 class BASE_EXPORT GlobalActivityTracker { | 505 class BASE_EXPORT GlobalActivityTracker { |
| 394 public: | 506 public: |
| 395 // Type identifiers used when storing in persistent memory so they can be | 507 // Type identifiers used when storing in persistent memory so they can be |
| 396 // identified during extraction; the first 4 bytes of the SHA1 of the name | 508 // identified during extraction; the first 4 bytes of the SHA1 of the name |
| 397 // is used as a unique integer. A "version number" is added to the base | 509 // is used as a unique integer. A "version number" is added to the base |
| 398 // so that, if the structure of that object changes, stored older versions | 510 // so that, if the structure of that object changes, stored older versions |
| 399 // will be safely ignored. These are public so that an external process | 511 // will be safely ignored. These are public so that an external process |
| 400 // can recognize records of this type within an allocator. | 512 // can recognize records of this type within an allocator. |
| 401 enum : uint32_t { | 513 enum : uint32_t { |
| 402 kTypeIdActivityTracker = 0x5D7381AF + 1, // SHA1(ActivityTracker) v1 | 514 kTypeIdActivityTracker = 0x5D7381AF + 2, // SHA1(ActivityTracker) v2 |
| 515 kTypeIdUserDataRecord = 0x615EDDD7 + 1, // SHA1(UserDataRecord) v1 | |
| 516 kTypeIdGlobalDataRecord = 0xAFE61ABE + 1, // SHA1(GlobalDataRecord) v1 | |
| 517 | |
| 403 kTypeIdActivityTrackerFree = ~kTypeIdActivityTracker, | 518 kTypeIdActivityTrackerFree = ~kTypeIdActivityTracker, |
| 519 kTypeIdUserDataRecordFree = ~kTypeIdUserDataRecord, | |
| 404 }; | 520 }; |
| 405 | 521 |
| 406 // This is a thin wrapper around the thread-tracker's ScopedActivity that | 522 // This is a thin wrapper around the thread-tracker's ScopedActivity that |
| 407 // accesses the global tracker to provide some of the information, notably | 523 // accesses the global tracker to provide some of the information, notably |
| 408 // which thread-tracker to use. It is safe to create even if activity | 524 // which thread-tracker to use. It is safe to create even if activity |
| 409 // tracking is not enabled. | 525 // tracking is not enabled. |
| 410 class BASE_EXPORT ScopedThreadActivity | 526 class BASE_EXPORT ScopedThreadActivity |
| 411 : public ThreadActivityTracker::ScopedActivity { | 527 : public ThreadActivityTracker::ScopedActivity { |
| 412 public: | 528 public: |
| 413 ScopedThreadActivity(const void* origin, | 529 ScopedThreadActivity(const void* origin, |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 492 return tracker; | 608 return tracker; |
| 493 return CreateTrackerForCurrentThread(); | 609 return CreateTrackerForCurrentThread(); |
| 494 } | 610 } |
| 495 | 611 |
| 496 // Creates an activity-tracker for the current thread. | 612 // Creates an activity-tracker for the current thread. |
| 497 ThreadActivityTracker* CreateTrackerForCurrentThread(); | 613 ThreadActivityTracker* CreateTrackerForCurrentThread(); |
| 498 | 614 |
| 499 // Releases the activity-tracker for the current thread (for testing only). | 615 // Releases the activity-tracker for the current thread (for testing only). |
| 500 void ReleaseTrackerForCurrentThreadForTesting(); | 616 void ReleaseTrackerForCurrentThreadForTesting(); |
| 501 | 617 |
| 618 // Gets a reference to memory for holding user-defined activity data. If | |
| 619 // the reference is valid, it's memory will be returned. If not, then a | |
| 620 // new reference will be created (and stored) and that memory returned. | |
| 621 void* GetUserDataMemory(PersistentMemoryAllocator::Reference* reference); | |
| 622 | |
| 623 // Releases memory for user-defined activity data. | |
| 624 void ReleaseUserDataMemory(PersistentMemoryAllocator::Reference* reference); | |
| 625 | |
| 626 // Accesses the global data record for storing arbitrary key/value pairs. | |
| 627 ActivityUserData& user_data() { return user_data_; } | |
| 628 | |
| 502 private: | 629 private: |
| 503 friend class ActivityTrackerTest; | 630 friend class ActivityTrackerTest; |
| 504 | 631 |
| 505 enum : int { | 632 enum : int { |
| 506 // The maximum number of threads that can be tracked within a process. If | 633 // The maximum number of threads that can be tracked within a process. If |
| 507 // more than this number run concurrently, tracking of new ones may cease. | 634 // more than this number run concurrently, tracking of new ones may cease. |
| 508 kMaxThreadCount = 100, | 635 kMaxThreadCount = 100, |
| 509 kCachedThreadMemories = 10, | 636 kCachedThreadMemories = 10, |
| 637 kCachedUserDataMemories = 10, | |
| 510 }; | 638 }; |
| 511 | 639 |
| 512 // A thin wrapper around the main thread-tracker that keeps additional | 640 // A thin wrapper around the main thread-tracker that keeps additional |
| 513 // information that the global tracker needs to handle joined threads. | 641 // information that the global tracker needs to handle joined threads. |
| 514 class ManagedActivityTracker : public ThreadActivityTracker { | 642 class ManagedActivityTracker : public ThreadActivityTracker { |
| 515 public: | 643 public: |
| 516 ManagedActivityTracker(PersistentMemoryAllocator::Reference mem_reference, | 644 ManagedActivityTracker(PersistentMemoryAllocator::Reference mem_reference, |
| 517 void* base, | 645 void* base, |
| 518 size_t size); | 646 size_t size); |
| 519 ~ManagedActivityTracker() override; | 647 ~ManagedActivityTracker() override; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 555 // The activity tracker for the currently executing thread. | 683 // The activity tracker for the currently executing thread. |
| 556 base::ThreadLocalStorage::Slot this_thread_tracker_; | 684 base::ThreadLocalStorage::Slot this_thread_tracker_; |
| 557 | 685 |
| 558 // The number of thread trackers currently active. | 686 // The number of thread trackers currently active. |
| 559 std::atomic<int> thread_tracker_count_; | 687 std::atomic<int> thread_tracker_count_; |
| 560 | 688 |
| 561 // A caching memory allocator for thread-tracker objects. | 689 // A caching memory allocator for thread-tracker objects. |
| 562 ActivityTrackerMemoryAllocator thread_tracker_allocator_; | 690 ActivityTrackerMemoryAllocator thread_tracker_allocator_; |
| 563 base::Lock thread_tracker_allocator_lock_; | 691 base::Lock thread_tracker_allocator_lock_; |
| 564 | 692 |
| 693 // A caching memory allocator for user data attached to activity data. | |
| 694 ActivityTrackerMemoryAllocator user_data_allocator_; | |
| 695 base::Lock user_data_allocator_lock_; | |
| 696 | |
| 697 // An object for holding global arbitrary key value pairs. | |
| 698 ActivityUserData user_data_; | |
|
manzagop (departed)
2016/11/11 17:01:42
This has a thread checker, so it should only be us
bcwhite
2016/11/14 15:08:43
Done.
| |
| 699 | |
| 565 // The active global activity tracker. | 700 // The active global activity tracker. |
| 566 static GlobalActivityTracker* g_tracker_; | 701 static GlobalActivityTracker* g_tracker_; |
| 567 | 702 |
| 568 DISALLOW_COPY_AND_ASSIGN(GlobalActivityTracker); | 703 DISALLOW_COPY_AND_ASSIGN(GlobalActivityTracker); |
| 569 }; | 704 }; |
| 570 | 705 |
| 571 | 706 |
| 572 // Record entry in to and out of an arbitrary block of code. | 707 // Record entry in to and out of an arbitrary block of code. |
| 573 class BASE_EXPORT ScopedActivity | 708 class BASE_EXPORT ScopedActivity |
| 574 : public GlobalActivityTracker::ScopedThreadActivity { | 709 : public GlobalActivityTracker::ScopedThreadActivity { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 657 explicit ScopedProcessWaitActivity(const base::Process* process); | 792 explicit ScopedProcessWaitActivity(const base::Process* process); |
| 658 private: | 793 private: |
| 659 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); | 794 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); |
| 660 }; | 795 }; |
| 661 #endif | 796 #endif |
| 662 | 797 |
| 663 } // namespace debug | 798 } // namespace debug |
| 664 } // namespace base | 799 } // namespace base |
| 665 | 800 |
| 666 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ | 801 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ |
| OLD | NEW |