<p dir="ltr">As before, you need to keep the dupfd. There's even a long comment there to explain why.</p>
<div class="gmail_quote">On Jun 23, 2016 7:58 PM, "Rob Herring" <<a href="mailto:robh@kernel.org">robh@kernel.org</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Use the common pipe_screen ref counting and fd hashing functions. The<br>
mutex can be dropped as the pipe loader protects the create_screen()<br>
calls.<br>
<br>
Signed-off-by: Rob Herring <<a href="mailto:robh@kernel.org">robh@kernel.org</a>><br>
Cc: Alexandre Courbot <<a href="mailto:acourbot@nvidia.com">acourbot@nvidia.com</a>><br>
---<br>
 src/gallium/drivers/nouveau/nouveau_screen.c       |  6 --<br>
 src/gallium/drivers/nouveau/nouveau_screen.h       |  4 -<br>
 src/gallium/drivers/nouveau/nv30/nv30_screen.c     |  3 -<br>
 src/gallium/drivers/nouveau/nv50/nv50_screen.c     |  3 -<br>
 src/gallium/drivers/nouveau/nvc0/nvc0_screen.c     |  3 -<br>
 .../winsys/nouveau/drm/nouveau_drm_winsys.c        | 89 ++--------------------<br>
 6 files changed, 7 insertions(+), 101 deletions(-)<br>
<br>
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c<br>
index 2c421cc..41d4bef 100644<br>
--- a/src/gallium/drivers/nouveau/nouveau_screen.c<br>
+++ b/src/gallium/drivers/nouveau/nouveau_screen.c<br>
@@ -159,12 +159,6 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)<br>
    screen->drm = nouveau_drm(&dev->object);<br>
    screen->device = dev;<br>
