[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