[Mesa-dev] [PATCH v5 1/2] gallium/winsys/kms: Fix possible leak in map/unmap.

Lepton Wu lepton at chromium.org
Fri Mar 16 18:09:03 UTC 2018


If user calls map twice for kms_sw_displaytarget, the first mapped
buffer could get leaked. Instead of calling mmap every time, just
reuse previous mapping. Since user could map same displaytarget with
different flags, we have to keep two different pointers, one for rw
mapping and one for ro mapping. Also introduce reference count for
mapped buffer so we can unmap them at right time.

Change-Id: I65308f0ff2640bd57b2577c6a3469540c9722859
Signed-off-by: Lepton Wu <lepton at chromium.org>
---
 .../winsys/sw/kms-dri/kms_dri_sw_winsys.c     | 44 +++++++++++++++----
 1 file changed, 36 insertions(+), 8 deletions(-)

diff --git a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c
index 22e1c936ac5..b4fb852833d 100644
--- a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c
+++ b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c
@@ -70,8 +70,10 @@ struct kms_sw_displaytarget
 
    uint32_t handle;
    void *mapped;
+   void *ro_mapped;
 
    int ref_count;
+   int map_count;
    struct list_head link;
 };
 
@@ -170,6 +172,14 @@ kms_sw_displaytarget_destroy(struct sw_winsys *ws,
    if (kms_sw_dt->ref_count > 0)
       return;
 
+   if (kms_sw_dt->map_count > 0) {
+      DEBUG_PRINT("KMS-DEBUG: fix leaked map buffer %u\n", kms_sw_dt->handle);
+      munmap(kms_sw_dt->mapped, kms_sw_dt->size);
+      kms_sw_dt->mapped = NULL;
+      munmap(kms_sw_dt->ro_mapped, kms_sw_dt->size);
+      kms_sw_dt->ro_mapped = NULL;
+   }
+
    memset(&destroy_req, 0, sizeof destroy_req);
    destroy_req.handle = kms_sw_dt->handle;
    drmIoctl(kms_sw->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_req);
@@ -198,16 +208,21 @@ kms_sw_displaytarget_map(struct sw_winsys *ws,
       return NULL;
 
    prot = (flags == PIPE_TRANSFER_READ) ? PROT_READ : (PROT_READ | PROT_WRITE);
-   kms_sw_dt->mapped = mmap(0, kms_sw_dt->size, prot, MAP_SHARED,
-                            kms_sw->fd, map_req.offset);
-
-   if (kms_sw_dt->mapped == MAP_FAILED)
-      return NULL;
+   void **ptr = (flags == PIPE_TRANSFER_READ) ? &kms_sw_dt->ro_mapped : &kms_sw_dt->mapped;
+   if (!*ptr) {
+      void *tmp = mmap(0, kms_sw_dt->size, prot, MAP_SHARED,
+                       kms_sw->fd, map_req.offset);
+      if (tmp == MAP_FAILED)
+         return NULL;
+      *ptr = tmp;
+   }
 
    DEBUG_PRINT("KMS-DEBUG: mapped buffer %u (size %u) at %p\n",
-         kms_sw_dt->handle, kms_sw_dt->size, kms_sw_dt->mapped);
+         kms_sw_dt->handle, kms_sw_dt->size, *ptr);
+
+   kms_sw_dt->map_count++;
 
-   return kms_sw_dt->mapped;
+   return *ptr;
 }
 
 static struct kms_sw_displaytarget *
@@ -277,10 +292,23 @@ kms_sw_displaytarget_unmap(struct sw_winsys *ws,
 {
    struct kms_sw_displaytarget *kms_sw_dt = kms_sw_displaytarget(dt);
 
-   DEBUG_PRINT("KMS-DEBUG: unmapped buffer %u (was %p)\n", kms_sw_dt->handle, kms_sw_dt->mapped);
+   if (!kms_sw_dt->map_count)  {
+      DEBUG_PRINT("KMS-DEBUG: ignore duplicated unmap %u", kms_sw_dt->handle);
+      return;
+   }
+   kms_sw_dt->map_count--;
+   if (kms_sw_dt->map_count) {
+      DEBUG_PRINT("KMS-DEBUG: ignore unmap for busy buffer %u", kms_sw_dt->handle);
+      return;
+   }
 
+   DEBUG_PRINT("KMS-DEBUG: unmapped buffer %u (was %p)\n", kms_sw_dt->handle, kms_sw_dt->mapped);
+   DEBUG_PRINT("KMS-DEBUG: unmapped buffer %u (was %p)\n", kms_sw_dt->handle, kms_sw_dt->ro_mapped);
+ 
    munmap(kms_sw_dt->mapped, kms_sw_dt->size);
    kms_sw_dt->mapped = NULL;
+   munmap(kms_sw_dt->ro_mapped, kms_sw_dt->size);
+   kms_sw_dt->ro_mapped = NULL;
 }
 
 static struct sw_displaytarget *
-- 
2.16.2.804.g6dcf76e118-goog



More information about the mesa-dev mailing list