* Fix KDL output to use kprintf instead of dprintf.

* Make the allocations command available even without leak checking. The sizes
  that are dumped aren't as accurate without leak checking info, but having the
  address and max size is already helpful.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31811 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2009-07-27 14:47:04 +00:00
parent 27dd21091a
commit 5efec82035

View File

@ -285,7 +285,7 @@ dump_page(heap_page *page)
for (addr_t *temp = page->free_list; temp != NULL; temp = (addr_t *)*temp)
count++;
dprintf("\t\tpage %p: bin_index: %u; free_count: %u; empty_index: %u; "
kprintf("\t\tpage %p: bin_index: %u; free_count: %u; empty_index: %u; "
"free_list %p (%lu entr%s)\n", page, page->bin_index, page->free_count,
page->empty_index, page->free_list, count, count == 1 ? "y" : "ies");
}
@ -294,7 +294,7 @@ dump_page(heap_page *page)
static void
dump_bin(heap_bin *bin)
{
dprintf("\telement_size: %lu; max_free_count: %u; page_list %p;\n",
kprintf("\telement_size: %lu; max_free_count: %u; page_list %p;\n",
bin->element_size, bin->max_free_count, bin->page_list);
for (heap_page *temp = bin->page_list; temp != NULL; temp = temp->next)
@ -307,7 +307,7 @@ dump_bin_list(heap_allocator *heap)
{
for (uint32 i = 0; i < heap->bin_count; i++)
dump_bin(&heap->bins[i]);
dprintf("\n");
kprintf("\n");
}
@ -316,21 +316,21 @@ dump_allocator_areas(heap_allocator *heap)
{
heap_area *area = heap->all_areas;
while (area) {
dprintf("\tarea %p: area: %ld; base: 0x%08lx; size: %lu; page_count: "
kprintf("\tarea %p: area: %ld; base: 0x%08lx; size: %lu; page_count: "
"%lu; free_pages: %p (%lu entr%s)\n", area, area->area, area->base,
area->size, area->page_count, area->free_pages,
area->free_page_count, area->free_page_count == 1 ? "y" : "ies");
area = area->all_next;
}
dprintf("\n");
kprintf("\n");
}
static void
dump_allocator(heap_allocator *heap, bool areas, bool bins)
{
dprintf("allocator %p: name: %s; page_size: %lu; bin_count: %lu; pages: "
kprintf("allocator %p: name: %s; page_size: %lu; bin_count: %lu; pages: "
"%lu; free_pages: %lu; empty_areas: %lu\n", heap, heap->name,
heap->page_size, heap->bin_count, heap->total_pages,
heap->total_free_pages, heap->empty_areas);
@ -350,7 +350,7 @@ dump_heap_list(int argc, char **argv)
if (strcmp(argv[1], "grow") == 0) {
// only dump dedicated grow heap info
dprintf("dedicated grow heap:\n");
kprintf("dedicated grow heap:\n");
dump_allocator(sGrowHeap, true, true);
} else if (strcmp(argv[1], "stats") == 0) {
for (uint32 i = 0; i < HEAP_CLASS_COUNT; i++)
@ -370,7 +370,104 @@ dump_heap_list(int argc, char **argv)
}
#if KERNEL_HEAP_LEAK_CHECK
#if !KERNEL_HEAP_LEAK_CHECK
static int
dump_allocations(int argc, char **argv)
{
uint64 heapAddress = 0;
bool statsOnly = false;
for (int32 i = 1; i < argc; i++) {
if (strcmp(argv[i], "stats") == 0)
statsOnly = true;
else if (!evaluate_debug_expression(argv[i], &heapAddress, true)) {
print_debugger_command_usage(argv[0]);
return 0;
}
}
size_t totalSize = 0;
uint32 totalCount = 0;
for (uint32 classIndex = 0; classIndex < HEAP_CLASS_COUNT; classIndex++) {
heap_allocator *heap = sHeaps[classIndex];
if (heapAddress != 0)
heap = (heap_allocator *)(addr_t)heapAddress;
// go through all the pages in all the areas
heap_area *area = heap->all_areas;
while (area) {
for (uint32 i = 0; i < area->page_count; i++) {
heap_page *page = &area->page_table[i];
if (!page->in_use)
continue;
addr_t base = area->base + i * heap->page_size;
if (page->bin_index < heap->bin_count) {
// page is used by a small allocation bin
uint32 elementCount = page->empty_index;
size_t elementSize
= heap->bins[page->bin_index].element_size;
for (uint32 j = 0; j < elementCount;
j++, base += elementSize) {
// walk the free list to see if this element is in use
bool elementInUse = true;
for (addr_t *temp = page->free_list; temp != NULL;
temp = (addr_t *)*temp) {
if ((addr_t)temp == base) {
elementInUse = false;
break;
}
}
if (!elementInUse)
continue;
if (!statsOnly) {
kprintf("address: 0x%08lx; size: %lu bytes\n",
base, elementSize);
}
totalSize += elementSize;
totalCount++;
}
} else {
// page is used by a big allocation, find the page count
uint32 pageCount = 1;
while (i + pageCount < area->page_count
&& area->page_table[i + pageCount].in_use
&& area->page_table[i + pageCount].bin_index
== heap->bin_count
&& area->page_table[i + pageCount].allocation_id
== page->allocation_id)
pageCount++;
size_t size = pageCount * heap->page_size;
if (!statsOnly) {
kprintf("address: 0x%08lx; size: %lu bytes\n", base,
size);
}
totalSize += size;
totalCount++;
// skip the allocated pages
i += pageCount - 1;
}
}
area = area->all_next;
}
if (heapAddress != 0)
break;
}
kprintf("total allocations: %lu; total bytes: %lu\n", totalCount, totalSize);
return 0;
}
#else // !KERNEL_HEAP_LEAK_CHECK
static int
dump_allocations(int argc, char **argv)
@ -437,7 +534,7 @@ dump_allocations(int argc, char **argv)
&& (caller == 0 || info->caller == caller)) {
// interesting...
if (!statsOnly) {
dprintf("team: % 6ld; thread: % 6ld; "
kprintf("team: % 6ld; thread: % 6ld; "
"address: 0x%08lx; size: %lu bytes; "
"caller: %#lx\n", info->team, info->thread,
base, info->size, info->caller);
@ -466,7 +563,7 @@ dump_allocations(int argc, char **argv)
&& (caller == 0 || info->caller == caller)) {
// interesting...
if (!statsOnly) {
dprintf("team: % 6ld; thread: % 6ld;"
kprintf("team: % 6ld; thread: % 6ld;"
" address: 0x%08lx; size: %lu bytes;"
" caller: %#lx\n", info->team, info->thread,
base, info->size, info->caller);
@ -485,7 +582,7 @@ dump_allocations(int argc, char **argv)
}
}
dprintf("total allocations: %lu; total bytes: %lu\n", totalCount, totalSize);
kprintf("total allocations: %lu; total bytes: %lu\n", totalCount, totalSize);
return 0;
}
@ -1738,9 +1835,18 @@ heap_init(addr_t base, size_t size)
"given as the argument, currently only the heap count is printed.\n"
"If <heap> is given, it is interpreted as the address of the heap to\n"
"print infos about.\n", 0);
#if KERNEL_HEAP_LEAK_CHECK
#if !KERNEL_HEAP_LEAK_CHECK
add_debugger_command_etc("allocations", &dump_allocations,
"Dump current allocations",
"Dump current heap allocations",
"[\"stats\"] [<heap>]\n"
"If no parameters are given, all current alloactions are dumped.\n"
"If the optional argument \"stats\" is specified, only the allocation\n"
"counts and no individual allocations are printed\n"
"If a specific heap address is given, only allocations of this\n"
"allocator are dumped\n", 0);
#else // !KERNEL_HEAP_LEAK_CHECK
add_debugger_command_etc("allocations", &dump_allocations,
"Dump current heap allocations",
"[(\"team\" | \"thread\") <id>] [ \"caller\" <address> ] [\"stats\"]\n"
"If no parameters are given, all current alloactions are dumped.\n"
"If \"team\", \"thread\", and/or \"caller\" is specified as the first\n"
@ -1750,13 +1856,13 @@ heap_init(addr_t base, size_t size)
"counts and no individual allocations are printed\n", 0);
add_debugger_command_etc("allocations_per_caller",
&dump_allocations_per_caller,
"Dump current allocations summed up per caller",
"Dump current heap allocations summed up per caller",
"[ \"-c\" ] [ -h <heap> ]\n"
"The current allocations will by summed up by caller (their count and\n"
"size) printed in decreasing order by size or, if \"-c\" is\n"
"specified, by allocation count. If given <heap> specifies the\n"
"address of the heap for which to print the allocations.\n", 0);
#endif
#endif // KERNEL_HEAP_LEAK_CHECK
return B_OK;
}