Add present bytes when recording allocations.
When an allocation is freed, add information about the total
present bytes in the allocation that can be used to tell the
usage of allocations. This also applies to realloc operations
that free the previous pointer.
Add new unit tests for this functionality.
Test: All unit tests pass.
Change-Id: Id3a253e4beb1c7342711137a2bf7ebed4e25d973
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index fce6c24..7e96169 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -682,6 +682,13 @@
if (DebugCallsDisabled() || pointer == nullptr) {
return g_dispatch->free(pointer);
}
+
+ size_t size;
+ if (g_debug->config().options() & RECORD_ALLOCS) {
+ // Need to get the size before disabling debug calls.
+ size = debug_malloc_usable_size(pointer);
+ }
+
ScopedConcurrentLock lock;
ScopedDisableDebugCalls disable;
ScopedBacktraceSignalBlocker blocked;
@@ -690,11 +697,16 @@
return;
}
+ int64_t present_bytes = -1;
memory_trace::Entry* entry = nullptr;
if (g_debug->config().options() & RECORD_ALLOCS) {
// In order to preserve the order of operations, reserve the entry before
// performing the operation.
entry = g_debug->record->ReserveEntry();
+
+ // Need to get the present bytes before the pointer is freed in case the
+ // memory is released during the free call.
+ present_bytes = g_debug->record->GetPresentBytes(pointer, size);
}
TimedResult result = InternalFree(pointer);
@@ -703,6 +715,7 @@
*entry = memory_trace::Entry{.tid = gettid(),
.type = memory_trace::FREE,
.ptr = reinterpret_cast<uint64_t>(pointer),
+ .present_bytes = present_bytes,
.start_ns = result.GetStartTimeNS(),
.end_ns = result.GetEndTimeNS()};
}
@@ -815,6 +828,13 @@
if (DebugCallsDisabled()) {
return g_dispatch->realloc(pointer, bytes);
}
+
+ size_t old_size;
+ if (pointer != nullptr && g_debug->config().options() & RECORD_ALLOCS) {
+ // Need to get the size before disabling debug calls.
+ old_size = debug_malloc_usable_size(pointer);
+ }
+
ScopedConcurrentLock lock;
ScopedDisableDebugCalls disable;
ScopedBacktraceSignalBlocker blocked;
@@ -845,6 +865,13 @@
return nullptr;
}
+ int64_t present_bytes = -1;
+ if (g_debug->config().options() & RECORD_ALLOCS) {
+ // Need to get the present bytes before the pointer is freed in case the
+ // memory is released during the free call.
+ present_bytes = g_debug->record->GetPresentBytes(pointer, old_size);
+ }
+
if (bytes == 0) {
TimedResult result = InternalFree(pointer);
@@ -854,6 +881,7 @@
.ptr = 0,
.size = 0,
.u.old_ptr = reinterpret_cast<uint64_t>(pointer),
+ .present_bytes = present_bytes,
.start_ns = result.GetStartTimeNS(),
.end_ns = result.GetEndTimeNS()};
}
@@ -957,6 +985,7 @@
.ptr = reinterpret_cast<uint64_t>(new_pointer),
.size = bytes,
.u.old_ptr = reinterpret_cast<uint64_t>(pointer),
+ .present_bytes = present_bytes,
.start_ns = result.GetStartTimeNS(),
.end_ns = result.GetEndTimeNS()};
}