<br>
-   /*<br>
-    * this is initialized to 1 in nouveau_drm_screen_create after screen<br>
-    * is fully constructed and added to the global screen list.<br>
-    */<br>
-   screen->refcount = -1;<br>
-<br>
    if (dev->chipset < 0xc0) {<br>
       data = &nv04_data;<br>
       size = sizeof(nv04_data);<br>
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h<br>
index 28c4760..55156c3 100644<br>
--- a/src/gallium/drivers/nouveau/nouveau_screen.h<br>
+++ b/src/gallium/drivers/nouveau/nouveau_screen.h<br>
@@ -23,8 +23,6 @@ struct nouveau_screen {<br>
    struct nouveau_client *client;<br>
    struct nouveau_pushbuf *pushbuf;<br>
<br>
-   int refcount;<br>
-<br>
    unsigned vidmem_bindings; /* PIPE_BIND_* where VRAM placement is desired */<br>
    unsigned sysmem_bindings; /* PIPE_BIND_* where GART placement is desired */<br>
    unsigned lowmem_bindings; /* PIPE_BIND_* that require an address < 4 GiB */<br>
@@ -119,8 +117,6 @@ nouveau_screen(struct pipe_screen *pscreen)<br>
    return (struct nouveau_screen *)pscreen;<br>
 }<br>
<br>
-bool nouveau_drm_screen_unref(struct nouveau_screen *screen);<br>
-<br>
 bool<br>
 nouveau_screen_bo_get_handle(struct pipe_screen *pscreen,<br>
                              struct nouveau_bo *bo,<br>
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_screen.c b/src/gallium/drivers/nouveau/nv30/nv30_screen.c<br>
index de798cf..08194fd 100644<br>
--- a/src/gallium/drivers/nouveau/nv30/nv30_screen.c<br>
+++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.c<br>
@@ -406,9 +406,6 @@ nv30_screen_destroy(struct pipe_screen *pscreen)<br>
 {<br>
    struct nv30_screen *screen = nv30_screen(pscreen);<br>
<br>
-   if (!nouveau_drm_screen_unref(&screen->base))<br>
-      return;<br>
-<br>
    if (screen->base.fence.current) {<br>
       struct nouveau_fence *current = NULL;<br>
<br>
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c<br>
index 03f4591..1654d0e 100644<br>
--- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c<br>
+++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c<br>
@@ -425,9 +425,6 @@ nv50_screen_destroy(struct pipe_screen *pscreen)<br>
 {<br>
    struct nv50_screen *screen = nv50_screen(pscreen);<br>
<br>
-   if (!nouveau_drm_screen_unref(&screen->base))<br>
-      return;<br>
-<br>
    if (screen->base.fence.current) {<br>
       struct nouveau_fence *current = NULL;<br>
<br>
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c<br>
index b9437b2..712293a 100644<br>
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c<br>
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c<br>
@@ -481,9 +481,6 @@ nvc0_screen_destroy(struct pipe_screen *pscreen)<br>
 {<br>
    struct nvc0_screen *screen = nvc0_screen(pscreen);<br>
<br>
-   if (!nouveau_drm_screen_unref(&screen->base))<br>
-      return;<br>
-<br>
    if (screen->base.fence.current) {<br>
       struct nouveau_fence *current = NULL;<br>
<br>
diff --git a/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c b/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c<br>
index 598ffcb..b5f4247 100644<br>
--- a/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c<br>
+++ b/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c<br>
@@ -1,12 +1,9 @@<br>
-#include <sys/stat.h><br>
 #include <unistd.h><br>
 #include "pipe/p_context.h"<br>
 #include "pipe/p_state.h"<br>
 #include "util/u_format.h"<br>
 #include "util/u_memory.h"<br>
-#include "util/u_inlines.h"<br>
-#include "util/u_hash_table.h"<br>
-#include "os/os_thread.h"<br>
+#include "util/u_screen.h"<br>
<br>
 #include "nouveau_drm_public.h"<br>
<br>
@@ -16,47 +13,6 @@<br>
 #include <nvif/class.h><br>
 #include <nvif/cl0080.h><br>
<br>
-static struct util_hash_table *fd_tab = NULL;<br>
-<br>
-pipe_static_mutex(nouveau_screen_mutex);<br>
-<br>
-bool nouveau_drm_screen_unref(struct nouveau_screen *screen)<br>
-{<br>
-       int ret;<br>
-       if (screen->refcount == -1)<br>
-               return true;<br>
-<br>
-       pipe_mutex_lock(nouveau_screen_mutex);<br>
-       ret = --screen->refcount;<br>
-       assert(ret >= 0);<br>
-       if (ret == 0)<br>
-               util_hash_table_remove(fd_tab, intptr_to_pointer(screen->drm->fd));<br>
-       pipe_mutex_unlock(nouveau_screen_mutex);<br>
-       return ret == 0;<br>
-}<br>
-<br>
-static unsigned hash_fd(void *key)<br>
-{<br>
-    int fd = pointer_to_intptr(key);<br>
-    struct stat stat;<br>
-    fstat(fd, &stat);<br>
-<br>
-    return stat.st_dev ^ stat.st_ino ^ stat.st_rdev;<br>
-}<br>
-<br>
-static int compare_fd(void *key1, void *key2)<br>
-{<br>
-    int fd1 = pointer_to_intptr(key1);<br>
-    int fd2 = pointer_to_intptr(key2);<br>
-    struct stat stat1, stat2;<br>
-    fstat(fd1, &stat1);<br>
-    fstat(fd2, &stat2);<br>
-<br>
-    return stat1.st_dev != stat2.st_dev ||<br>
-           stat1.st_ino != stat2.st_ino ||<br>
-           stat1.st_rdev != stat2.st_rdev;<br>
-}<br>
-<br>
 PUBLIC struct pipe_screen *<br>
 nouveau_drm_screen_create(int fd)<br>
 {<br>
@@ -64,36 +20,13 @@ nouveau_drm_screen_create(int fd)<br>
        struct nouveau_device *dev = NULL;<br>
        struct nouveau_screen *(*init)(struct nouveau_device *);<br>
        struct nouveau_screen *screen = NULL;<br>
-       int ret, dupfd;<br>
-<br>
-       pipe_mutex_lock(nouveau_screen_mutex);<br>
-       if (!fd_tab) {<br>
-               fd_tab = util_hash_table_create(hash_fd, compare_fd);<br>
-               if (!fd_tab) {<br>
-                       pipe_mutex_unlock(nouveau_screen_mutex);<br>
-                       return NULL;<br>
-               }<br>
-       }<br>
-<br>
-       screen = util_hash_table_get(fd_tab, intptr_to_pointer(fd));<br>
-       if (screen) {<br>
-               screen->refcount++;<br>
-               pipe_mutex_unlock(nouveau_screen_mutex);<br>
-               return &screen->base;<br>
-       }<br>
+       struct pipe_screen *pscreen = pipe_screen_reference(fd);<br>
+       int ret;<br>
<br>
-       /* Since the screen re-use is based on the device node and not the fd,<br>
-        * create a copy of the fd to be owned by the device. Otherwise a<br>
-        * scenario could occur where two screens are created, and the first<br>
-        * one is shut down, along with the fd being closed. The second<br>
-        * (identical) screen would now have a reference to the closed fd. We<br>
-        * avoid this by duplicating the original fd. Note that<br>
-        * nouveau_device_wrap does not close the fd in case of a device<br>
-        * creation error.<br>
-        */<br>
-       dupfd = dup(fd);<br>
+       if (pscreen)<br>
+               return pscreen;<br>
<br>
-       ret = nouveau_drm_new(dupfd, &drm);<br>
+       ret = nouveau_drm_new(fd, &drm);<br>
        if (ret)<br>
                goto err;<br>
<br>
@@ -135,13 +68,7 @@ nouveau_drm_screen_create(int fd)<br>
        if (!screen || !screen->base.context_create)<br>
                goto err;<br>
<br>
-       /* Use dupfd in hash table, to avoid errors if the original fd gets<br>
-        * closed by its owner. The hash key needs to live at least as long as<br>
-        * the screen.<br>
-        */<br>
-       util_hash_table_set(fd_tab, intptr_to_pointer(dupfd), screen);<br>
-       screen->refcount = 1;<br>
-       pipe_mutex_unlock(nouveau_screen_mutex);<br>
+       pipe_screen_reference_init(&screen->base, fd);<br>
        return &screen->base;<br>
<br>
 err:<br>
@@ -150,8 +77,6 @@ err:<br>
        } else {<br>
                nouveau_device_del(&dev);<br>
                nouveau_drm_del(&drm);<br>
-               close(dupfd);<br>
        }<br>
-       pipe_mutex_unlock(nouveau_screen_mutex);<br>
        return NULL;<br>
 }<br>
--<br>
2.9.0<br>
<br>
</blockquote></div>