[Mesa-dev] [RFC 2/7] pipe-loader-drm: Add common pipe_screen refcounting

Rob Herring robh at kernel.org
Fri Jun 17 17:45:31 UTC 2016


Some gallium drivers have implemented reference counting of pipe_screen
to avoid creating multiple screens for a device. Move this into the
pipe-loader where it can be shared.

Not completely sure, but it should not necessary to dup() the fd as
dri2_create_screen does that for us already.

Signed-off-by: Rob Herring <robh at kernel.org>
Cc: Emil Velikov <emil.l.velikov at gmail.com>
---
 .../auxiliary/pipe-loader/pipe_loader_drm.c        | 66 +++++++++++++++++++++-
 src/gallium/include/pipe/p_screen.h                |  1 +
 2 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c b/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c
index 62f109f..71169ed 100644
--- a/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c
+++ b/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c
@@ -34,6 +34,7 @@
 #include <stdio.h>
 #include <xf86drm.h>
 #include <unistd.h>
+#include <sys/stat.h>
 
 #include "loader.h"
 #include "target-helpers/drm_helper_public.h"
@@ -41,9 +42,12 @@
 #include "pipe_loader_priv.h"
 #include "pipe/p_screen.h"
 
+#include "os/os_thread.h"
 #include "util/u_memory.h"
 #include "util/u_dl.h"
 #include "util/u_debug.h"
+#include "util/u_pointer.h"
+#include "util/u_hash_table.h"
 
 #define DRM_RENDER_NODE_DEV_NAME_FORMAT "%s/renderD%d"
 #define DRM_RENDER_NODE_MAX_NODES 63
@@ -266,14 +270,50 @@ pipe_loader_drm_probe(struct pipe_loader_device **devs, int ndev)
    return j;
 }
 
+static struct util_hash_table *fd_tab = NULL;
+pipe_static_mutex(loader_mutex);
+static int refcnt;
+
+static unsigned hash_fd(void *key)
+{
+   int fd = pointer_to_intptr(key);
+   struct stat stat;
+   fstat(fd, &stat);
+
+   return stat.st_dev ^ stat.st_ino ^ stat.st_rdev;
+}
+
+static int compare_fd(void *key1, void *key2)
+{
+   int fd1 = pointer_to_intptr(key1);
+   int fd2 = pointer_to_intptr(key2);
+   struct stat stat1, stat2;
+   fstat(fd1, &stat1);
+   fstat(fd2, &stat2);
+
+   return stat1.st_dev != stat2.st_dev ||
+         stat1.st_ino != stat2.st_ino ||
+         stat1.st_rdev != stat2.st_rdev;
+}
+
 static void
 pipe_loader_drm_release(struct pipe_loader_device **dev)
 {
    struct pipe_loader_drm_device *ddev = pipe_loader_drm_device(*dev);
    struct pipe_screen *pscreen = ddev->base.pscreen;
+   int fd = ddev->fd;
 
-   pscreen->destroy(pscreen);
+   pipe_mutex_lock(loader_mutex);
+   if (pscreen) {
+      if (--pscreen->refcnt != 0) {
+         pipe_mutex_unlock(loader_mutex);
+         return;
+      }
 
+      pscreen->destroy(pscreen);
+
+      util_hash_table_remove(fd_tab, intptr_to_pointer(fd));
+   }
 #ifndef GALLIUM_STATIC_TARGETS
    if (ddev->lib)
       util_dl_close(ddev->lib);
@@ -283,6 +323,8 @@ pipe_loader_drm_release(struct pipe_loader_device **dev)
    FREE(ddev->base.driver_name);
    FREE(ddev);
    *dev = NULL;
+
+   pipe_mutex_unlock(loader_mutex);
 }
 
 static const struct drm_conf_ret *
@@ -301,10 +343,30 @@ static struct pipe_screen *
 pipe_loader_drm_create_screen(struct pipe_loader_device *dev)
 {
    struct pipe_loader_drm_device *ddev = pipe_loader_drm_device(dev);
+   int fd = ddev->fd;
    struct pipe_screen *pscreen = NULL;
 
-   pscreen = ddev->dd->create_screen(fd);
+   pipe_mutex_lock(loader_mutex);
+   if (!fd_tab) {
+      fd_tab = util_hash_table_create(hash_fd, compare_fd);
+      if (!fd_tab)
+         goto unlock;
+   }
+
+   pscreen = util_hash_table_get(fd_tab, intptr_to_pointer(fd));
+   if (pscreen) {
+      pscreen->refcnt++;
+      goto unlock;
+   } else {
+      pscreen = ddev->dd->create_screen(fd);
+      if (pscreen)
+         util_hash_table_set(fd_tab, intptr_to_pointer(fd), pscreen);
+      pscreen->refcnt = 1;
+   }
+
+unlock:
    ddev->base.pscreen = pscreen;
+   pipe_mutex_unlock(loader_mutex);
    return pscreen;
 }
 
diff --git a/src/gallium/include/pipe/p_screen.h b/src/gallium/include/pipe/p_screen.h
index 755291a..28a3f71 100644
--- a/src/gallium/include/pipe/p_screen.h
+++ b/src/gallium/include/pipe/p_screen.h
@@ -66,6 +66,7 @@ struct pipe_memory_info;
  * context.
  */
 struct pipe_screen {
+   int refcnt;
    void (*destroy)( struct pipe_screen * );
 
    const char *(*get_name)( struct pipe_screen * );
-- 
2.7.4



More information about the mesa-dev mailing list