From: Marek Olšák Date: Thu, 23 Sep 2010 12:24:52 +0000 (+0200) Subject: r300g: make accessing map_list and buffer_handles thread-safe X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a333485386c66672fc34813c77c1400516c56ee5;p=mesa.git r300g: make accessing map_list and buffer_handles thread-safe NOTE: This is a candidate for the 7.9 branch. --- diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c b/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c index 075ab5cb324..78723948d41 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c @@ -11,8 +11,10 @@ #include "util/u_simple_list.h" #include "pipebuffer/pb_buffer.h" #include "pipebuffer/pb_bufmgr.h" +#include "os/os_thread.h" #include "radeon_winsys.h" + struct radeon_drm_bufmgr; struct radeon_drm_buffer { @@ -39,10 +41,19 @@ radeon_drm_buffer(struct pb_buffer *buf) } struct radeon_drm_bufmgr { + /* Base class. */ struct pb_manager base; + + /* Winsys. */ struct radeon_libdrm_winsys *rws; + + /* List of mapped buffers and its mutex. */ struct radeon_drm_buffer buffer_map_list; + pipe_mutex buffer_map_list_mutex; + + /* List of buffer handles and its mutex. */ struct util_hash_table *buffer_handles; + pipe_mutex buffer_handles_mutex; }; static INLINE struct radeon_drm_bufmgr * @@ -59,14 +70,21 @@ radeon_drm_buffer_destroy(struct pb_buffer *_buf) int name; if (buf->bo->ptr != NULL) { - remove_from_list(buf); - radeon_bo_unmap(buf->bo); - buf->bo->ptr = NULL; + pipe_mutex_lock(buf->mgr->buffer_map_list_mutex); + /* Now test it again inside the mutex. */ + if (buf->bo->ptr != NULL) { + remove_from_list(buf); + radeon_bo_unmap(buf->bo); + buf->bo->ptr = NULL; + } + pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex); } name = radeon_gem_name_bo(buf->bo); if (name) { + pipe_mutex_lock(buf->mgr->buffer_handles_mutex); util_hash_table_remove(buf->mgr->buffer_handles, (void*)(uintptr_t)name); + pipe_mutex_unlock(buf->mgr->buffer_handles_mutex); } radeon_bo_unref(buf->bo); @@ -119,7 +137,13 @@ radeon_drm_buffer_map_internal(struct pb_buffer *_buf, } if (buf->bo->ptr != NULL) { - remove_from_list(buf); + pipe_mutex_lock(buf->mgr->buffer_map_list_mutex); + /* Now test ptr again inside the mutex. We might have gotten a race + * during the first test. */ + if (buf->bo->ptr != NULL) { + remove_from_list(buf); + } + pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex); return buf->bo->ptr; } @@ -145,7 +169,9 @@ radeon_drm_buffer_map_internal(struct pb_buffer *_buf, return NULL; } + pipe_mutex_lock(buf->mgr->buffer_map_list_mutex); remove_from_list(buf); + pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex); return buf->bo->ptr; } @@ -153,9 +179,11 @@ static void radeon_drm_buffer_unmap_internal(struct pb_buffer *_buf) { struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf); + pipe_mutex_lock(buf->mgr->buffer_map_list_mutex); if (is_empty_list(buf)) { /* = is not inserted... */ insert_at_tail(&buf->mgr->buffer_map_list, buf); } + pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex); } static void @@ -192,8 +220,9 @@ const struct pb_vtbl radeon_drm_buffer_vtbl = { radeon_drm_buffer_get_base_buffer, }; -struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr, - uint32_t handle) +static struct pb_buffer * +radeon_drm_bufmgr_create_buffer_from_handle_unsafe(struct pb_manager *_mgr, + uint32_t handle) { struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); struct radeon_libdrm_winsys *rws = mgr->rws; @@ -201,6 +230,7 @@ struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager struct radeon_bo *bo; buf = util_hash_table_get(mgr->buffer_handles, (void*)(uintptr_t)handle); + if (buf) { struct pb_buffer *b = NULL; pb_reference(&b, &buf->base); @@ -234,6 +264,20 @@ struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager return &buf->base; } +struct pb_buffer * +radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr, + uint32_t handle) +{ + struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); + struct pb_buffer *pb; + + pipe_mutex_lock(mgr->buffer_handles_mutex); + pb = radeon_drm_bufmgr_create_buffer_from_handle_unsafe(_mgr, handle); + pipe_mutex_unlock(mgr->buffer_handles_mutex); + + return pb; +} + static struct pb_buffer * radeon_drm_bufmgr_create_buffer(struct pb_manager *_mgr, pb_size size, @@ -285,6 +329,8 @@ radeon_drm_bufmgr_destroy(struct pb_manager *_mgr) { struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); util_hash_table_destroy(mgr->buffer_handles); + pipe_mutex_destroy(mgr->buffer_map_list_mutex); + pipe_mutex_destroy(mgr->buffer_handles_mutex); FREE(mgr); } @@ -314,6 +360,8 @@ radeon_drm_bufmgr_create(struct radeon_libdrm_winsys *rws) mgr->rws = rws; make_empty_list(&mgr->buffer_map_list); mgr->buffer_handles = util_hash_table_create(handle_hash, handle_compare); + pipe_mutex_init(mgr->buffer_map_list_mutex); + pipe_mutex_init(mgr->buffer_handles_mutex); return &mgr->base; } @@ -489,6 +537,8 @@ void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr) struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); struct radeon_drm_buffer *rpb, *t_rpb; + pipe_mutex_lock(mgr->buffer_map_list_mutex); + foreach_s(rpb, t_rpb, &mgr->buffer_map_list) { radeon_bo_unmap(rpb->bo); rpb->bo->ptr = NULL; @@ -496,6 +546,8 @@ void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr) } make_empty_list(&mgr->buffer_map_list); + + pipe_mutex_unlock(mgr->buffer_map_list_mutex); } void radeon_drm_bufmgr_wait(struct r300_winsys_screen *ws,