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 |