[Freedreno] [RFC] freedreno: valgrind support
Rob Clark
robdclark at gmail.com
Wed Mar 22 15:24:54 UTC 2017
On Wed, Mar 22, 2017 at 7:54 AM, Rob Clark <robdclark at gmail.com> wrote:
> 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
heh, well just dropping '-v' arg to valgrind drops the extended spam
that enable/disable error checking triggers.
It does seem like maybe I could move the list node to the head of the
block and pretend this is a custom allocator (VALGRIND_MEMPOOL_*), but
that also seems like a bit of a hack..
BR,
-R
> 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