#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 {
}
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 *
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);
}
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;
}
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;
}
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
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;
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 &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,
{
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);
}
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;
}
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;
}
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,