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 #include "base/debug/thread_heap_usage_tracker.h" | 5 #include "base/debug/thread_heap_usage_tracker.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 #include <algorithm> | 8 #include <algorithm> |
9 #include <type_traits> | 9 #include <type_traits> |
10 | 10 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
137 ThreadHeapUsage* GetOrCreateThreadUsage() { | 137 ThreadHeapUsage* GetOrCreateThreadUsage() { |
138 ThreadHeapUsage* allocator_usage = | 138 ThreadHeapUsage* allocator_usage = |
139 static_cast<ThreadHeapUsage*>(g_thread_allocator_usage.Get()); | 139 static_cast<ThreadHeapUsage*>(g_thread_allocator_usage.Get()); |
140 if (allocator_usage == kInitializingSentinel) | 140 if (allocator_usage == kInitializingSentinel) |
141 return nullptr; // Re-entrancy case. | 141 return nullptr; // Re-entrancy case. |
142 | 142 |
143 if (allocator_usage == nullptr) { | 143 if (allocator_usage == nullptr) { |
144 // Prevent reentrancy due to the allocation below. | 144 // Prevent reentrancy due to the allocation below. |
145 g_thread_allocator_usage.Set(kInitializingSentinel); | 145 g_thread_allocator_usage.Set(kInitializingSentinel); |
146 | 146 |
147 allocator_usage = new ThreadHeapUsage; | 147 // Delegate the allocation of the per-thread structure to the underlying |
148 // heap shim, for symmetry with the deallocation. Otherwise interposing | |
149 // shims may mis-attribute or mis-direct this allocation. | |
150 const AllocatorDispatch* next = allocator_dispatch.next; | |
Primiano Tucci (use gerrit)
2016/11/28 18:38:31
add a compile_assert(std::is_pod(ThreadHeapUsage))
Sigurður Ásgeirsson
2016/11/30 14:41:14
Got one of those down a couple of lines, added ano
| |
151 allocator_usage = static_cast<ThreadHeapUsage*>( | |
152 next->alloc_function(next, sizeof(ThreadHeapUsage))); | |
Primiano Tucci (use gerrit)
2016/11/28 18:38:31
maybe a placement new is slighlty cleaner here.
I
Sigurður Ásgeirsson
2016/11/30 14:41:14
Ah, placement new - cool - haven't used it for thi
| |
148 memset(allocator_usage, 0, sizeof(*allocator_usage)); | 153 memset(allocator_usage, 0, sizeof(*allocator_usage)); |
149 g_thread_allocator_usage.Set(allocator_usage); | 154 g_thread_allocator_usage.Set(allocator_usage); |
150 } | 155 } |
151 | 156 |
152 return allocator_usage; | 157 return allocator_usage; |
153 } | 158 } |
154 | 159 |
155 } // namespace | 160 } // namespace |
156 | 161 |
157 ThreadHeapUsageTracker::ThreadHeapUsageTracker() : thread_usage_(nullptr) { | 162 ThreadHeapUsageTracker::ThreadHeapUsageTracker() : thread_usage_(nullptr) { |
158 static_assert(std::is_pod<ThreadHeapUsage>::value, "Must be POD."); | 163 static_assert(std::is_pod<ThreadHeapUsage>::value, "Must be POD."); |
159 } | 164 } |
160 | 165 |
161 ThreadHeapUsageTracker::~ThreadHeapUsageTracker() { | 166 ThreadHeapUsageTracker::~ThreadHeapUsageTracker() { |
162 DCHECK(thread_checker_.CalledOnValidThread()); | 167 // TODO(fdoray): This DCHECK causes inexplicable fallout in Chrome. This |
168 // was isolated to a line in CalledOnValidThread reading. | |
169 // if (task_token_ == TaskToken::GetForCurrentThread()) | |
170 // DCHECK(thread_checker_.CalledOnValidThread()); | |
163 | 171 |
164 if (thread_usage_ != nullptr) { | 172 if (thread_usage_ != nullptr) { |
165 // If this tracker wasn't stopped, make it inclusive so that the | 173 // If this tracker wasn't stopped, make it inclusive so that the |
166 // usage isn't lost. | 174 // usage isn't lost. |
167 Stop(false); | 175 Stop(false); |
168 } | 176 } |
169 } | 177 } |
170 | 178 |
171 void ThreadHeapUsageTracker::Start() { | 179 void ThreadHeapUsageTracker::Start() { |
172 DCHECK(thread_checker_.CalledOnValidThread()); | 180 DCHECK(thread_checker_.CalledOnValidThread()); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
247 } | 255 } |
248 | 256 |
249 base::allocator::AllocatorDispatch* | 257 base::allocator::AllocatorDispatch* |
250 ThreadHeapUsageTracker::GetDispatchForTesting() { | 258 ThreadHeapUsageTracker::GetDispatchForTesting() { |
251 return &allocator_dispatch; | 259 return &allocator_dispatch; |
252 } | 260 } |
253 | 261 |
254 void ThreadHeapUsageTracker::EnsureTLSInitialized() { | 262 void ThreadHeapUsageTracker::EnsureTLSInitialized() { |
255 if (!g_thread_allocator_usage.initialized()) { | 263 if (!g_thread_allocator_usage.initialized()) { |
256 g_thread_allocator_usage.Initialize([](void* allocator_usage) { | 264 g_thread_allocator_usage.Initialize([](void* allocator_usage) { |
257 delete static_cast<ThreadHeapUsage*>(allocator_usage); | 265 // Delegate the freeing of the per-thread structure to the next-lower |
266 // heap shim. Otherwise this free will re-initialize the TLS on thread | |
267 // exit. | |
268 allocator_dispatch.next->free_function(allocator_dispatch.next, | |
269 allocator_usage); | |
258 }); | 270 }); |
259 } | 271 } |
260 } | 272 } |
261 | 273 |
262 } // namespace debug | 274 } // namespace debug |
263 } // namespace base | 275 } // namespace base |
OLD | NEW |