Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #include "base/tracked_objects.h" | 5 #include "base/tracked_objects.h" |
| 6 | 6 |
| 7 #include <limits.h> | 7 #include <limits.h> |
| 8 #include <stdlib.h> | 8 #include <stdlib.h> |
| 9 | 9 |
| 10 #include "base/atomicops.h" | 10 #include "base/atomicops.h" |
| 11 #include "base/base_switches.h" | 11 #include "base/base_switches.h" |
| 12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
| 13 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
| 14 #include "base/debug/leak_annotations.h" | 14 #include "base/debug/leak_annotations.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/process/process_handle.h" | 16 #include "base/process/process_handle.h" |
| 17 #include "base/profiler/alternate_timer.h" | |
| 18 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
| 19 #include "base/third_party/valgrind/memcheck.h" | 18 #include "base/third_party/valgrind/memcheck.h" |
| 20 #include "base/tracking_info.h" | 19 #include "base/tracking_info.h" |
| 21 #include "build/build_config.h" | 20 #include "build/build_config.h" |
| 22 | 21 |
| 23 using base::TimeDelta; | 22 using base::TimeDelta; |
| 24 | 23 |
| 25 namespace base { | 24 namespace base { |
| 26 class TimeDelta; | 25 class TimeDelta; |
| 27 } | 26 } |
| 28 | 27 |
| 29 namespace tracked_objects { | 28 namespace tracked_objects { |
| 30 | 29 |
| 31 namespace { | 30 namespace { |
| 32 // When ThreadData is first initialized, should we start in an ACTIVE state to | 31 // When ThreadData is first initialized, should we start in an ACTIVE state to |
| 33 // record all of the startup-time tasks, or should we start up DEACTIVATED, so | 32 // record all of the startup-time tasks, or should we start up DEACTIVATED, so |
| 34 // that we only record after parsing the command line flag --enable-tracking. | 33 // that we only record after parsing the command line flag --enable-tracking. |
| 35 // Note that the flag may force either state, so this really controls only the | 34 // Note that the flag may force either state, so this really controls only the |
| 36 // period of time up until that flag is parsed. If there is no flag seen, then | 35 // period of time up until that flag is parsed. If there is no flag seen, then |
| 37 // this state may prevail for much or all of the process lifetime. | 36 // this state may prevail for much or all of the process lifetime. |
| 38 const ThreadData::Status kInitialStartupState = ThreadData::PROFILING_ACTIVE; | 37 const ThreadData::Status kInitialStartupState = ThreadData::PROFILING_ACTIVE; |
| 39 | 38 |
| 40 // Control whether an alternate time source (Now() function) is supported by | 39 // Control whether an alternate time source (Now() function) is supported by |
| 41 // the ThreadData class. This compile time flag should be set to true if we | 40 // the ThreadData class. This compile time flag should be set to true if we |
| 42 // want other modules (such as a memory allocator, or a thread-specific CPU time | 41 // want other modules (such as a memory allocator, or a thread-specific CPU time |
| 43 // clock) to be able to provide a thread-specific Now() function. Without this | 42 // clock) to be able to provide a thread-specific Now() function. Without this |
| 44 // compile-time flag, the code will only support the wall-clock time. This flag | 43 // compile-time flag, the code will only support the wall-clock time. This flag |
| 45 // can be flipped to efficiently disable this path (if there is a performance | 44 // can be flipped to efficiently disable this path (if there is a performance |
| 46 // problem with its presence). | 45 // problem with its presence). |
| 47 static const bool kAllowAlternateTimeSourceHandling = true; | 46 static const bool kAllowAlternateTimeSourceHandling = true; |
|
Ilya Sherman
2016/01/28 01:36:47
Can this be removed?
Primiano Tucci (use gerrit)
2016/01/28 10:46:36
Yeah this sounds a "just in case" switch to make t
| |
| 48 | 47 |
| 49 // Possible states of the profiler timing enabledness. | 48 // Possible states of the profiler timing enabledness. |
| 50 enum { | 49 enum { |
| 51 UNDEFINED_TIMING, | 50 UNDEFINED_TIMING, |
| 52 ENABLED_TIMING, | 51 ENABLED_TIMING, |
| 53 DISABLED_TIMING, | 52 DISABLED_TIMING, |
| 54 }; | 53 }; |
| 55 | 54 |
| 56 // State of the profiler timing enabledness. | 55 // State of the profiler timing enabledness. |
| 57 base::subtle::Atomic32 g_profiler_timing_enabled = UNDEFINED_TIMING; | 56 base::subtle::Atomic32 g_profiler_timing_enabled = UNDEFINED_TIMING; |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 278 | 277 |
| 279 //------------------------------------------------------------------------------ | 278 //------------------------------------------------------------------------------ |
| 280 // ThreadData maintains the central data for all births and deaths on a single | 279 // ThreadData maintains the central data for all births and deaths on a single |
| 281 // thread. | 280 // thread. |
| 282 | 281 |
| 283 // TODO(jar): We should pull all these static vars together, into a struct, and | 282 // TODO(jar): We should pull all these static vars together, into a struct, and |
| 284 // optimize layout so that we benefit from locality of reference during accesses | 283 // optimize layout so that we benefit from locality of reference during accesses |
| 285 // to them. | 284 // to them. |
| 286 | 285 |
| 287 // static | 286 // static |
| 288 NowFunction* ThreadData::now_function_ = NULL; | 287 ThreadData::NowFunction* ThreadData::now_function_ = NULL; |
| 289 | 288 |
| 290 // static | 289 // static |
| 291 bool ThreadData::now_function_is_time_ = false; | 290 bool ThreadData::now_function_is_time_ = false; |
| 292 | 291 |
| 293 // A TLS slot which points to the ThreadData instance for the current thread. | 292 // A TLS slot which points to the ThreadData instance for the current thread. |
| 294 // We do a fake initialization here (zeroing out data), and then the real | 293 // We do a fake initialization here (zeroing out data), and then the real |
| 295 // in-place construction happens when we call tls_index_.Initialize(). | 294 // in-place construction happens when we call tls_index_.Initialize(). |
| 296 // static | 295 // static |
| 297 base::ThreadLocalStorage::StaticSlot ThreadData::tls_index_ = TLS_INITIALIZER; | 296 base::ThreadLocalStorage::StaticSlot ThreadData::tls_index_ = TLS_INITIALIZER; |
| 298 | 297 |
| (...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 685 } | 684 } |
| 686 | 685 |
| 687 void ThreadData::OnProfilingPhaseCompletedOnThread(int profiling_phase) { | 686 void ThreadData::OnProfilingPhaseCompletedOnThread(int profiling_phase) { |
| 688 base::AutoLock lock(map_lock_); | 687 base::AutoLock lock(map_lock_); |
| 689 | 688 |
| 690 for (auto& death : death_map_) { | 689 for (auto& death : death_map_) { |
| 691 death.second.OnProfilingPhaseCompleted(profiling_phase); | 690 death.second.OnProfilingPhaseCompleted(profiling_phase); |
| 692 } | 691 } |
| 693 } | 692 } |
| 694 | 693 |
| 695 static void OptionallyInitializeAlternateTimer() { | |
| 696 NowFunction* alternate_time_source = GetAlternateTimeSource(); | |
| 697 if (alternate_time_source) | |
| 698 ThreadData::SetAlternateTimeSource(alternate_time_source); | |
| 699 } | |
| 700 | |
| 701 void ThreadData::Initialize() { | 694 void ThreadData::Initialize() { |
| 702 if (base::subtle::Acquire_Load(&status_) >= DEACTIVATED) | 695 if (base::subtle::Acquire_Load(&status_) >= DEACTIVATED) |
| 703 return; // Someone else did the initialization. | 696 return; // Someone else did the initialization. |
| 704 // Due to racy lazy initialization in tests, we'll need to recheck status_ | 697 // Due to racy lazy initialization in tests, we'll need to recheck status_ |
| 705 // after we acquire the lock. | 698 // after we acquire the lock. |
| 706 | 699 |
| 707 // Ensure that we don't double initialize tls. We are called when single | 700 // Ensure that we don't double initialize tls. We are called when single |
| 708 // threaded in the product, but some tests may be racy and lazy about our | 701 // threaded in the product, but some tests may be racy and lazy about our |
| 709 // initialization. | 702 // initialization. |
| 710 base::AutoLock lock(*list_lock_.Pointer()); | 703 base::AutoLock lock(*list_lock_.Pointer()); |
| 711 if (base::subtle::Acquire_Load(&status_) >= DEACTIVATED) | 704 if (base::subtle::Acquire_Load(&status_) >= DEACTIVATED) |
| 712 return; // Someone raced in here and beat us. | 705 return; // Someone raced in here and beat us. |
| 713 | 706 |
| 714 // Put an alternate timer in place if the environment calls for it, such as | |
| 715 // for tracking TCMalloc allocations. This insertion is idempotent, so we | |
| 716 // don't mind if there is a race, and we'd prefer not to be in a lock while | |
| 717 // doing this work. | |
| 718 if (kAllowAlternateTimeSourceHandling) | |
| 719 OptionallyInitializeAlternateTimer(); | |
| 720 | |
| 721 // Perform the "real" TLS initialization now, and leave it intact through | 707 // Perform the "real" TLS initialization now, and leave it intact through |
| 722 // process termination. | 708 // process termination. |
| 723 if (!tls_index_.initialized()) { // Testing may have initialized this. | 709 if (!tls_index_.initialized()) { // Testing may have initialized this. |
| 724 DCHECK_EQ(base::subtle::NoBarrier_Load(&status_), UNINITIALIZED); | 710 DCHECK_EQ(base::subtle::NoBarrier_Load(&status_), UNINITIALIZED); |
| 725 tls_index_.Initialize(&ThreadData::OnThreadTermination); | 711 tls_index_.Initialize(&ThreadData::OnThreadTermination); |
| 726 DCHECK(tls_index_.initialized()); | 712 DCHECK(tls_index_.initialized()); |
| 727 } else { | 713 } else { |
| 728 // TLS was initialzed for us earlier. | 714 // TLS was initialzed for us earlier. |
| 729 DCHECK_EQ(base::subtle::NoBarrier_Load(&status_), DORMANT_DURING_TESTS); | 715 DCHECK_EQ(base::subtle::NoBarrier_Load(&status_), DORMANT_DURING_TESTS); |
| 730 } | 716 } |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 760 // static | 746 // static |
| 761 bool ThreadData::TrackingStatus() { | 747 bool ThreadData::TrackingStatus() { |
| 762 return base::subtle::Acquire_Load(&status_) > DEACTIVATED; | 748 return base::subtle::Acquire_Load(&status_) > DEACTIVATED; |
| 763 } | 749 } |
| 764 | 750 |
| 765 // static | 751 // static |
| 766 void ThreadData::SetAlternateTimeSource(NowFunction* now_function) { | 752 void ThreadData::SetAlternateTimeSource(NowFunction* now_function) { |
| 767 DCHECK(now_function); | 753 DCHECK(now_function); |
| 768 if (kAllowAlternateTimeSourceHandling) | 754 if (kAllowAlternateTimeSourceHandling) |
| 769 now_function_ = now_function; | 755 now_function_ = now_function; |
| 770 } | 756 } |
|
Ilya Sherman
2016/01/28 01:36:47
Can this be removed?
Primiano Tucci (use gerrit)
2016/01/28 10:46:36
Yes, I need to just keep now_function_ for the tes
| |
| 771 | 757 |
| 772 // static | 758 // static |
| 773 void ThreadData::EnableProfilerTiming() { | 759 void ThreadData::EnableProfilerTiming() { |
| 774 base::subtle::NoBarrier_Store(&g_profiler_timing_enabled, ENABLED_TIMING); | 760 base::subtle::NoBarrier_Store(&g_profiler_timing_enabled, ENABLED_TIMING); |
| 775 } | 761 } |
| 776 | 762 |
| 777 // static | 763 // static |
| 778 TrackedTime ThreadData::Now() { | 764 TrackedTime ThreadData::Now() { |
| 779 if (kAllowAlternateTimeSourceHandling && now_function_) | 765 if (kAllowAlternateTimeSourceHandling && now_function_) |
| 780 return TrackedTime::FromMilliseconds((*now_function_)()); | 766 return TrackedTime::FromMilliseconds((*now_function_)()); |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1005 : process_id(base::GetCurrentProcId()) { | 991 : process_id(base::GetCurrentProcId()) { |
| 1006 #else | 992 #else |
| 1007 : process_id(base::kNullProcessId) { | 993 : process_id(base::kNullProcessId) { |
| 1008 #endif | 994 #endif |
| 1009 } | 995 } |
| 1010 | 996 |
| 1011 ProcessDataSnapshot::~ProcessDataSnapshot() { | 997 ProcessDataSnapshot::~ProcessDataSnapshot() { |
| 1012 } | 998 } |
| 1013 | 999 |
| 1014 } // namespace tracked_objects | 1000 } // namespace tracked_objects |
| OLD | NEW |