Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Side by Side Diff: base/trace_event/heap_profiler_allocation_context_tracker.cc

Issue 1675183006: tracing: add dump provider for malloc heap profiler (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@shim_layer_linux
Patch Set: add comment Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/trace_event/heap_profiler_allocation_context_tracker.h" 5 #include "base/trace_event/heap_profiler_allocation_context_tracker.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <iterator> 8 #include <iterator>
9 9
10 #include "base/atomicops.h" 10 #include "base/atomicops.h"
11 #include "base/threading/thread_local_storage.h" 11 #include "base/threading/thread_local_storage.h"
12 #include "base/trace_event/heap_profiler_allocation_context.h" 12 #include "base/trace_event/heap_profiler_allocation_context.h"
13 13
14 namespace base { 14 namespace base {
15 namespace trace_event { 15 namespace trace_event {
16 16
17 subtle::Atomic32 AllocationContextTracker::capture_enabled_ = 0; 17 subtle::Atomic32 AllocationContextTracker::capture_enabled_ = 0;
18 18
19 namespace { 19 namespace {
20 20
21 const size_t kMaxStackDepth = 128u;
22 AllocationContextTracker* const kInitializingSentinel =
23 reinterpret_cast<AllocationContextTracker*>(-1);
24
21 ThreadLocalStorage::StaticSlot g_tls_alloc_ctx_tracker = TLS_INITIALIZER; 25 ThreadLocalStorage::StaticSlot g_tls_alloc_ctx_tracker = TLS_INITIALIZER;
22 26
23 // This function is added to the TLS slot to clean up the instance when the 27 // This function is added to the TLS slot to clean up the instance when the
24 // thread exits. 28 // thread exits.
25 void DestructAllocationContextTracker(void* alloc_ctx_tracker) { 29 void DestructAllocationContextTracker(void* alloc_ctx_tracker) {
26 delete static_cast<AllocationContextTracker*>(alloc_ctx_tracker); 30 delete static_cast<AllocationContextTracker*>(alloc_ctx_tracker);
27 } 31 }
28 32
29 } // namespace 33 } // namespace
30 34
31 AllocationContextTracker::AllocationContextTracker() {} 35 AllocationContextTracker::AllocationContextTracker() {
36 pseudo_stack_.reserve(kMaxStackDepth);
37 }
32 AllocationContextTracker::~AllocationContextTracker() {} 38 AllocationContextTracker::~AllocationContextTracker() {}
33 39
34 // static 40 // static
41 AllocationContextTracker::InitializationState
42 AllocationContextTracker::GetStateForCurrentThread() {
43 auto tracker =
44 static_cast<AllocationContextTracker*>(g_tls_alloc_ctx_tracker.Get());
45 if (!tracker)
46 return kNotInitialized;
47 if (tracker == kInitializingSentinel)
48 return kInitializing;
49 return kInitialized;
50 }
51
52 // static
53 AllocationContextTracker*
54 AllocationContextTracker::InitializeForCurrentThread() {
55 DCHECK_EQ(kNotInitialized, GetStateForCurrentThread());
56 g_tls_alloc_ctx_tracker.Set(kInitializingSentinel);
57 AllocationContextTracker* tracker = new AllocationContextTracker();
58 g_tls_alloc_ctx_tracker.Set(tracker);
59 return tracker;
60 }
61
62 // static
35 AllocationContextTracker* AllocationContextTracker::GetThreadLocalTracker() { 63 AllocationContextTracker* AllocationContextTracker::GetThreadLocalTracker() {
36 auto tracker = 64 auto tracker =
37 static_cast<AllocationContextTracker*>(g_tls_alloc_ctx_tracker.Get()); 65 static_cast<AllocationContextTracker*>(g_tls_alloc_ctx_tracker.Get());
38 66 DCHECK_NE(kInitializingSentinel, tracker);
39 if (!tracker) { 67 if (!tracker)
40 tracker = new AllocationContextTracker(); 68 tracker = InitializeForCurrentThread();
41 g_tls_alloc_ctx_tracker.Set(tracker);
42 }
43
44 return tracker; 69 return tracker;
45 } 70 }
46 71
47 // static 72 // static
48 void AllocationContextTracker::SetCaptureEnabled(bool enabled) { 73 void AllocationContextTracker::SetCaptureEnabled(bool enabled) {
49 // When enabling capturing, also initialize the TLS slot. This does not create 74 // When enabling capturing, also initialize the TLS slot. This does not create
50 // a TLS instance yet. 75 // a TLS instance yet.
51 if (enabled && !g_tls_alloc_ctx_tracker.initialized()) 76 if (enabled && !g_tls_alloc_ctx_tracker.initialized())
52 g_tls_alloc_ctx_tracker.Initialize(DestructAllocationContextTracker); 77 g_tls_alloc_ctx_tracker.Initialize(DestructAllocationContextTracker);
53 78
54 // Release ordering ensures that when a thread observes |capture_enabled_| to 79 // Release ordering ensures that when a thread observes |capture_enabled_| to
55 // be true through an acquire load, the TLS slot has been initialized. 80 // be true through an acquire load, the TLS slot has been initialized.
56 subtle::Release_Store(&capture_enabled_, enabled); 81 subtle::Release_Store(&capture_enabled_, enabled);
57 } 82 }
58 83
59 // static 84 // static
60 void AllocationContextTracker::PushPseudoStackFrame(StackFrame frame) { 85 void AllocationContextTracker::PushPseudoStackFrame(StackFrame frame) {
61 auto tracker = AllocationContextTracker::GetThreadLocalTracker(); 86 auto tracker = AllocationContextTracker::GetThreadLocalTracker();
62 87
63 // Impose a limit on the height to verify that every push is popped, because 88 // Impose a limit on the height to verify that every push is popped, because
64 // in practice the pseudo stack never grows higher than ~20 frames. 89 // in practice the pseudo stack never grows higher than ~20 frames.
ssid 2016/03/11 19:51:10 It could happen when someone tries to trace recurs
Primiano Tucci (use gerrit) 2016/03/21 19:29:24 Never seen this happening in practice. If we do I
65 DCHECK_LT(tracker->pseudo_stack_.size(), 128u); 90 if (tracker->pseudo_stack_.size() < kMaxStackDepth)
66 tracker->pseudo_stack_.push_back(frame); 91 tracker->pseudo_stack_.push_back(frame);
92 else
93 NOTREACHED();
67 } 94 }
68 95
69 // static 96 // static
70 void AllocationContextTracker::PopPseudoStackFrame(StackFrame frame) { 97 void AllocationContextTracker::PopPseudoStackFrame(StackFrame frame) {
71 auto tracker = AllocationContextTracker::GetThreadLocalTracker(); 98 auto tracker = AllocationContextTracker::GetThreadLocalTracker();
72 99
73 // Guard for stack underflow. If tracing was started with a TRACE_EVENT in 100 // Guard for stack underflow. If tracing was started with a TRACE_EVENT in
74 // scope, the frame was never pushed, so it is possible that pop is called 101 // scope, the frame was never pushed, so it is possible that pop is called
75 // on an empty stack. 102 // on an empty stack.
76 if (tracker->pseudo_stack_.empty()) 103 if (tracker->pseudo_stack_.empty())
(...skipping 29 matching lines...) Expand all
106 std::fill(dst, dst_end, nullptr); 133 std::fill(dst, dst_end, nullptr);
107 } 134 }
108 135
109 ctx.type_name = nullptr; 136 ctx.type_name = nullptr;
110 137
111 return ctx; 138 return ctx;
112 } 139 }
113 140
114 } // namespace trace_event 141 } // namespace trace_event
115 } // namespace base 142 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698