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

Side by Side Diff: base/allocator/allocator_shim.cc

Issue 2697123007: base: Add support for malloc zones to the allocator shim (Closed)
Patch Set: Windows compile error. Created 3 years, 10 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 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/allocator/allocator_shim.h" 5 #include "base/allocator/allocator_shim.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 8
9 #include <new> 9 #include <new>
10 10
11 #include "base/atomicops.h" 11 #include "base/atomicops.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "base/process/process_metrics.h" 14 #include "base/process/process_metrics.h"
15 #include "base/threading/platform_thread.h" 15 #include "base/threading/platform_thread.h"
16 #include "build/build_config.h" 16 #include "build/build_config.h"
17 17
18 #if !defined(OS_WIN) 18 #if !defined(OS_WIN)
19 #include <unistd.h> 19 #include <unistd.h>
20 #else 20 #else
21 #include "base/allocator/winheap_stubs_win.h" 21 #include "base/allocator/winheap_stubs_win.h"
22 #endif 22 #endif
23 23
24 #if defined(OS_MACOSX)
25 #include <malloc/malloc.h>
26 #endif
27
24 // No calls to malloc / new in this file. They would would cause re-entrancy of 28 // No calls to malloc / new in this file. They would would cause re-entrancy of
25 // the shim, which is hard to deal with. Keep this code as simple as possible 29 // the shim, which is hard to deal with. Keep this code as simple as possible
26 // and don't use any external C++ object here, not even //base ones. Even if 30 // and don't use any external C++ object here, not even //base ones. Even if
27 // they are safe to use today, in future they might be refactored. 31 // they are safe to use today, in future they might be refactored.
28 32
29 namespace { 33 namespace {
30 34
31 using namespace base; 35 using namespace base;
32 36
33 subtle::AtomicWord g_chain_head = reinterpret_cast<subtle::AtomicWord>( 37 subtle::AtomicWord g_chain_head = reinterpret_cast<subtle::AtomicWord>(
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 93
90 namespace base { 94 namespace base {
91 namespace allocator { 95 namespace allocator {
92 96
93 void SetCallNewHandlerOnMallocFailure(bool value) { 97 void SetCallNewHandlerOnMallocFailure(bool value) {
94 g_call_new_handler_on_malloc_failure = value; 98 g_call_new_handler_on_malloc_failure = value;
95 } 99 }
96 100
97 void* UncheckedAlloc(size_t size) { 101 void* UncheckedAlloc(size_t size) {
98 const allocator::AllocatorDispatch* const chain_head = GetChainHead(); 102 const allocator::AllocatorDispatch* const chain_head = GetChainHead();
99 return chain_head->alloc_function(chain_head, size); 103 return chain_head->alloc_function(chain_head, size, nullptr);
100 } 104 }
101 105
102 void InsertAllocatorDispatch(AllocatorDispatch* dispatch) { 106 void InsertAllocatorDispatch(AllocatorDispatch* dispatch) {
103 // Loop in case of (an unlikely) race on setting the list head. 107 // Loop in case of (an unlikely) race on setting the list head.
104 size_t kMaxRetries = 7; 108 size_t kMaxRetries = 7;
105 for (size_t i = 0; i < kMaxRetries; ++i) { 109 for (size_t i = 0; i < kMaxRetries; ++i) {
106 const AllocatorDispatch* chain_head = GetChainHead(); 110 const AllocatorDispatch* chain_head = GetChainHead();
107 dispatch->next = chain_head; 111 dispatch->next = chain_head;
108 112
109 // This function guarantees to be thread-safe w.r.t. concurrent 113 // This function guarantees to be thread-safe w.r.t. concurrent
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 // - If the std::new_handler is NOT set just return nullptr. 155 // - If the std::new_handler is NOT set just return nullptr.
152 // - If the std::new_handler is set: 156 // - If the std::new_handler is set:
153 // - Assume it will abort() if it fails (very likely the new_handler will 157 // - Assume it will abort() if it fails (very likely the new_handler will
154 // just suicide priting a message). 158 // just suicide priting a message).
155 // - Assume it did succeed if it returns, in which case reattempt the alloc. 159 // - Assume it did succeed if it returns, in which case reattempt the alloc.
156 160
157 void* ShimCppNew(size_t size) { 161 void* ShimCppNew(size_t size) {
158 const allocator::AllocatorDispatch* const chain_head = GetChainHead(); 162 const allocator::AllocatorDispatch* const chain_head = GetChainHead();
159 void* ptr; 163 void* ptr;
160 do { 164 do {
161 ptr = chain_head->alloc_function(chain_head, size); 165 void* context = nullptr;
166 #if defined(OS_MACOSX)
167 context = malloc_default_zone();
168 #endif
169 ptr = chain_head->alloc_function(chain_head, size, context);
162 } while (!ptr && CallNewHandler(size)); 170 } while (!ptr && CallNewHandler(size));
163 return ptr; 171 return ptr;
164 } 172 }
165 173
166 void ShimCppDelete(void* address) { 174 void ShimCppDelete(void* address) {
175 void* context = nullptr;
176 #if defined(OS_MACOSX)
177 context = malloc_default_zone();
178 #endif
167 const allocator::AllocatorDispatch* const chain_head = GetChainHead(); 179 const allocator::AllocatorDispatch* const chain_head = GetChainHead();
168 return chain_head->free_function(chain_head, address); 180 return chain_head->free_function(chain_head, address, context);
169 } 181 }
170 182
171 void* ShimMalloc(size_t size) { 183 void* ShimMalloc(size_t size, void* context) {
172 const allocator::AllocatorDispatch* const chain_head = GetChainHead(); 184 const allocator::AllocatorDispatch* const chain_head = GetChainHead();
173 void* ptr; 185 void* ptr;
174 do { 186 do {
175 ptr = chain_head->alloc_function(chain_head, size); 187 ptr = chain_head->alloc_function(chain_head, size, context);
176 } while (!ptr && g_call_new_handler_on_malloc_failure && 188 } while (!ptr && g_call_new_handler_on_malloc_failure &&
177 CallNewHandler(size)); 189 CallNewHandler(size));
178 return ptr; 190 return ptr;
179 } 191 }
180 192
181 void* ShimCalloc(size_t n, size_t size) { 193 void* ShimCalloc(size_t n, size_t size, void* context) {
182 const allocator::AllocatorDispatch* const chain_head = GetChainHead(); 194 const allocator::AllocatorDispatch* const chain_head = GetChainHead();
183 void* ptr; 195 void* ptr;
184 do { 196 do {
185 ptr = chain_head->alloc_zero_initialized_function(chain_head, n, size); 197 ptr = chain_head->alloc_zero_initialized_function(chain_head, n, size,
198 context);
186 } while (!ptr && g_call_new_handler_on_malloc_failure && 199 } while (!ptr && g_call_new_handler_on_malloc_failure &&
187 CallNewHandler(size)); 200 CallNewHandler(size));
188 return ptr; 201 return ptr;
189 } 202 }
190 203
191 void* ShimRealloc(void* address, size_t size) { 204 void* ShimRealloc(void* address, size_t size, void* context) {
192 // realloc(size == 0) means free() and might return a nullptr. We should 205 // realloc(size == 0) means free() and might return a nullptr. We should
193 // not call the std::new_handler in that case, though. 206 // not call the std::new_handler in that case, though.
194 const allocator::AllocatorDispatch* const chain_head = GetChainHead(); 207 const allocator::AllocatorDispatch* const chain_head = GetChainHead();
195 void* ptr; 208 void* ptr;
196 do { 209 do {
197 ptr = chain_head->realloc_function(chain_head, address, size); 210 ptr = chain_head->realloc_function(chain_head, address, size, context);
198 } while (!ptr && size && g_call_new_handler_on_malloc_failure && 211 } while (!ptr && size && g_call_new_handler_on_malloc_failure &&
199 CallNewHandler(size)); 212 CallNewHandler(size));
200 return ptr; 213 return ptr;
201 } 214 }
202 215
203 void* ShimMemalign(size_t alignment, size_t size) { 216 void* ShimMemalign(size_t alignment, size_t size, void* context) {
204 const allocator::AllocatorDispatch* const chain_head = GetChainHead(); 217 const allocator::AllocatorDispatch* const chain_head = GetChainHead();
205 void* ptr; 218 void* ptr;
206 do { 219 do {
207 ptr = chain_head->alloc_aligned_function(chain_head, alignment, size); 220 ptr = chain_head->alloc_aligned_function(chain_head, alignment, size,
221 context);
208 } while (!ptr && g_call_new_handler_on_malloc_failure && 222 } while (!ptr && g_call_new_handler_on_malloc_failure &&
209 CallNewHandler(size)); 223 CallNewHandler(size));
210 return ptr; 224 return ptr;
211 } 225 }
212 226
213 int ShimPosixMemalign(void** res, size_t alignment, size_t size) { 227 int ShimPosixMemalign(void** res, size_t alignment, size_t size) {
214 // posix_memalign is supposed to check the arguments. See tc_posix_memalign() 228 // posix_memalign is supposed to check the arguments. See tc_posix_memalign()
215 // in tc_malloc.cc. 229 // in tc_malloc.cc.
216 if (((alignment % sizeof(void*)) != 0) || 230 if (((alignment % sizeof(void*)) != 0) ||
217 ((alignment & (alignment - 1)) != 0) || (alignment == 0)) { 231 ((alignment & (alignment - 1)) != 0) || (alignment == 0)) {
218 return EINVAL; 232 return EINVAL;
219 } 233 }
220 void* ptr = ShimMemalign(alignment, size); 234 void* ptr = ShimMemalign(alignment, size, nullptr);
221 *res = ptr; 235 *res = ptr;
222 return ptr ? 0 : ENOMEM; 236 return ptr ? 0 : ENOMEM;
223 } 237 }
224 238
225 void* ShimValloc(size_t size) { 239 void* ShimValloc(size_t size, void* context) {
226 return ShimMemalign(GetCachedPageSize(), size); 240 return ShimMemalign(GetCachedPageSize(), size, context);
227 } 241 }
228 242
229 void* ShimPvalloc(size_t size) { 243 void* ShimPvalloc(size_t size) {
230 // pvalloc(0) should allocate one page, according to its man page. 244 // pvalloc(0) should allocate one page, according to its man page.
231 if (size == 0) { 245 if (size == 0) {
232 size = GetCachedPageSize(); 246 size = GetCachedPageSize();
233 } else { 247 } else {
234 size = (size + GetCachedPageSize() - 1) & ~(GetCachedPageSize() - 1); 248 size = (size + GetCachedPageSize() - 1) & ~(GetCachedPageSize() - 1);
235 } 249 }
236 return ShimMemalign(GetCachedPageSize(), size); 250 return ShimMemalign(GetCachedPageSize(), size, nullptr);
Primiano Tucci (use gerrit) 2017/02/20 10:33:05 add a comment saying that this is nullptr because
237 } 251 }
238 252
239 void ShimFree(void* address) { 253 void ShimFree(void* address, void* context) {
240 const allocator::AllocatorDispatch* const chain_head = GetChainHead(); 254 const allocator::AllocatorDispatch* const chain_head = GetChainHead();
241 return chain_head->free_function(chain_head, address); 255 return chain_head->free_function(chain_head, address, context);
242 } 256 }
243 257
244 size_t ShimGetSizeEstimate(const void* address) { 258 size_t ShimGetSizeEstimate(const void* address, void* context) {
245 const allocator::AllocatorDispatch* const chain_head = GetChainHead(); 259 const allocator::AllocatorDispatch* const chain_head = GetChainHead();
246 return chain_head->get_size_estimate_function(chain_head, 260 return chain_head->get_size_estimate_function(
247 const_cast<void*>(address)); 261 chain_head, const_cast<void*>(address), context);
248 } 262 }
249 263
250 unsigned ShimBatchMalloc(size_t size, void** results, unsigned num_requested) { 264 unsigned ShimBatchMalloc(size_t size,
265 void** results,
266 unsigned num_requested,
267 void* context) {
251 const allocator::AllocatorDispatch* const chain_head = GetChainHead(); 268 const allocator::AllocatorDispatch* const chain_head = GetChainHead();
252 return chain_head->batch_malloc_function(chain_head, size, results, 269 return chain_head->batch_malloc_function(chain_head, size, results,
253 num_requested); 270 num_requested, context);
254 } 271 }
255 272
256 void ShimBatchFree(void** to_be_freed, unsigned num_to_be_freed) { 273 void ShimBatchFree(void** to_be_freed,
274 unsigned num_to_be_freed,
275 void* context) {
257 const allocator::AllocatorDispatch* const chain_head = GetChainHead(); 276 const allocator::AllocatorDispatch* const chain_head = GetChainHead();
258 return chain_head->batch_free_function(chain_head, to_be_freed, 277 return chain_head->batch_free_function(chain_head, to_be_freed,
259 num_to_be_freed); 278 num_to_be_freed, context);
260 } 279 }
261 280
262 void ShimFreeDefiniteSize(void* ptr, size_t size) { 281 void ShimFreeDefiniteSize(void* ptr, size_t size, void* context) {
263 const allocator::AllocatorDispatch* const chain_head = GetChainHead(); 282 const allocator::AllocatorDispatch* const chain_head = GetChainHead();
264 return chain_head->free_definite_size_function(chain_head, ptr, size); 283 return chain_head->free_definite_size_function(chain_head, ptr, size,
284 context);
265 } 285 }
266 286
267 } // extern "C" 287 } // extern "C"
268 288
269 #if !defined(OS_WIN) && !defined(OS_MACOSX) 289 #if !defined(OS_WIN) && !defined(OS_MACOSX)
270 // Cpp symbols (new / delete) should always be routed through the shim layer 290 // Cpp symbols (new / delete) should always be routed through the shim layer
271 // except on Windows and macOS where the malloc intercept is deep enough that it 291 // except on Windows and macOS where the malloc intercept is deep enough that it
272 // also catches the cpp calls. 292 // also catches the cpp calls.
273 #include "base/allocator/allocator_shim_override_cpp_symbols.h" 293 #include "base/allocator/allocator_shim_override_cpp_symbols.h"
274 #endif 294 #endif
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 // Cross-checks. 333 // Cross-checks.
314 334
315 #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) 335 #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
316 #error The allocator shim should not be compiled when building for memory tools. 336 #error The allocator shim should not be compiled when building for memory tools.
317 #endif 337 #endif
318 338
319 #if (defined(__GNUC__) && defined(__EXCEPTIONS)) || \ 339 #if (defined(__GNUC__) && defined(__EXCEPTIONS)) || \
320 (defined(_HAS_EXCEPTIONS) && _HAS_EXCEPTIONS) 340 (defined(_HAS_EXCEPTIONS) && _HAS_EXCEPTIONS)
321 #error This code cannot be used when exceptions are turned on. 341 #error This code cannot be used when exceptions are turned on.
322 #endif 342 #endif
OLDNEW
« no previous file with comments | « base/allocator/allocator_shim.h ('k') | base/allocator/allocator_shim_default_dispatch_to_glibc.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698