summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Olšák <maraeo@gmail.com>2010-09-23 14:24:52 +0200
committerMarek Olšák <maraeo@gmail.com>2010-09-24 02:29:05 +0200
commita333485386c66672fc34813c77c1400516c56ee5 (patch)
treebaed973e3ddbf03904c376d68865f6211ed8c31b
parent206d92912cfd1ac73233d9c027fa590b60270cb8 (diff)
r300g: make accessing map_list and buffer_handles thread-safe
NOTE: This is a candidate for the 7.9 branch.
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_buffer.c64
1 files changed, 58 insertions, 6 deletions
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c b/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c
index 075ab5cb32..78723948d4 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,