2 * Copyright 2015, Michael Lotz <mmlr@mlotz.ch>.
3 * Distributed under the terms of the MIT License.
7 #include "malloc_debug_api.h"
16 static heap_implementation
* sCurrentHeap
= NULL
;
19 // #pragma mark - Heap Debug API
23 heap_debug_start_wall_checking(int msInterval
)
25 if (sCurrentHeap
->start_wall_checking
!= NULL
)
26 return sCurrentHeap
->start_wall_checking(msInterval
);
28 return B_NOT_SUPPORTED
;
33 heap_debug_stop_wall_checking()
35 if (sCurrentHeap
->stop_wall_checking
!= NULL
)
36 return sCurrentHeap
->stop_wall_checking();
38 return B_NOT_SUPPORTED
;
43 heap_debug_set_paranoid_validation(bool enabled
)
45 if (sCurrentHeap
->set_paranoid_validation
!= NULL
)
46 sCurrentHeap
->set_paranoid_validation(enabled
);
51 heap_debug_set_memory_reuse(bool enabled
)
53 if (sCurrentHeap
->set_memory_reuse
!= NULL
)
54 sCurrentHeap
->set_memory_reuse(enabled
);
59 heap_debug_set_debugger_calls(bool enabled
)
61 if (sCurrentHeap
->set_debugger_calls
!= NULL
)
62 sCurrentHeap
->set_debugger_calls(enabled
);
67 heap_debug_set_default_alignment(size_t defaultAlignment
)
69 if (sCurrentHeap
->set_default_alignment
!= NULL
)
70 sCurrentHeap
->set_default_alignment(defaultAlignment
);
75 heap_debug_validate_heaps()
77 if (sCurrentHeap
->validate_heaps
!= NULL
)
78 sCurrentHeap
->validate_heaps();
83 heap_debug_validate_walls()
85 if (sCurrentHeap
->validate_walls
!= NULL
)
86 sCurrentHeap
->validate_walls();
91 heap_debug_dump_allocations(bool statsOnly
, thread_id thread
)
93 if (sCurrentHeap
->dump_allocations
!= NULL
)
94 sCurrentHeap
->dump_allocations(statsOnly
, thread
);
99 heap_debug_dump_heaps(bool dumpAreas
, bool dumpBins
)
101 if (sCurrentHeap
->dump_heaps
!= NULL
)
102 sCurrentHeap
->dump_heaps(dumpAreas
, dumpBins
);
107 heap_debug_malloc_with_guard_page(size_t size
)
109 if (sCurrentHeap
->malloc_with_guard_page
!= NULL
)
110 return sCurrentHeap
->malloc_with_guard_page(size
);
117 heap_debug_get_allocation_info(void *address
, size_t *size
,
120 if (sCurrentHeap
->get_allocation_info
!= NULL
)
121 return sCurrentHeap
->get_allocation_info(address
, size
, thread
);
123 return B_NOT_SUPPORTED
;
128 heap_debug_set_dump_allocations_on_exit(bool enabled
)
130 if (sCurrentHeap
->set_dump_allocations_on_exit
!= NULL
)
131 return sCurrentHeap
->set_dump_allocations_on_exit(enabled
);
133 return B_NOT_SUPPORTED
;
138 heap_debug_set_stack_trace_depth(size_t stackTraceDepth
)
140 if (sCurrentHeap
->set_stack_trace_depth
!= NULL
)
141 return sCurrentHeap
->set_stack_trace_depth(stackTraceDepth
);
143 return B_NOT_SUPPORTED
;
147 // #pragma mark - Init
153 const char *mode
= getenv("MALLOC_DEBUG");
154 if (mode
== NULL
|| strchr(mode
, 'g') == NULL
)
155 sCurrentHeap
= &__mallocDebugHeap
;
157 sCurrentHeap
= &__mallocGuardedHeap
;
159 status_t result
= sCurrentHeap
->init();
164 if (strchr(mode
, 'p') != NULL
)
165 heap_debug_set_paranoid_validation(true);
166 if (strchr(mode
, 'r') != NULL
)
167 heap_debug_set_memory_reuse(false);
168 if (strchr(mode
, 'e') != NULL
)
169 heap_debug_set_dump_allocations_on_exit(true);
171 size_t defaultAlignment
= 0;
172 const char *argument
= strchr(mode
, 'a');
174 && sscanf(argument
, "a%" B_SCNuSIZE
, &defaultAlignment
) == 1) {
175 heap_debug_set_default_alignment(defaultAlignment
);
178 size_t stackTraceDepth
= 0;
179 argument
= strchr(mode
, 's');
181 && sscanf(argument
, "s%" B_SCNuSIZE
, &stackTraceDepth
) == 1) {
182 heap_debug_set_stack_trace_depth(stackTraceDepth
);
185 int wallCheckInterval
= 0;
186 argument
= strchr(mode
, 'w');
188 && sscanf(argument
, "w%d", &wallCheckInterval
) == 1) {
189 heap_debug_start_wall_checking(wallCheckInterval
);
198 __heap_terminate_after()
200 if (sCurrentHeap
->terminate_after
!= NULL
)
201 sCurrentHeap
->terminate_after();
206 __heap_before_fork(void)
212 __heap_after_fork_child(void)
218 __heap_after_fork_parent(void)
223 // #pragma mark - Public API
227 memalign(size_t alignment
, size_t size
)
229 return sCurrentHeap
->memalign(alignment
, size
);
236 return sCurrentHeap
->malloc(size
);
243 sCurrentHeap
->free(address
);
248 realloc(void* address
, size_t newSize
)
250 return sCurrentHeap
->realloc(address
, newSize
);
255 calloc(size_t numElements
, size_t size
)
257 if (sCurrentHeap
->calloc
!= NULL
)
258 return sCurrentHeap
->calloc(numElements
, size
);
260 void* address
= malloc(numElements
* size
);
262 memset(address
, 0, numElements
* size
);
271 if (sCurrentHeap
->valloc
!= NULL
)
272 return sCurrentHeap
->valloc(size
);
274 return memalign(B_PAGE_SIZE
, size
);
279 posix_memalign(void **pointer
, size_t alignment
, size_t size
)
281 if (sCurrentHeap
->posix_memalign
!= NULL
)
282 return sCurrentHeap
->posix_memalign(pointer
, alignment
, size
);
284 if (!is_valid_alignment(alignment
))
287 *pointer
= memalign(alignment
, size
);
288 if (*pointer
== NULL
)