diff options
author | Marek Olšák <[email protected]> | 2010-09-15 03:46:10 +0200 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2010-09-15 04:29:18 +0200 |
commit | 0b9eb5c9bb03e5134d9a41786178100109e80c5a (patch) | |
tree | c6d7f785f7088811be8db93eb281cddb6547c186 /src/gallium/winsys | |
parent | fd7f70af4897e4e31b11562eb1c473f0ee00fce5 (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.c | 26 |
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; } |