[Skiboot] [PATCH v2] mem_region: Merge similar allocations when dumping
Oliver O'Halloran
oohall at gmail.com
Tue Jul 31 17:05:27 AEST 2018
Currently we print one line for each allocation done at runtime when
dumping the memory allocations. We do a few thousand allocations at
boot so this can result in a huge amount of text being printed which
is a) slow to print, and b) Can result in the log buffer overflowing
which destroys otherwise useful information.
This patch adds a de-duplication to this memory allocation dump by
merging "similar" allocations (same location, same size) into one.
Unfortunately, the algorithm used to do the de-duplication is quadratic,
but considering we only dump the allocations in the event of a fatal
error I think this is acceptable. I also did some benchmarking and found
that on a ZZ it takes ~3ms to do a dump with 12k allocations. On a Zaius
it's slightly longer at about ~10ms for 10k allocs. However, the
difference there was due to the output being written to the UART.
This patch also bumps the log level to PR_NOTICE. PR_INFO messages are
suppressed at the default log level, which probably isn't something you
want considering we only dump the allocations when we run out of skiboot
heap space.
Signed-off-by: Oliver O'Halloran <oohall at gmail.com>
---
v2: Only perform the dump on the first allocation failure rather
than every time. This allows us to extract useful debug information
when there is an allocation failure without spamming the console
too much.
Fixed some 80 cols junk.
---
core/mem_region.c | 49 ++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 42 insertions(+), 7 deletions(-)
diff --git a/core/mem_region.c b/core/mem_region.c
index 0051ea6ece61..bd387f3c3773 100644
--- a/core/mem_region.c
+++ b/core/mem_region.c
@@ -96,7 +96,8 @@ static struct mem_region skiboot_cpu_stacks = {
struct alloc_hdr {
bool free : 1;
bool prev_free : 1;
- unsigned long num_longs : BITS_PER_LONG-2; /* Including header. */
+ bool printed : 1;
+ unsigned long num_longs : BITS_PER_LONG-3; /* Including header. */
const char *location;
};
@@ -285,7 +286,7 @@ static bool region_is_reserved(struct mem_region *region)
void mem_dump_allocs(void)
{
struct mem_region *region;
- struct alloc_hdr *hdr;
+ struct alloc_hdr *h, *i;
/* Second pass: populate property data */
prlog(PR_INFO, "Memory regions:\n");
@@ -301,11 +302,40 @@ void mem_dump_allocs(void)
prlog(PR_INFO, " no allocs\n");
continue;
}
- for (hdr = region_start(region); hdr; hdr = next_hdr(region, hdr)) {
- if (hdr->free)
+
+ /*
+ * XXX: When dumping the allocation list we coalase allocations
+ * with the same location and size into a single line. This is
+ * quadratic, but it makes the dump human-readable and the raw
+ * dump sometimes causes the log buffer to wrap.
+ */
+ for (h = region_start(region); h; h = next_hdr(region, h))
+ h->printed = false;
+
+ for (h = region_start(region); h; h = next_hdr(region, h)) {
+ unsigned long bytes;
+ int count = 0;
+
+ if (h->free)
continue;
- prlog(PR_INFO, " 0x%.8lx %s\n", hdr->num_longs * sizeof(long),
- hdr_location(hdr));
+ if (h->printed)
+ continue;
+
+ for (i = h; i; i = next_hdr(region, i)) {
+ if (i->free)
+ continue;
+ if (i->num_longs != h->num_longs)
+ continue;
+ if (strcmp(i->location, h->location))
+ continue;
+
+ i->printed = true;
+ count++;
+ }
+
+ bytes = h->num_longs * sizeof(long);
+ prlog(PR_NOTICE, " % 8d allocs of 0x%.8lx bytes at %s (total 0x%lx)\n",
+ count, bytes, hdr_location(h), bytes * count);
}
}
}
@@ -439,6 +469,7 @@ found:
void *mem_alloc(struct mem_region *region, size_t size, size_t align,
const char *location)
{
+ static bool dumped = false;
void *r;
assert(lock_held_by_me(®ion->free_list_lock));
@@ -449,7 +480,11 @@ void *mem_alloc(struct mem_region *region, size_t size, size_t align,
prerror("mem_alloc(0x%lx, 0x%lx, \"%s\", %s) failed !\n",
size, align, location, region->name);
- mem_dump_allocs();
+ if (!dumped) {
+ mem_dump_allocs();
+ dumped = true;
+ }
+
return NULL;
}
--
2.9.5
More information about the Skiboot
mailing list