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 <new> |
9 #include <type_traits> | 10 #include <type_traits> |
10 | 11 |
11 #include "base/allocator/allocator_shim.h" | 12 #include "base/allocator/allocator_shim.h" |
12 #include "base/allocator/features.h" | 13 #include "base/allocator/features.h" |
13 #include "base/logging.h" | 14 #include "base/logging.h" |
14 #include "base/threading/thread_local_storage.h" | 15 #include "base/threading/thread_local_storage.h" |
15 #include "build/build_config.h" | 16 #include "build/build_config.h" |
16 | 17 |
17 #if defined(OS_MACOSX) || defined(OS_IOS) | 18 #if defined(OS_MACOSX) || defined(OS_IOS) |
18 #include <malloc/malloc.h> | 19 #include <malloc/malloc.h> |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 ThreadHeapUsage* GetOrCreateThreadUsage() { | 138 ThreadHeapUsage* GetOrCreateThreadUsage() { |
138 ThreadHeapUsage* allocator_usage = | 139 ThreadHeapUsage* allocator_usage = |
139 static_cast<ThreadHeapUsage*>(g_thread_allocator_usage.Get()); | 140 static_cast<ThreadHeapUsage*>(g_thread_allocator_usage.Get()); |
140 if (allocator_usage == kInitializingSentinel) | 141 if (allocator_usage == kInitializingSentinel) |
141 return nullptr; // Re-entrancy case. | 142 return nullptr; // Re-entrancy case. |
142 | 143 |
143 if (allocator_usage == nullptr) { | 144 if (allocator_usage == nullptr) { |
144 // Prevent reentrancy due to the allocation below. | 145 // Prevent reentrancy due to the allocation below. |
145 g_thread_allocator_usage.Set(kInitializingSentinel); | 146 g_thread_allocator_usage.Set(kInitializingSentinel); |
146 | 147 |
147 allocator_usage = new ThreadHeapUsage; | 148 // Delegate the allocation of the per-thread structure to the underlying |
| 149 // heap shim, for symmetry with the deallocation. Otherwise interposing |
| 150 // shims may mis-attribute or mis-direct this allocation. |
| 151 const AllocatorDispatch* next = allocator_dispatch.next; |
| 152 allocator_usage = new (next->alloc_function(next, sizeof(ThreadHeapUsage))) |
| 153 ThreadHeapUsage(); |
| 154 static_assert(std::is_pod<ThreadHeapUsage>::value, |
| 155 "AllocatorDispatch must be POD"); |
148 memset(allocator_usage, 0, sizeof(*allocator_usage)); | 156 memset(allocator_usage, 0, sizeof(*allocator_usage)); |
149 g_thread_allocator_usage.Set(allocator_usage); | 157 g_thread_allocator_usage.Set(allocator_usage); |
150 } | 158 } |
151 | 159 |
152 return allocator_usage; | 160 return allocator_usage; |
153 } | 161 } |
154 | 162 |
155 } // namespace | 163 } // namespace |
156 | 164 |
157 ThreadHeapUsageTracker::ThreadHeapUsageTracker() : thread_usage_(nullptr) { | 165 ThreadHeapUsageTracker::ThreadHeapUsageTracker() : thread_usage_(nullptr) { |
(...skipping 89 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 |