summaryrefslogtreecommitdiffstats
path: root/src/gallium/winsys
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2010-09-15 03:46:10 +0200
committerMarek Olšák <[email protected]>2010-09-15 04:29:18 +0200
commit0b9eb5c9bb03e5134d9a41786178100109e80c5a (patch)
treec6d7f785f7088811be8db93eb281cddb6547c186 /src/gallium/winsys
parentfd7f70af4897e4e31b11562eb1c473f0ee00fce5 (diff)
r300g: prevent creating multiple winsys BOs for the same handle
This fixes a DRM deadlock in the cubestorm xscreensaver, because somehow there must not be 2 different BOs relocated in one CS if both BOs back the same handle. I was told it is impossible to happen, but apparently it is not, or there is something else wrong.
Diffstat (limited to 'src/gallium/winsys')
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_buffer.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c b/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c
index 19f194b36cb..46e8df76067 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c
@@ -5,6 +5,7 @@
#include "radeon_cs_gem.h"
#include "radeon_buffer.h"
+#include "util/u_hash_table.h"
#include "util/u_inlines.h"
#include "util/u_memory.h"
#include "util/u_simple_list.h"
@@ -41,6 +42,7 @@ struct radeon_drm_bufmgr {
struct pb_manager base;
struct radeon_libdrm_winsys *rws;
struct radeon_drm_buffer buffer_map_list;
+ struct util_hash_table *buffer_handles;
};
static INLINE struct radeon_drm_bufmgr *
@@ -60,6 +62,9 @@ radeon_drm_buffer_destroy(struct pb_buffer *_buf)
radeon_bo_unmap(buf->bo);
buf->bo->ptr = NULL;
}
+
+ util_hash_table_remove(buf->mgr->buffer_handles,
+ (void*)(uintptr_t)buf->bo->handle);
radeon_bo_unref(buf->bo);
FREE(buf);
@@ -186,6 +191,13 @@ struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager
struct radeon_drm_buffer *buf;
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);
+ return b;
+ }
+
bo = radeon_bo_open(rws->bom, handle, 0,
0, 0, 0);
if (bo == NULL)
@@ -208,6 +220,8 @@ struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager
buf->bo = bo;
+ util_hash_table_set(mgr->buffer_handles, (void*)(uintptr_t)handle, buf);
+
return &buf->base;
}
@@ -261,9 +275,20 @@ static void
radeon_drm_bufmgr_destroy(struct pb_manager *_mgr)
{
struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
+ util_hash_table_destroy(mgr->buffer_handles);
FREE(mgr);
}
+static unsigned handle_hash(void *key)
+{
+ return (unsigned)key;
+}
+
+static int handle_compare(void *key1, void *key2)
+{
+ return !((int)key1 == (int)key2);
+}
+
struct pb_manager *
radeon_drm_bufmgr_create(struct radeon_libdrm_winsys *rws)
{
@@ -279,6 +304,7 @@ 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);
return &mgr->base;
}