minigbm: unmap right before buffer destruction
Regardless of the allocator, we want to make sure any mappings
we create are eventually freed. This patch adds logic to
drv_bo_destroy to free any mappings before the GEM close
ioctl is called.
BUG=chromium:764871
TEST=gbmtest, mmap_test -g on eve
Change-Id: I8f4edb4bc01ff6e1d71a60e0309e77e9fc3840f4
Reviewed-on: https://chromium-review.googlesource.com/441916
Commit-Ready: Gurchetan Singh <gurchetansingh@chromium.org>
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
Reviewed-by: Joe Kniss <djmk@google.com>
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
Reviewed-by: Tomasz Figa <tfiga@chromium.org>
diff --git a/drv.c b/drv.c
index ff99893..b43b771 100644
--- a/drv.c
+++ b/drv.c
@@ -305,7 +305,6 @@
{
size_t plane;
uintptr_t total = 0;
- size_t map_count = 0;
struct driver *drv = bo->drv;
pthread_mutex_lock(&drv->driver_lock);
@@ -313,22 +312,13 @@
for (plane = 0; plane < bo->num_planes; plane++)
drv_decrement_reference_count(drv, bo, plane);
- for (plane = 0; plane < bo->num_planes; plane++) {
- void *ptr;
-
+ for (plane = 0; plane < bo->num_planes; plane++)
total += drv_get_reference_count(drv, bo, plane);
- map_count += !drmHashLookup(bo->drv->map_table, bo->handles[plane].u32, &ptr);
- }
pthread_mutex_unlock(&drv->driver_lock);
if (total == 0) {
- /*
- * If we leak a reference to the GEM handle being freed here in the mapping table,
- * we risk using the mapping table entry later for a completely different BO that
- * gets the same handle. (See b/38250067.)
- */
- assert(!map_count);
+ assert(drv_map_info_destroy(bo) == 0);
bo->drv->backend->bo_destroy(bo);
}
diff --git a/helpers.c b/helpers.c
index 9d72a6c..979521a 100644
--- a/helpers.c
+++ b/helpers.c
@@ -318,6 +318,35 @@
return munmap(data->addr, data->length);
}
+int drv_map_info_destroy(struct bo *bo)
+{
+ int ret;
+ void *ptr;
+ size_t plane;
+ struct map_info *data;
+
+ /*
+ * This function is called right before the buffer is destroyed. It will free any mappings
+ * associated with the buffer.
+ */
+
+ for (plane = 0; plane < bo->num_planes; plane++) {
+ if (!drmHashLookup(bo->drv->map_table, bo->handles[plane].u32, &ptr)) {
+ data = (struct map_info *)ptr;
+ ret = bo->drv->backend->bo_unmap(bo, data);
+ if (ret) {
+ fprintf(stderr, "drv: munmap failed");
+ return ret;
+ }
+
+ drmHashDelete(bo->drv->map_table, data->handle);
+ free(data);
+ }
+ }
+
+ return 0;
+}
+
uintptr_t drv_get_reference_count(struct driver *drv, struct bo *bo, size_t plane)
{
void *count;
diff --git a/helpers.h b/helpers.h
index b580643..0cc1a17 100644
--- a/helpers.h
+++ b/helpers.h
@@ -14,6 +14,7 @@
int drv_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
uint32_t flags);
int drv_dumb_bo_destroy(struct bo *bo);
+int drv_map_info_destroy(struct bo *bo);
int drv_gem_bo_destroy(struct bo *bo);
int drv_prime_bo_import(struct bo *bo, struct drv_import_fd_data *data);
void *drv_dumb_bo_map(struct bo *bo, struct map_info *data, size_t plane, int prot);