| 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 <memory> | 19 #include <memory> |
| 20 #include <string> | 20 #include <string> |
| 21 #include <vector> | 21 #include <vector> |
| 22 | 22 |
| 23 #include "base/base_export.h" | 23 #include "base/base_export.h" |
| 24 #include "base/compiler_specific.h" |
| 24 #include "base/location.h" | 25 #include "base/location.h" |
| 25 #include "base/metrics/persistent_memory_allocator.h" | 26 #include "base/metrics/persistent_memory_allocator.h" |
| 26 #include "base/threading/platform_thread.h" | 27 #include "base/threading/platform_thread.h" |
| 27 #include "base/threading/thread_checker.h" | 28 #include "base/threading/thread_checker.h" |
| 28 #include "base/threading/thread_local_storage.h" | 29 #include "base/threading/thread_local_storage.h" |
| 29 | 30 |
| 30 namespace base { | 31 namespace base { |
| 31 | 32 |
| 32 struct PendingTask; | 33 struct PendingTask; |
| 33 | 34 |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 // These constants can be used to separate the category and action from | 216 // These constants can be used to separate the category and action from |
| 216 // a combined activity type. | 217 // a combined activity type. |
| 217 ACT_CATEGORY_MASK = 0xF << 4, | 218 ACT_CATEGORY_MASK = 0xF << 4, |
| 218 ACT_ACTION_MASK = 0xF | 219 ACT_ACTION_MASK = 0xF |
| 219 }; | 220 }; |
| 220 | 221 |
| 221 // Internal representation of time. During collection, this is in "ticks" | 222 // Internal representation of time. During collection, this is in "ticks" |
| 222 // but when returned in a snapshot, it is "wall time". | 223 // but when returned in a snapshot, it is "wall time". |
| 223 int64_t time_internal; | 224 int64_t time_internal; |
| 224 | 225 |
| 226 // The address that pushed the activity onto the stack as a raw number. |
| 227 uint64_t calling_address; |
| 228 |
| 225 // The address that is the origin of the activity if it not obvious from | 229 // The address that is the origin of the activity if it not obvious from |
| 226 // the call stack. This is useful for things like tasks that are posted | 230 // the call stack. This is useful for things like tasks that are posted |
| 227 // from a completely different thread though most activities will leave | 231 // from a completely different thread though most activities will leave |
| 228 // it null. | 232 // it null. |
| 229 uint64_t origin_address; | 233 uint64_t origin_address; |
| 230 | 234 |
| 231 // Array of program-counters that make up the top of the call stack. | 235 // Array of program-counters that make up the top of the call stack. |
| 232 // Despite the fixed size, this list is always null-terminated. Entries | 236 // Despite the fixed size, this list is always null-terminated. Entries |
| 233 // after the terminator have no meaning and may or may not also be null. | 237 // after the terminator have no meaning and may or may not also be null. |
| 234 // The list will be completely empty if call-stack collection is not | 238 // The list will be completely empty if call-stack collection is not |
| 235 // enabled. | 239 // enabled. |
| 236 uint64_t call_stack[kActivityCallStackSize]; | 240 uint64_t call_stack[kActivityCallStackSize]; |
| 237 | 241 |
| 238 // The (enumerated) type of the activity. This defines what fields of the | 242 // The (enumerated) type of the activity. This defines what fields of the |
| 239 // |data| record are valid. | 243 // |data| record are valid. |
| 240 uint8_t activity_type; | 244 uint8_t activity_type; |
| 241 | 245 |
| 242 // Padding to ensure that the next member begins on a 64-bit boundary | 246 // Padding to ensure that the next member begins on a 64-bit boundary |
| 243 // even on 32-bit builds which ensures inter-operability between CPU | 247 // even on 32-bit builds which ensures inter-operability between CPU |
| 244 // architectures. New fields can be taken from this space. | 248 // architectures. New fields can be taken from this space. |
| 245 uint8_t padding[7]; | 249 uint8_t padding[7]; |
| 246 | 250 |
| 247 // Information specific to the |activity_type|. | 251 // Information specific to the |activity_type|. |
| 248 ActivityData data; | 252 ActivityData data; |
| 249 | 253 |
| 250 static void FillFrom(Activity* activity, | 254 static void FillFrom(Activity* activity, |
| 255 const void* program_counter, |
| 251 const void* origin, | 256 const void* origin, |
| 252 Type type, | 257 Type type, |
| 253 const ActivityData& data); | 258 const ActivityData& data); |
| 254 }; | 259 }; |
| 255 | 260 |
| 256 // This structure holds a copy of all the internal data at the moment the | 261 // This structure holds a copy of all the internal data at the moment the |
| 257 // "snapshot" operation is done. It is disconnected from the live tracker | 262 // "snapshot" operation is done. It is disconnected from the live tracker |
| 258 // so that continued operation of the thread will not cause changes here. | 263 // so that continued operation of the thread will not cause changes here. |
| 259 struct BASE_EXPORT ActivitySnapshot { | 264 struct BASE_EXPORT ActivitySnapshot { |
| 260 // Explicit constructor/destructor are needed because of complex types | 265 // Explicit constructor/destructor are needed because of complex types |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 294 // objects. | 299 // objects. |
| 295 class BASE_EXPORT ThreadActivityTracker { | 300 class BASE_EXPORT ThreadActivityTracker { |
| 296 public: | 301 public: |
| 297 // This is the base class for having the compiler manage an activity on the | 302 // This is the base class for having the compiler manage an activity on the |
| 298 // tracker's stack. It does nothing but call methods on the passed |tracker| | 303 // tracker's stack. It does nothing but call methods on the passed |tracker| |
| 299 // if it is not null, making it safe (and cheap) to create these objects | 304 // if it is not null, making it safe (and cheap) to create these objects |
| 300 // even if activity tracking is not enabled. | 305 // even if activity tracking is not enabled. |
| 301 class BASE_EXPORT ScopedActivity { | 306 class BASE_EXPORT ScopedActivity { |
| 302 public: | 307 public: |
| 303 ScopedActivity(ThreadActivityTracker* tracker, | 308 ScopedActivity(ThreadActivityTracker* tracker, |
| 309 const void* program_counter, |
| 304 const void* origin, | 310 const void* origin, |
| 305 Activity::Type type, | 311 Activity::Type type, |
| 306 const ActivityData& data) | 312 const ActivityData& data) |
| 307 : tracker_(tracker) { | 313 : tracker_(tracker) { |
| 308 if (tracker_) | 314 if (tracker_) |
| 309 tracker_->PushActivity(origin, type, data); | 315 tracker_->PushActivity(program_counter, origin, type, data); |
| 310 } | 316 } |
| 311 | 317 |
| 312 ~ScopedActivity() { | 318 ~ScopedActivity() { |
| 313 if (tracker_) | 319 if (tracker_) |
| 314 tracker_->PopActivity(); | 320 tracker_->PopActivity(); |
| 315 } | 321 } |
| 316 | 322 |
| 317 void ChangeTypeAndData(Activity::Type type, const ActivityData& data) { | 323 void ChangeTypeAndData(Activity::Type type, const ActivityData& data) { |
| 318 if (tracker_) | 324 if (tracker_) |
| 319 tracker_->ChangeActivity(type, data); | 325 tracker_->ChangeActivity(type, data); |
| 320 } | 326 } |
| 321 | 327 |
| 322 private: | 328 private: |
| 323 // The thread tracker to which this object reports. It can be null if | 329 // The thread tracker to which this object reports. It can be null if |
| 324 // activity tracking is not (yet) enabled. | 330 // activity tracking is not (yet) enabled. |
| 325 ThreadActivityTracker* const tracker_; | 331 ThreadActivityTracker* const tracker_; |
| 326 | 332 |
| 327 DISALLOW_COPY_AND_ASSIGN(ScopedActivity); | 333 DISALLOW_COPY_AND_ASSIGN(ScopedActivity); |
| 328 }; | 334 }; |
| 329 | 335 |
| 330 // A ThreadActivityTracker runs on top of memory that is managed externally. | 336 // A ThreadActivityTracker runs on top of memory that is managed externally. |
| 331 // It must be large enough for the internal header and a few Activity | 337 // It must be large enough for the internal header and a few Activity |
| 332 // blocks. See SizeForStackDepth(). | 338 // blocks. See SizeForStackDepth(). |
| 333 ThreadActivityTracker(void* base, size_t size); | 339 ThreadActivityTracker(void* base, size_t size); |
| 334 virtual ~ThreadActivityTracker(); | 340 virtual ~ThreadActivityTracker(); |
| 335 | 341 |
| 336 // Indicates that an activity has started from a given |origin| address in | 342 // Indicates that an activity has started from a given |origin| address in |
| 337 // the code, though it can be null if the creator's address is not known. | 343 // the code, though it can be null if the creator's address is not known. |
| 338 // The |type| and |data| describe the activity. | 344 // The |type| and |data| describe the activity. |program_counter| should be |
| 345 // the result of GetProgramCounter() where push is called. |
| 346 void PushActivity(const void* program_counter, |
| 347 const void* origin, |
| 348 Activity::Type type, |
| 349 const ActivityData& data); |
| 350 |
| 351 // An inlined version of the above that gets the program counter where it |
| 352 // is called. |
| 353 ALWAYS_INLINE |
| 339 void PushActivity(const void* origin, | 354 void PushActivity(const void* origin, |
| 340 Activity::Type type, | 355 Activity::Type type, |
| 341 const ActivityData& data); | 356 const ActivityData& data) { |
| 357 PushActivity(::tracked_objects::GetProgramCounter(), origin, type, data); |
| 358 } |
| 342 | 359 |
| 343 // Changes the activity |type| and |data| of the top-most entry on the stack. | 360 // Changes the activity |type| and |data| of the top-most entry on the stack. |
| 344 // This is useful if the information has changed and it is desireable to | 361 // This is useful if the information has changed and it is desireable to |
| 345 // track that change without creating a new stack entry. If the type is | 362 // track that change without creating a new stack entry. If the type is |
| 346 // ACT_NULL or the data is kNullActivityData then that value will remain | 363 // ACT_NULL or the data is kNullActivityData then that value will remain |
| 347 // unchanged. The type, if changed, must remain in the same category. | 364 // unchanged. The type, if changed, must remain in the same category. |
| 348 // Changing both is not atomic so a snapshot operation could occur between | 365 // Changing both is not atomic so a snapshot operation could occur between |
| 349 // the update of |type| and |data| or between update of |data| fields. | 366 // the update of |type| and |data| or between update of |data| fields. |
| 350 void ChangeActivity(Activity::Type type, const ActivityData& data); | 367 void ChangeActivity(Activity::Type type, const ActivityData& data); |
| 351 | 368 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 // for the data to be analyzed by a parallel process or even post-mortem. | 408 // for the data to be analyzed by a parallel process or even post-mortem. |
| 392 class BASE_EXPORT GlobalActivityTracker { | 409 class BASE_EXPORT GlobalActivityTracker { |
| 393 public: | 410 public: |
| 394 // Type identifiers used when storing in persistent memory so they can be | 411 // Type identifiers used when storing in persistent memory so they can be |
| 395 // identified during extraction; the first 4 bytes of the SHA1 of the name | 412 // identified during extraction; the first 4 bytes of the SHA1 of the name |
| 396 // is used as a unique integer. A "version number" is added to the base | 413 // is used as a unique integer. A "version number" is added to the base |
| 397 // so that, if the structure of that object changes, stored older versions | 414 // so that, if the structure of that object changes, stored older versions |
| 398 // will be safely ignored. These are public so that an external process | 415 // will be safely ignored. These are public so that an external process |
| 399 // can recognize records of this type within an allocator. | 416 // can recognize records of this type within an allocator. |
| 400 enum : uint32_t { | 417 enum : uint32_t { |
| 401 kTypeIdActivityTracker = 0x5D7381AF + 1, // SHA1(ActivityTracker) v1 | 418 kTypeIdActivityTracker = 0x5D7381AF + 2, // SHA1(ActivityTracker) v2 |
| 402 kTypeIdActivityTrackerFree = ~kTypeIdActivityTracker, | 419 kTypeIdActivityTrackerFree = ~kTypeIdActivityTracker, |
| 403 }; | 420 }; |
| 404 | 421 |
| 405 // This is a thin wrapper around the thread-tracker's ScopedActivity that | 422 // This is a thin wrapper around the thread-tracker's ScopedActivity that |
| 406 // accesses the global tracker to provide some of the information, notably | 423 // accesses the global tracker to provide some of the information, notably |
| 407 // which thread-tracker to use. It is safe to create even if activity | 424 // which thread-tracker to use. It is safe to create even if activity |
| 408 // tracking is not enabled. | 425 // tracking is not enabled. |
| 409 class BASE_EXPORT ScopedThreadActivity | 426 class BASE_EXPORT ScopedThreadActivity |
| 410 : public ThreadActivityTracker::ScopedActivity { | 427 : public ThreadActivityTracker::ScopedActivity { |
| 411 public: | 428 public: |
| 412 ScopedThreadActivity(const void* origin, | 429 ScopedThreadActivity(const void* program_counter, |
| 430 const void* origin, |
| 413 Activity::Type type, | 431 Activity::Type type, |
| 414 const ActivityData& data, | 432 const ActivityData& data, |
| 415 bool lock_allowed) | 433 bool lock_allowed) |
| 416 : ThreadActivityTracker::ScopedActivity( | 434 : ThreadActivityTracker::ScopedActivity( |
| 417 GetOrCreateTracker(lock_allowed), | 435 GetOrCreateTracker(lock_allowed), |
| 436 program_counter, |
| 418 origin, | 437 origin, |
| 419 type, | 438 type, |
| 420 data) {} | 439 data) {} |
| 421 | 440 |
| 422 private: | 441 private: |
| 423 // Gets (or creates) a tracker for the current thread. If locking is not | 442 // Gets (or creates) a tracker for the current thread. If locking is not |
| 424 // allowed (because a lock is being tracked which would cause recursion) | 443 // allowed (because a lock is being tracked which would cause recursion) |
| 425 // then the attempt to create one if none found will be skipped. Once | 444 // then the attempt to create one if none found will be skipped. Once |
| 426 // the tracker for this thread has been created for other reasons, locks | 445 // the tracker for this thread has been created for other reasons, locks |
| 427 // will be tracked. The thread-tracker uses locks. | 446 // will be tracked. The thread-tracker uses locks. |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 // |info|. None of these values affect operation; they're all purely | 596 // |info|. None of these values affect operation; they're all purely |
| 578 // for association and analysis. To have unique identifiers across a | 597 // for association and analysis. To have unique identifiers across a |
| 579 // diverse code-base, create the number by taking the first 8 characters | 598 // diverse code-base, create the number by taking the first 8 characters |
| 580 // of the hash of the activity being tracked. | 599 // of the hash of the activity being tracked. |
| 581 // | 600 // |
| 582 // For example: | 601 // For example: |
| 583 // Tracking method: void MayNeverExit(uint32_t foo) {...} | 602 // Tracking method: void MayNeverExit(uint32_t foo) {...} |
| 584 // echo -n "MayNeverExit" | sha1sum => e44873ccab21e2b71270da24aa1... | 603 // echo -n "MayNeverExit" | sha1sum => e44873ccab21e2b71270da24aa1... |
| 585 // | 604 // |
| 586 // void MayNeverExit(int32_t foo) { | 605 // void MayNeverExit(int32_t foo) { |
| 587 // base::debug::ScopedActivity track_me(FROM_HERE, 0, 0xE44873CC, foo); | 606 // base::debug::ScopedActivity track_me(0, 0xE44873CC, foo); |
| 588 // ... | 607 // ... |
| 589 // } | 608 // } |
| 590 ScopedActivity(const tracked_objects::Location& location, | 609 ALWAYS_INLINE |
| 591 uint8_t action, | 610 ScopedActivity(uint8_t action, uint32_t id, int32_t info) |
| 592 uint32_t id, | 611 : ScopedActivity(::tracked_objects::GetProgramCounter(), |
| 593 int32_t info); | 612 action, |
| 594 | 613 id, |
| 595 // Because this is inline, the FROM_HERE macro will resolve the current | 614 info) {} |
| 596 // program-counter as the location in the calling code. | 615 ScopedActivity() : ScopedActivity(0, 0, 0) {} |
| 597 ScopedActivity() : ScopedActivity(FROM_HERE, 0, 0, 0) {} | |
| 598 | 616 |
| 599 // Changes the |action| and/or |info| of this activity on the stack. This | 617 // Changes the |action| and/or |info| of this activity on the stack. This |
| 600 // is useful for tracking progress through a function, updating the action | 618 // is useful for tracking progress through a function, updating the action |
| 601 // to indicate "milestones" in the block (max 16 milestones: 0-15) or the | 619 // to indicate "milestones" in the block (max 16 milestones: 0-15) or the |
| 602 // info to reflect other changes. Changing both is not atomic so a snapshot | 620 // info to reflect other changes. Changing both is not atomic so a snapshot |
| 603 // operation could occur between the update of |action| and |info|. | 621 // operation could occur between the update of |action| and |info|. |
| 604 void ChangeAction(uint8_t action); | 622 void ChangeAction(uint8_t action); |
| 605 void ChangeInfo(int32_t info); | 623 void ChangeInfo(int32_t info); |
| 606 void ChangeActionAndInfo(uint8_t action, int32_t info); | 624 void ChangeActionAndInfo(uint8_t action, int32_t info); |
| 607 | 625 |
| 608 private: | 626 private: |
| 627 // Constructs the object using a passed-in program-counter. |
| 628 ScopedActivity(const void* program_counter, |
| 629 uint8_t action, |
| 630 uint32_t id, |
| 631 int32_t info); |
| 632 |
| 609 // A copy of the ID code so it doesn't have to be passed by the caller when | 633 // A copy of the ID code so it doesn't have to be passed by the caller when |
| 610 // changing the |info| field. | 634 // changing the |info| field. |
| 611 uint32_t id_; | 635 uint32_t id_; |
| 612 | 636 |
| 613 DISALLOW_COPY_AND_ASSIGN(ScopedActivity); | 637 DISALLOW_COPY_AND_ASSIGN(ScopedActivity); |
| 614 }; | 638 }; |
| 615 | 639 |
| 616 | 640 |
| 617 // These "scoped" classes provide easy tracking of various blocking actions. | 641 // These "scoped" classes provide easy tracking of various blocking actions. |
| 618 | 642 |
| 619 class BASE_EXPORT ScopedTaskRunActivity | 643 class BASE_EXPORT ScopedTaskRunActivity |
| 620 : public GlobalActivityTracker::ScopedThreadActivity { | 644 : public GlobalActivityTracker::ScopedThreadActivity { |
| 621 public: | 645 public: |
| 622 explicit ScopedTaskRunActivity(const base::PendingTask& task); | 646 ALWAYS_INLINE |
| 647 explicit ScopedTaskRunActivity(const base::PendingTask& task) |
| 648 : ScopedTaskRunActivity(::tracked_objects::GetProgramCounter(), |
| 649 task) {} |
| 650 |
| 623 private: | 651 private: |
| 652 ScopedTaskRunActivity(const void* program_counter, |
| 653 const base::PendingTask& task); |
| 624 DISALLOW_COPY_AND_ASSIGN(ScopedTaskRunActivity); | 654 DISALLOW_COPY_AND_ASSIGN(ScopedTaskRunActivity); |
| 625 }; | 655 }; |
| 626 | 656 |
| 627 class BASE_EXPORT ScopedLockAcquireActivity | 657 class BASE_EXPORT ScopedLockAcquireActivity |
| 628 : public GlobalActivityTracker::ScopedThreadActivity { | 658 : public GlobalActivityTracker::ScopedThreadActivity { |
| 629 public: | 659 public: |
| 630 explicit ScopedLockAcquireActivity(const base::internal::LockImpl* lock); | 660 ALWAYS_INLINE |
| 661 explicit ScopedLockAcquireActivity(const base::internal::LockImpl* lock) |
| 662 : ScopedLockAcquireActivity(::tracked_objects::GetProgramCounter(), |
| 663 lock) {} |
| 664 |
| 631 private: | 665 private: |
| 666 ScopedLockAcquireActivity(const void* program_counter, |
| 667 const base::internal::LockImpl* lock); |
| 632 DISALLOW_COPY_AND_ASSIGN(ScopedLockAcquireActivity); | 668 DISALLOW_COPY_AND_ASSIGN(ScopedLockAcquireActivity); |
| 633 }; | 669 }; |
| 634 | 670 |
| 635 class BASE_EXPORT ScopedEventWaitActivity | 671 class BASE_EXPORT ScopedEventWaitActivity |
| 636 : public GlobalActivityTracker::ScopedThreadActivity { | 672 : public GlobalActivityTracker::ScopedThreadActivity { |
| 637 public: | 673 public: |
| 638 explicit ScopedEventWaitActivity(const base::WaitableEvent* event); | 674 ALWAYS_INLINE |
| 675 explicit ScopedEventWaitActivity(const base::WaitableEvent* event) |
| 676 : ScopedEventWaitActivity(::tracked_objects::GetProgramCounter(), |
| 677 event) {} |
| 678 |
| 639 private: | 679 private: |
| 680 ScopedEventWaitActivity(const void* program_counter, |
| 681 const base::WaitableEvent* event); |
| 640 DISALLOW_COPY_AND_ASSIGN(ScopedEventWaitActivity); | 682 DISALLOW_COPY_AND_ASSIGN(ScopedEventWaitActivity); |
| 641 }; | 683 }; |
| 642 | 684 |
| 643 class BASE_EXPORT ScopedThreadJoinActivity | 685 class BASE_EXPORT ScopedThreadJoinActivity |
| 644 : public GlobalActivityTracker::ScopedThreadActivity { | 686 : public GlobalActivityTracker::ScopedThreadActivity { |
| 645 public: | 687 public: |
| 646 explicit ScopedThreadJoinActivity(const base::PlatformThreadHandle* thread); | 688 ALWAYS_INLINE |
| 689 explicit ScopedThreadJoinActivity(const base::PlatformThreadHandle* thread) |
| 690 : ScopedThreadJoinActivity(::tracked_objects::GetProgramCounter(), |
| 691 thread) {} |
| 692 |
| 647 private: | 693 private: |
| 694 ScopedThreadJoinActivity(const void* program_counter, |
| 695 const base::PlatformThreadHandle* thread); |
| 648 DISALLOW_COPY_AND_ASSIGN(ScopedThreadJoinActivity); | 696 DISALLOW_COPY_AND_ASSIGN(ScopedThreadJoinActivity); |
| 649 }; | 697 }; |
| 650 | 698 |
| 651 // Some systems don't have base::Process | 699 // Some systems don't have base::Process |
| 652 #if !defined(OS_NACL) && !defined(OS_IOS) | 700 #if !defined(OS_NACL) && !defined(OS_IOS) |
| 653 class BASE_EXPORT ScopedProcessWaitActivity | 701 class BASE_EXPORT ScopedProcessWaitActivity |
| 654 : public GlobalActivityTracker::ScopedThreadActivity { | 702 : public GlobalActivityTracker::ScopedThreadActivity { |
| 655 public: | 703 public: |
| 656 explicit ScopedProcessWaitActivity(const base::Process* process); | 704 ALWAYS_INLINE |
| 705 explicit ScopedProcessWaitActivity(const base::Process* process) |
| 706 : ScopedProcessWaitActivity(::tracked_objects::GetProgramCounter(), |
| 707 process) {} |
| 708 |
| 657 private: | 709 private: |
| 710 ScopedProcessWaitActivity(const void* program_counter, |
| 711 const base::Process* process); |
| 658 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); | 712 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); |
| 659 }; | 713 }; |
| 660 #endif | 714 #endif |
| 661 | 715 |
| 662 } // namespace debug | 716 } // namespace debug |
| 663 } // namespace base | 717 } // namespace base |
| 664 | 718 |
| 665 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ | 719 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ |
| OLD | NEW |