summaryrefslogtreecommitdiffstats
path: root/src/gallium/winsys/radeon
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2014-04-09 01:07:52 +0200
committerMarek Olšák <[email protected]>2014-04-10 20:50:17 +0200
commit3b0b44f7def0acb4f7a7aef086c0bece321418a6 (patch)
treeb156e7e948909c0a31d127d30099da60cb178b5d /src/gallium/winsys/radeon
parentac330d4130cb005c75972da2a701b674413456ba (diff)
winsys/radeon: fix a race condition in initialization of radeon_winsys::screen
Create the screen in the winsys while the mutex is locked. This also results in a nice code cleanup! Reviewed-by: Michel Dänzer <[email protected]> Reviewed-by: Christian König <[email protected]>
Diffstat (limited to 'src/gallium/winsys/radeon')
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_public.h6
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_winsys.c18
2 files changed, 21 insertions, 3 deletions
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_public.h b/src/gallium/winsys/radeon/drm/radeon_drm_public.h
index 4fc62f1a400..dfcaaa4b6ef 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_public.h
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_public.h
@@ -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
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
index 07b3c05f2b7..0eb0c6a07b9 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
@@ -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. */