summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2015-06-17 22:56:15 -0700
committerEric Anholt <[email protected]>2015-06-17 23:53:49 -0700
commit62d153ea37b1bf572c39aab8ec46099fc903362d (patch)
tree052721f0c4a868e840aeb3de7f892e955d270ca9 /src/gallium/drivers
parent2b1cdb0eddb73f62e4848d4b64840067f1f70865 (diff)
vc4: Track the number of BOs allocated and their size.
This is useful for BO leak debugging.
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r--src/gallium/drivers/vc4/vc4_bufmgr.c101
-rw-r--r--src/gallium/drivers/vc4/vc4_screen.h6
2 files changed, 100 insertions, 7 deletions
diff --git a/src/gallium/drivers/vc4/vc4_bufmgr.c b/src/gallium/drivers/vc4/vc4_bufmgr.c
index 69a7584e14b..eef7e9dc16f 100644
--- a/src/gallium/drivers/vc4/vc4_bufmgr.c
+++ b/src/gallium/drivers/vc4/vc4_bufmgr.c
@@ -34,6 +34,47 @@
#include "vc4_context.h"
#include "vc4_screen.h"
+static bool dump_stats = false;
+
+static void
+vc4_bo_dump_stats(struct vc4_screen *screen)
+{
+ struct vc4_bo_cache *cache = &screen->bo_cache;
+
+ fprintf(stderr, " BOs allocated: %d\n", screen->bo_count);
+ fprintf(stderr, " BOs size: %dkb\n", screen->bo_size / 102);
+ fprintf(stderr, " BOs cached: %d\n", cache->bo_count);
+ fprintf(stderr, " BOs cached size: %dkb\n", cache->bo_size / 102);
+
+ if (!list_empty(&cache->time_list)) {
+ struct vc4_bo *first = LIST_ENTRY(struct vc4_bo,
+ cache->time_list.next,
+ time_list);
+ struct vc4_bo *last = LIST_ENTRY(struct vc4_bo,
+ cache->time_list.prev,
+ time_list);
+
+ fprintf(stderr, " oldest cache time: %ld\n",
+ (long)first->free_time);
+ fprintf(stderr, " newest cache time: %ld\n",
+ (long)last->free_time);
+
+ struct timespec time;
+ clock_gettime(CLOCK_MONOTONIC, &time);
+ fprintf(stderr, " now: %ld\n",
+ time.tv_sec);
+ }
+}
+
+static void
+vc4_bo_remove_from_cache(struct vc4_bo_cache *cache, struct vc4_bo *bo)
+{
+ list_del(&bo->time_list);
+ list_del(&bo->size_list);
+ cache->bo_count--;
+ cache->bo_size -= bo->size;
+}
+
static struct vc4_bo *
vc4_bo_from_cache(struct vc4_screen *screen, uint32_t size, const char *name)
{
@@ -60,8 +101,7 @@ vc4_bo_from_cache(struct vc4_screen *screen, uint32_t size, const char *name)
}
pipe_reference_init(&bo->reference, 1);
- list_del(&bo->time_list);
- list_del(&bo->size_list);
+ vc4_bo_remove_from_cache(cache, bo);
bo->name = name;
}
@@ -78,8 +118,14 @@ vc4_bo_alloc(struct vc4_screen *screen, uint32_t size, const char *name)
size = align(size, 4096);
bo = vc4_bo_from_cache(screen, size, name);
- if (bo)
+ if (bo) {
+ if (dump_stats) {
+ fprintf(stderr, "Allocated %s %dkb from cache:\n",
+ name, size / 1024);
+ vc4_bo_dump_stats(screen);
+ }
return bo;
+ }
bo = CALLOC_STRUCT(vc4_bo);
if (!bo)
@@ -116,6 +162,13 @@ vc4_bo_alloc(struct vc4_screen *screen, uint32_t size, const char *name)
abort();
}
+ screen->bo_count++;
+ screen->bo_size += bo->size;
+ if (dump_stats) {
+ fprintf(stderr, "Allocated %s %dkb:\n", name, size / 1024);
+ vc4_bo_dump_stats(screen);
+ }
+
return bo;
}
@@ -153,6 +206,17 @@ vc4_bo_free(struct vc4_bo *bo)
if (ret != 0)
fprintf(stderr, "close object %d: %s\n", bo->handle, strerror(errno));
+ screen->bo_count--;
+ screen->bo_size -= bo->size;
+
+ if (dump_stats) {
+ fprintf(stderr, "Freed %s%s%dkb:\n",
+ bo->name ? bo->name : "",
+ bo->name ? " " : "",
+ bo->size / 1024);
+ vc4_bo_dump_stats(screen);
+ }
+
free(bo);
}
@@ -160,18 +224,29 @@ static void
free_stale_bos(struct vc4_screen *screen, time_t time)
{
struct vc4_bo_cache *cache = &screen->bo_cache;
+ bool freed_any = false;
list_for_each_entry_safe(struct vc4_bo, bo, &cache->time_list,
time_list) {
+ if (dump_stats && !freed_any) {
+ fprintf(stderr, "Freeing stale BOs:\n");
+ vc4_bo_dump_stats(screen);
+ freed_any = true;
+ }
+
/* If it's more than a second old, free it. */
if (time - bo->free_time > 2) {
- list_del(&bo->time_list);
- list_del(&bo->size_list);
+ vc4_bo_remove_from_cache(cache, bo);
vc4_bo_free(bo);
} else {
break;
}
}
+
+ if (dump_stats && freed_any) {
+ fprintf(stderr, "Freed stale BOs:\n");
+ vc4_bo_dump_stats(screen);
+ }
}
void
@@ -214,6 +289,14 @@ vc4_bo_last_unreference_locked_timed(struct vc4_bo *bo, time_t time)
bo->free_time = time;
list_addtail(&bo->size_list, &cache->size_list[page_index]);
list_addtail(&bo->time_list, &cache->time_list);
+ cache->bo_count++;
+ cache->bo_size += bo->size;
+ if (dump_stats) {
+ fprintf(stderr, "Freed %s %dkb to cache:\n",
+ bo->name, bo->size / 1024);
+ vc4_bo_dump_stats(screen);
+ }
+ bo->name = NULL;
free_stale_bos(screen, time);
}
@@ -450,8 +533,12 @@ vc4_bufmgr_destroy(struct pipe_screen *pscreen)
list_for_each_entry_safe(struct vc4_bo, bo, &cache->time_list,
time_list) {
- list_del(&bo->time_list);
- list_del(&bo->size_list);
+ vc4_bo_remove_from_cache(cache, bo);
vc4_bo_free(bo);
}
+
+ if (dump_stats) {
+ fprintf(stderr, "BO stats after screen destroy:\n");
+ vc4_bo_dump_stats(screen);
+ }
}
diff --git a/src/gallium/drivers/vc4/vc4_screen.h b/src/gallium/drivers/vc4/vc4_screen.h
index fb08cc1c7a0..5992e371093 100644
--- a/src/gallium/drivers/vc4/vc4_screen.h
+++ b/src/gallium/drivers/vc4/vc4_screen.h
@@ -67,7 +67,13 @@ struct vc4_screen {
uint32_t size_list_size;
pipe_mutex lock;
+
+ uint32_t bo_size;
+ uint32_t bo_count;
} bo_cache;
+
+ uint32_t bo_size;
+ uint32_t bo_count;
};
static inline struct vc4_screen *