diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index 085453ff8cf9ad4c69638c998a0f168baa00af5c..408d184884fc8be8abbd31a0c1a0727f2c364d5d 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -309,6 +309,7 @@ static void dump(int fd, const char** arguments) { btif_debug_config_dump(fd); BTA_HfClientDumpStatistics(fd); wakelock_debug_dump(fd); + osi_allocator_debug_dump(fd); alarm_debug_dump(fd); #if (BTSNOOP_MEM == TRUE) btif_debug_btsnoop_dump(fd); diff --git a/system/osi/include/allocator.h b/system/osi/include/allocator.h index 890722b4831c135b32415405f74f29a3f6626bcf..ef03f9a710bc7bf6e2665155ee6cfde5c950df58 100644 --- a/system/osi/include/allocator.h +++ b/system/osi/include/allocator.h @@ -46,3 +46,8 @@ void osi_free(void* ptr); // |p_ptr| is a pointer to the buffer pointer to be reset. // |p_ptr| cannot be NULL. void osi_free_and_reset(void** p_ptr); + +// Dump allocation-related statistics and debug info to the |fd| file +// descriptor. +// The information is in user-readable text format. The |fd| must be valid. +void osi_allocator_debug_dump(int fd); diff --git a/system/osi/src/allocation_tracker.cc b/system/osi/src/allocation_tracker.cc index 78bd2596ce083fc9d4be10c23cb01beebe4ef746..461e3428349fe63bc9c16371d7ed6363d051c07a 100644 --- a/system/osi/src/allocation_tracker.cc +++ b/system/osi/src/allocation_tracker.cc @@ -43,6 +43,12 @@ static std::unordered_map<void*, allocation_t*> allocations; static std::mutex tracker_lock; static bool enabled = false; +// Memory allocation statistics +static size_t alloc_counter = 0; +static size_t free_counter = 0; +static size_t alloc_total_size = 0; +static size_t free_total_size = 0; + void allocation_tracker_init(void) { std::unique_lock<std::mutex> lock(tracker_lock); if (enabled) return; @@ -98,6 +104,10 @@ void* allocation_tracker_notify_alloc(uint8_t allocator_id, void* ptr, std::unique_lock<std::mutex> lock(tracker_lock); if (!enabled || !ptr) return ptr; + // Keep statistics + alloc_counter++; + alloc_total_size += allocation_tracker_resize_for_canary(requested_size); + return_ptr = ((char*)ptr) + canary_size; auto map_entry = allocations.find(return_ptr); @@ -126,6 +136,7 @@ void* allocation_tracker_notify_alloc(uint8_t allocator_id, void* ptr, void* allocation_tracker_notify_free(UNUSED_ATTR uint8_t allocator_id, void* ptr) { std::unique_lock<std::mutex> lock(tracker_lock); + if (!enabled || !ptr) return ptr; auto map_entry = allocations.find(ptr); @@ -135,6 +146,11 @@ void* allocation_tracker_notify_free(UNUSED_ATTR uint8_t allocator_id, CHECK(!allocation->freed); // Must not be a double free CHECK(allocation->allocator_id == allocator_id); // Must be from the same allocator + + // Keep statistics + free_counter++; + free_total_size += allocation_tracker_resize_for_canary(allocation->size); + allocation->freed = true; UNUSED_ATTR const char* beginning_canary = ((char*)ptr) - canary_size; @@ -156,3 +172,15 @@ void* allocation_tracker_notify_free(UNUSED_ATTR uint8_t allocator_id, size_t allocation_tracker_resize_for_canary(size_t size) { return (!enabled) ? size : size + (2 * canary_size); } + +void osi_allocator_debug_dump(int fd) { + dprintf(fd, "\nBluetooth Memory Allocation Statistics:\n"); + + std::unique_lock<std::mutex> lock(tracker_lock); + + dprintf(fd, " Total allocated/free/used counts : %zu / %zu / %zu\n", + alloc_counter, free_counter, alloc_counter - free_counter); + dprintf(fd, " Total allocated/free/used octets : %zu / %zu / %zu\n", + alloc_total_size, free_total_size, + alloc_total_size - free_total_size); +}