summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Clark <robclark@freedesktop.org>2017-03-21 19:44:57 -0400
committerRob Clark <robclark@freedesktop.org>2017-03-23 15:22:30 -0400
commitd0dae26ca4e743933f50c1bf4a742e0db8e1994b (patch)
tree89b06b5466f9bcfc0291c3c19b56e4f7215a5ec3
parentb983b054d4f1a6be67105e90f0ae2064f91a762c (diff)
downloadlibdrm-d0dae26ca4e743933f50c1bf4a742e0db8e1994b.tar.gz
libdrm-d0dae26ca4e743933f50c1bf4a742e0db8e1994b.tar.bz2
libdrm-d0dae26ca4e743933f50c1bf4a742e0db8e1994b.zip
freedreno: valgrind support
Signed-off-by: Rob Clark <robclark@freedesktop.org>
-rw-r--r--freedreno/Makefile.am1
-rw-r--r--freedreno/freedreno_bo.c12
-rw-r--r--freedreno/freedreno_bo_cache.c4
-rw-r--r--freedreno/freedreno_priv.h56
-rw-r--r--freedreno/kgsl/kgsl_device.c2
-rw-r--r--freedreno/msm/msm_device.c2
6 files changed, 75 insertions, 2 deletions
diff --git a/freedreno/Makefile.am b/freedreno/Makefile.am
index 0771d146..cbb0d031 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.c b/freedreno/freedreno_bo.c
index 996d6b95..10949ebf 100644
--- a/freedreno/freedreno_bo.c
+++ b/freedreno/freedreno_bo.c
@@ -102,6 +102,8 @@ fd_bo_new(struct fd_device *dev, uint32_t size, uint32_t flags)
bo->bo_reuse = TRUE;
pthread_mutex_unlock(&table_lock);
+ VG_BO_ALLOC(bo);
+
return bo;
}
@@ -118,6 +120,8 @@ fd_bo_from_handle(struct fd_device *dev, uint32_t handle, uint32_t size)
bo = bo_from_handle(dev, size, handle);
+ VG_BO_ALLOC(bo);
+
out_unlock:
pthread_mutex_unlock(&table_lock);
@@ -147,6 +151,8 @@ fd_bo_from_dmabuf(struct fd_device *dev, int fd)
bo = bo_from_handle(dev, size, handle);
+ VG_BO_ALLOC(bo);
+
out_unlock:
pthread_mutex_unlock(&table_lock);
@@ -177,8 +183,10 @@ struct fd_bo * fd_bo_from_name(struct fd_device *dev, uint32_t name)
goto out_unlock;
bo = bo_from_handle(dev, req.size, req.handle);
- if (bo)
+ if (bo) {
set_name(bo, name);
+ VG_BO_ALLOC(bo);
+ }
out_unlock:
pthread_mutex_unlock(&table_lock);
@@ -213,6 +221,8 @@ out:
/* Called under table_lock */
drm_private void bo_del(struct fd_bo *bo)
{
+ VG_BO_FREE(bo);
+
if (bo->map)
drm_munmap(bo->map, bo->size);
diff --git a/freedreno/freedreno_bo_cache.c b/freedreno/freedreno_bo_cache.c
index 7becb0d6..d922f3a9 100644
--- a/freedreno/freedreno_bo_cache.c
+++ b/freedreno/freedreno_bo_cache.c
@@ -33,7 +33,6 @@
#include "freedreno_drmif.h"
#include "freedreno_priv.h"
-
drm_private void bo_del(struct fd_bo *bo);
drm_private extern pthread_mutex_t table_lock;
@@ -102,6 +101,7 @@ fd_bo_cache_cleanup(struct fd_bo_cache *cache, time_t time)
if (time && ((time - bo->free_time) <= 1))
break;
+ VG_BO_OBTAIN(bo);
list_del(&bo->list);
bo_del(bo);
}
@@ -177,6 +177,7 @@ retry:
*size = bucket->size;
bo = find_in_bucket(bucket, flags);
if (bo) {
+ VG_BO_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 +208,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_BO_RELEASE(bo);
list_addtail(&bo->list, &bucket->list);
fd_bo_cache_cleanup(cache, time.tv_sec);
diff --git a/freedreno/freedreno_priv.h b/freedreno/freedreno_priv.h
index 32170391..8dd3ee69 100644
--- a/freedreno/freedreno_priv.h
+++ b/freedreno/freedreno_priv.h
@@ -102,6 +102,9 @@ struct fd_device {
struct fd_bo_cache bo_cache;
int closefd; /* call close(fd) upon destruction */
+
+ /* just for valgrind: */
+ int bo_size;
};
drm_private void fd_bo_cache_init(struct fd_bo_cache *cache, int coarse);
@@ -196,4 +199,57 @@ offset_bytes(void *end, void *start)
return ((char *)end) - ((char *)start);
}
+#ifdef HAVE_VALGRIND
+# include <memcheck.h>
+
+/*
+ * For tracking the backing memory (if valgrind enabled, we force a mmap
+ * for the purposes of tracking)
+ */
+static inline void VG_BO_ALLOC(struct fd_bo *bo)
+{
+ if (bo && RUNNING_ON_VALGRIND) {
+ VALGRIND_MALLOCLIKE_BLOCK(fd_bo_map(bo), bo->size, 0, 1);
+ }
+}
+
+static inline void VG_BO_FREE(struct fd_bo *bo)
+{
+ VALGRIND_FREELIKE_BLOCK(bo->map, 0);
+}
+
+/*
+ * For tracking bo structs that are in the buffer-cache, so that valgrind
+ * doesn't attribute ownership to the first one to allocate the recycled
+ * bo.
+ *
+ * Note that the list_head in fd_bo is used to track the buffers in cache
+ * so disable error reporting on the range while they are in cache so
+ * valgrind doesn't squawk about list traversal.
+ *
+ */
+static inline void VG_BO_RELEASE(struct fd_bo *bo)
+{
+ if (RUNNING_ON_VALGRIND) {
+ VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(bo, bo->dev->bo_size);
+ VALGRIND_MAKE_MEM_NOACCESS(bo, bo->dev->bo_size);
+ VALGRIND_FREELIKE_BLOCK(bo->map, 0);
+ }
+}
+static inline void VG_BO_OBTAIN(struct fd_bo *bo)
+{
+ if (RUNNING_ON_VALGRIND) {
+ VALGRIND_MAKE_MEM_DEFINED(bo, bo->dev->bo_size);
+ VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(bo, bo->dev->bo_size);
+ VALGRIND_MALLOCLIKE_BLOCK(bo->map, bo->size, 0, 1);
+ }
+}
+#else
+static inline void VG_BO_ALLOC(struct fd_bo *bo) {}
+static inline void VG_BO_FREE(struct fd_bo *bo) {}
+static inline void VG_BO_RELEASE(struct fd_bo *bo) {}
+static inline void VG_BO_OBTAIN(struct fd_bo *bo) {}
+#endif
+
+
#endif /* FREEDRENO_PRIV_H_ */
diff --git a/freedreno/kgsl/kgsl_device.c b/freedreno/kgsl/kgsl_device.c
index 175e8378..958e8a72 100644
--- a/freedreno/kgsl/kgsl_device.c
+++ b/freedreno/kgsl/kgsl_device.c
@@ -61,5 +61,7 @@ drm_private struct fd_device * kgsl_device_new(int fd)
dev = &kgsl_dev->base;
dev->funcs = &funcs;
+ dev->bo_size = sizeof(struct kgsl_bo);
+
return dev;
}
diff --git a/freedreno/msm/msm_device.c b/freedreno/msm/msm_device.c
index 727baa44..c454938d 100644
--- a/freedreno/msm/msm_device.c
+++ b/freedreno/msm/msm_device.c
@@ -64,5 +64,7 @@ drm_private struct fd_device * msm_device_new(int fd)
fd_bo_cache_init(&msm_dev->ring_cache, TRUE);
+ dev->bo_size = sizeof(struct msm_bo);
+
return dev;
}