diff options
author | Marek Olšák <[email protected]> | 2014-04-08 23:36:53 +0200 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2014-04-10 20:50:17 +0200 |
commit | 7c57b01564b987259ec3ce8ed24266290fa60e75 (patch) | |
tree | 12e9a7753650e96cdf883c46ddbf7d830b13db01 /src/gallium/winsys/radeon | |
parent | b5ebfc33b8d44de9947ace7cbb7fde1625e6c97f (diff) |
winsys/radeon: fix a race condition between 2 calls to radeon_winsys_create
This fixes random crashes of: piglit/glx-multithread-shader-compile.
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_winsys.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c index a2480540c40..ebf7697ac33 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c @@ -46,6 +46,7 @@ #include <unistd.h> static struct util_hash_table *fd_tab = NULL; +pipe_static_mutex(fd_tab_mutex); /* Enable/disable feature access for one command stream. * If enable == TRUE, return TRUE on success. @@ -391,6 +392,12 @@ static void radeon_winsys_destroy(struct radeon_winsys *rws) { struct radeon_drm_winsys *ws = (struct radeon_drm_winsys*)rws; + pipe_mutex_lock(fd_tab_mutex); + if (fd_tab) { + util_hash_table_remove(fd_tab, intptr_to_pointer(ws->fd)); + } + pipe_mutex_unlock(fd_tab_mutex); + if (ws->thread) { ws->kill_thread = 1; pipe_semaphore_signal(&ws->cs_queued); @@ -407,9 +414,6 @@ static void radeon_winsys_destroy(struct radeon_winsys *rws) if (ws->gen >= DRV_R600) { radeon_surface_manager_free(ws->surf_man); } - if (fd_tab) { - util_hash_table_remove(fd_tab, intptr_to_pointer(ws->fd)); - } FREE(rws); } @@ -573,20 +577,24 @@ PUBLIC struct radeon_winsys *radeon_drm_winsys_create(int fd) { struct radeon_drm_winsys *ws; + pipe_mutex_lock(fd_tab_mutex); if (!fd_tab) { fd_tab = util_hash_table_create(hash_fd, compare_fd); } ws = util_hash_table_get(fd_tab, intptr_to_pointer(fd)); if (ws) { + pipe_mutex_unlock(fd_tab_mutex); pipe_reference(NULL, &ws->base.reference); return &ws->base; } ws = CALLOC_STRUCT(radeon_drm_winsys); if (!ws) { + pipe_mutex_unlock(fd_tab_mutex); return NULL; } + ws->fd = fd; util_hash_table_set(fd_tab, intptr_to_pointer(fd), ws); @@ -630,9 +638,15 @@ 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); + /* 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. */ + pipe_mutex_unlock(fd_tab_mutex); + return &ws->base; fail: + pipe_mutex_unlock(fd_tab_mutex); if (ws->cman) ws->cman->destroy(ws->cman); if (ws->kman) |