winsys/radeon: fix a race condition in initialization of radeon_winsys::screen
authorMarek Olšák <marek.olsak@amd.com>
Tue, 8 Apr 2014 23:07:52 +0000 (01:07 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Thu, 10 Apr 2014 18:50:17 +0000 (20:50 +0200)
Create the screen in the winsys while the mutex is locked.
This also results in a nice code cleanup!

Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
src/gallium/targets/egl-static/egl_pipe.c
src/gallium/targets/pipe-loader/pipe_r300.c
src/gallium/targets/pipe-loader/pipe_r600.c
src/gallium/targets/pipe-loader/pipe_radeonsi.c
src/gallium/targets/r300/common/drm_target.c
src/gallium/targets/r600/common/drm_target.c
src/gallium/targets/radeonsi/common/drm_target.c
src/gallium/winsys/radeon/drm/radeon_drm_public.h
src/gallium/winsys/radeon/drm/radeon_drm_winsys.c

index eb1cff9c76b456839aca40e8483690d2823ca9a0..ce734fb47110becc984e6c49ca5efd132a827802 100644 (file)
@@ -119,19 +119,9 @@ pipe_r300_create_screen(int fd)
 {
 #if _EGL_PIPE_R300
    struct radeon_winsys *sws;
-   struct pipe_screen *screen;
-
-   sws = radeon_drm_winsys_create(fd);
-   if (!sws)
-      return NULL;
-
-   screen = r300_screen_create(sws);
-   if (!screen)
-      return NULL;
 
-   screen = debug_screen_wrap(screen);
-
-   return screen;
+   sws = radeon_drm_winsys_create(fd, r300_screen_create);
+   return sws ? debug_screen_wrap(sws->screen) : NULL;
 #else
    return NULL;
 #endif
@@ -142,19 +132,9 @@ pipe_r600_create_screen(int fd)
 {
 #if _EGL_PIPE_R600
    struct radeon_winsys *rw;
-   struct pipe_screen *screen;
-
-   rw = radeon_drm_winsys_create(fd);
-   if (!rw)
-      return NULL;
-
-   screen = r600_screen_create(rw);
-   if (!screen)
-      return NULL;
-
-   screen = debug_screen_wrap(screen);
 
-   return screen;
+   rw = radeon_drm_winsys_create(fd, r600_screen_create);
+   return rw ? debug_screen_wrap(rw->screen) : NULL;
 #else
    return NULL;
 #endif
@@ -165,19 +145,9 @@ pipe_radeonsi_create_screen(int fd)
 {
 #if _EGL_PIPE_RADEONSI
    struct radeon_winsys *rw;
-   struct pipe_screen *screen;
-
-   rw = radeon_drm_winsys_create(fd);
-   if (!rw)
-      return NULL;
-
-   screen = radeonsi_screen_create(rw);
-   if (!screen)
-      return NULL;
 
-   screen = debug_screen_wrap(screen);
-
-   return screen;
+   rw = radeon_drm_winsys_create(fd, radeonsi_screen_create);
+   return rw ? debug_screen_wrap(rw->screen) : NULL;
 #else
    return NULL;
 #endif
index 055685996e6ff802a05eda4f24e56cec8d7e30d9..388b091f1447a289c0bd9565484a505ff550db5f 100644 (file)
@@ -8,19 +8,9 @@ static struct pipe_screen *
 create_screen(int fd)
 {
    struct radeon_winsys *sws;
-   struct pipe_screen *screen;
 
-   sws = radeon_drm_winsys_create(fd);
-   if (!sws)
-      return NULL;
-
-   screen = r300_screen_create(sws);
-   if (!screen)
-      return NULL;
-
-   screen = debug_screen_wrap(screen);
-
-   return screen;
+   sws = radeon_drm_winsys_create(fd, r300_screen_create);
+   return sws ? debug_screen_wrap(sws->screen) : NULL;
 }
 
 PUBLIC
index 5d89aca6ec37351b0edae10573ffd52dd689f4e3..0c590875784977a6b61025124fca3feaa82ed374 100644 (file)
@@ -7,19 +7,9 @@ static struct pipe_screen *
 create_screen(int fd)
 {
    struct radeon_winsys *rw;
-   struct pipe_screen *screen;
 
-   rw = radeon_drm_winsys_create(fd);
-   if (!rw)
-      return NULL;
-
-   screen = r600_screen_create(rw);
-   if (!screen)
-      return NULL;
-
-   screen = debug_screen_wrap(screen);
-
-   return screen;
+   rw = radeon_drm_winsys_create(fd, r600_screen_create);
+   return rw ? debug_screen_wrap(rw->screen) : NULL;
 }
 
 PUBLIC
index 48b2b5dff3fe4b139b7cc3a32baff9f497a8e609..406ba1e1ddb30520fb39fa38c6c9bc803d58d9de 100644 (file)
@@ -7,19 +7,9 @@ static struct pipe_screen *
 create_screen(int fd)
 {
    struct radeon_winsys *rw;
-   struct pipe_screen *screen;
 
-   rw = radeon_drm_winsys_create(fd);
-   if (!rw)
-      return NULL;
-
-   screen = radeonsi_screen_create(rw);
-   if (!screen)
-      return NULL;
-
-   screen = debug_screen_wrap(screen);
-
-   return screen;
+   rw = radeon_drm_winsys_create(fd, radeonsi_screen_create);
+   return rw ? debug_screen_wrap(rw->screen) : NULL;
 }
 
 PUBLIC
index 9b484469d476d02ccfc370dcd86d200c50924868..dff83dacba26af443b74dead852a8258555d1afa 100644 (file)
@@ -36,19 +36,8 @@ create_screen(int fd)
 {
    struct radeon_winsys *sws;
 
-   sws = radeon_drm_winsys_create(fd);
-   if (!sws)
-      return NULL;
-
-   if (!sws->screen) {
-      sws->screen = r300_screen_create(sws);
-      if (!sws->screen)
-         return NULL;
-
-      sws->screen = debug_screen_wrap(sws->screen);
-   }
-
-   return sws->screen;
+   sws = radeon_drm_winsys_create(fd, r300_screen_create);
+   return sws ? debug_screen_wrap(sws->screen) : NULL;
 }
 
 /* Technically this is only true for kernels >= 3.12, which
index ab1eec6ac9a3b82d982dd59bd5733c92fbf41ceb..09250c79fb9d16d60b36001d2d4c9dbab99c9a12 100644 (file)
@@ -35,19 +35,8 @@ static struct pipe_screen *create_screen(int fd)
 {
    struct radeon_winsys *radeon;
 
-   radeon = radeon_drm_winsys_create(fd);
-   if (!radeon)
-      return NULL;
-
-   if (!radeon->screen) {
-      radeon->screen = r600_screen_create(radeon);
-      if (!radeon->screen)
-         return NULL;
-
-      radeon->screen = debug_screen_wrap(radeon->screen);
-   }
-
-   return radeon->screen;
+   radeon = radeon_drm_winsys_create(fd, r600_screen_create);
+   return radeon ? debug_screen_wrap(radeon->screen) : NULL;
 }
 
 static const struct drm_conf_ret throttle_ret = {
index c695dde51ed7a9ba224cd8f7f92f6995802eef37..74980af5281502fc20edaa4f2e0bc03cd981c0ec 100644 (file)
@@ -35,19 +35,8 @@ static struct pipe_screen *create_screen(int fd)
 {
    struct radeon_winsys *radeon;
 
-   radeon = radeon_drm_winsys_create(fd);
-   if (!radeon)
-      return NULL;
-
-   if (!radeon->screen) {
-      radeon->screen = radeonsi_screen_create(radeon);
-      if (!radeon->screen)
-         return NULL;
-
-      radeon->screen = debug_screen_wrap(radeon->screen);
-   }
-
-   return radeon->screen;
+   radeon = radeon_drm_winsys_create(fd, radeonsi_screen_create);
+   return radeon ? debug_screen_wrap(radeon->screen) : NULL;
 }
 
 static const struct drm_conf_ret throttle_ret = {
index 4fc62f1a4006b2ffebe0812980ae7c9756149876..dfcaaa4b6efcd0814ba997a79d50b36c89e10f8a 100644 (file)
@@ -4,7 +4,11 @@
 #include "pipe/p_defines.h"
 
 struct radeon_winsys;
+struct pipe_screen;
 
-struct radeon_winsys *radeon_drm_winsys_create(int fd);
+typedef struct pipe_screen *(*radeon_screen_create_t)(struct radeon_winsys *);
+
+struct radeon_winsys *
+radeon_drm_winsys_create(int fd, radeon_screen_create_t screen_create);
 
 #endif
index 07b3c05f2b7012f7471a2198598ae988913f3af7..0eb0c6a07b9f519827b93e8667618033e68cba6c 100644 (file)
@@ -586,7 +586,8 @@ static bool radeon_winsys_unref(struct radeon_winsys *ws)
     return destroy;
 }
 
-PUBLIC struct radeon_winsys *radeon_drm_winsys_create(int fd)
+PUBLIC struct radeon_winsys *
+radeon_drm_winsys_create(int fd, radeon_screen_create_t screen_create)
 {
     struct radeon_drm_winsys *ws;
 
@@ -609,7 +610,6 @@ PUBLIC struct radeon_winsys *radeon_drm_winsys_create(int fd)
     }
 
     ws->fd = fd;
-    util_hash_table_set(fd_tab, intptr_to_pointer(fd), ws);
 
     if (!do_winsys_init(ws))
         goto fail;
@@ -652,6 +652,20 @@ PUBLIC struct radeon_winsys *radeon_drm_winsys_create(int fd)
     if (ws->num_cpus > 1 && debug_get_option_thread())
         ws->thread = pipe_thread_create(radeon_drm_cs_emit_ioctl, ws);
 
+    /* Create the screen at the end. The winsys must be initialized
+     * completely.
+     *
+     * Alternatively, we could create the screen based on "ws->gen"
+     * and link all drivers into one binary blob. */
+    ws->base.screen = screen_create(&ws->base);
+    if (!ws->base.screen) {
+        radeon_winsys_destroy(&ws->base);
+        pipe_mutex_unlock(fd_tab_mutex);
+        return NULL;
+    }
+
+    util_hash_table_set(fd_tab, intptr_to_pointer(fd), ws);
+
     /* We must unlock the mutex once the winsys is fully initialized, so that
      * other threads attempting to create the winsys from the same fd will
      * get a fully initialized winsys and not just half-way initialized. */