[Freedreno] [RFC] freedreno: valgrind support
Rob Clark
robdclark at gmail.com
Wed Mar 22 11:54:34 UTC 2017
From: Rob Clark <robclark at freedesktop.org>
---
This is mostly an attempt at teaching valgrind about the bo cache pool,
so it would not think that gem objects returned to the bo cache were
leaked. Unfortunately the list head node in the gem bo is used to
store the bo in the pool. This is why I also have to disable/enable
error reporting, otherwise valgrind thinks iterating the list is
invalid access.
But DISABLE/ENABLE_ADDR_ERROR_REPORTING_IN_RANGE() is quite chatty,
and I end up with like 90MB worth of:
--6162-- memcheck: modify_ignore_ranges: add 0x7D87590 0x7D875DF
--6162-- memcheck: now have 27 ranges:
--6162-- memcheck: [0] 0000000000000000-000000000531f92f NotIgnored
--6162-- memcheck: [1] 000000000531f930-000000000531f97f ClientReq
--6162-- memcheck: [2] 000000000531f980-000000000538865f NotIgnored
--6162-- memcheck: [3] 0000000005388660-00000000053886af ClientReq
--6162-- memcheck: [4] 00000000053886b0-00000000053a1ccf NotIgnored
--6162-- memcheck: [5] 00000000053a1cd0-00000000053a1d1f ClientReq
--6162-- memcheck: [6] 00000000053a1d20-00000000054df5af NotIgnored
--6162-- memcheck: [7] 00000000054df5b0-00000000054df5ff ClientReq
--6162-- memcheck: [8] 00000000054df600-00000000055807ef NotIgnored
--6162-- memcheck: [9] 00000000055807f0-000000000558083f ClientReq
--6162-- memcheck: [10] 0000000005580840-0000000006ae611f NotIgnored
--6162-- memcheck: [11] 0000000006ae6120-0000000006ae616f ClientReq
--6162-- memcheck: [12] 0000000006ae6170-0000000006bb0d0f NotIgnored
--6162-- memcheck: [13] 0000000006bb0d10-0000000006bb0d5f ClientReq
--6162-- memcheck: [14] 0000000006bb0d60-000000000780350f NotIgnored
--6162-- memcheck: [15] 0000000007803510-000000000780355f ClientReq
--6162-- memcheck: [16] 0000000007803560-0000000007d8758f NotIgnored
--6162-- memcheck: [17] 0000000007d87590-0000000007d875df ClientReq
--6162-- memcheck: [18] 0000000007d875e0-0000000007decc5f NotIgnored
--6162-- memcheck: [19] 0000000007decc60-0000000007deccaf ClientReq
--6162-- memcheck: [20] 0000000007deccb0-000000000820eb7f NotIgnored
--6162-- memcheck: [21] 000000000820eb80-000000000820ebcf ClientReq
--6162-- memcheck: [22] 000000000820ebd0-00000000095b9c6f NotIgnored
--6162-- memcheck: [23] 00000000095b9c70-00000000095b9cbf ClientReq
--6162-- memcheck: [24] 00000000095b9cc0-000000000963fdef NotIgnored
--6162-- memcheck: [25] 000000000963fdf0-000000000963fe3f ClientReq
--6162-- memcheck: [26] 000000000963fe40-ffffffffffffffff NotIgnored
Not really a valgrind expert, so not sure if there is a better way to
handle this.
I did notice that intel was using valgrind to track the mmap's, and
even track coherency of buffers, which is kinda clever. I should
probably do at least some of that sometime, but that isn't exactly
what I'm trying to do here.
Note that if the pipe_screen was destroyed, then the fd_device would
be destroyed and the cached bo's freed. Although that seems not to
be reliable. In particular, I'm looking at a memory leak in glmark2,
which does destroy/recreate EGL contexts. But the screen does not
appear to be destoyed. Something like:
glmark2 -b :duration=1 --run-forever
will reproduce. Bo's that end up in the cache make valgrind think
that buffers associated with the previous context have been leaked.
freedreno/Makefile.am | 1 +
freedreno/freedreno_bo_cache.c | 17 +++++++++++++++++
2 files changed, 18 insertions(+)
diff --git a/freedreno/Makefile.am b/freedreno/Makefile.am
index 0771d14..cbb0d03 100644
--- a/freedreno/Makefile.am
+++ b/freedreno/Makefile.am
@@ -5,6 +5,7 @@ AM_CFLAGS = \
$(WARN_CFLAGS) \
-I$(top_srcdir) \
$(PTHREADSTUBS_CFLAGS) \
+ $(VALGRIND_CFLAGS) \
-I$(top_srcdir)/include/drm
libdrm_freedreno_la_LTLIBRARIES = libdrm_freedreno.la
diff --git a/freedreno/freedreno_bo_cache.c b/freedreno/freedreno_bo_cache.c
index 7becb0d..0f8ff10 100644
--- a/freedreno/freedreno_bo_cache.c
+++ b/freedreno/freedreno_bo_cache.c
@@ -33,6 +33,20 @@
#include "freedreno_drmif.h"
#include "freedreno_priv.h"
+#ifdef HAVE_VALGRIND
+#include <memcheck.h>
+# define VG_RELEASE(__ptr) do { \
+ VALGRIND_MAKE_MEM_NOACCESS((__ptr), sizeof(*(__ptr))); \
+ VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE((__ptr), sizeof(*(__ptr))); \
+ } while (0);
+# define VG_OBTAIN(__ptr) do { \
+ VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE((__ptr), sizeof(*(__ptr))); \
+ VALGRIND_MAKE_MEM_DEFINED((__ptr), sizeof(*(__ptr))); \
+ } while (0);
+#else
+# define VG_RELEASE(__ptr) do { } while (0)
+# define VG_OBTAIN(__ptr) do { } while (0)
+#endif
drm_private void bo_del(struct fd_bo *bo);
drm_private extern pthread_mutex_t table_lock;
@@ -102,6 +116,7 @@ fd_bo_cache_cleanup(struct fd_bo_cache *cache, time_t time)
if (time && ((time - bo->free_time) <= 1))
break;
+ VG_OBTAIN(bo);
list_del(&bo->list);
bo_del(bo);
}
@@ -177,6 +192,7 @@ retry:
*size = bucket->size;
bo = find_in_bucket(bucket, flags);
if (bo) {
+ VG_OBTAIN(bo);
if (bo->funcs->madvise(bo, TRUE) <= 0) {
/* we've lost the backing pages, delete and try again: */
pthread_mutex_lock(&table_lock);
@@ -207,6 +223,7 @@ fd_bo_cache_free(struct fd_bo_cache *cache, struct fd_bo *bo)
clock_gettime(CLOCK_MONOTONIC, &time);
bo->free_time = time.tv_sec;
+ VG_RELEASE(bo);
list_addtail(&bo->list, &bucket->list);
fd_bo_cache_cleanup(cache, time.tv_sec);
--
2.9.3
More information about the Freedreno
mailing list