summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>2017-02-04 23:26:50 +0100
committerBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>2017-03-29 08:50:48 +0200
commitb20af5c8d7e607de781ed22694e67e514a133294 (patch)
tree61d0a310e0def36e3cec29935e48c6c2c6fe30d4
parente527e62e759547577d3afcb1ea5fafcb8530db4c (diff)
radv/amdgpu: Use reference counting for bos.
Per the Vulkan spec, memory objects may be deleted before the buffers and images using them are deleted, although those resources then cannot be used except for deletion themselves. For the virtual buffers, we need to access them on resource destruction to unmap the regions, so this results in a use-after-free. Implement reference counting to avoid this. Signed-off-by: Bas Nieuwenhuizen <basni@google.com> Reviewed-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c10
-rw-r--r--src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.h1
2 files changed, 11 insertions, 0 deletions
diff --git a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c
index 8e78ef75233..7b679450cbc 100644
--- a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c
+++ b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c
@@ -34,6 +34,11 @@
#include <amdgpu_drm.h>
#include <inttypes.h>
+#include "util/u_atomic.h"
+
+
+static void radv_amdgpu_winsys_bo_destroy(struct radeon_winsys_bo *_bo);
+
static void
radv_amdgpu_winsys_virtual_map(struct radv_amdgpu_winsys_bo *bo,
const struct radv_amdgpu_map_range *range)
@@ -43,6 +48,7 @@ radv_amdgpu_winsys_virtual_map(struct radv_amdgpu_winsys_bo *bo,
if (!range->bo)
return; /* TODO: PRT mapping */
+ p_atomic_inc(&range->bo->ref_count);
int r = amdgpu_bo_va_op(range->bo->bo, range->bo_offset, range->size,
range->offset + bo->va, 0, AMDGPU_VA_OP_MAP);
if (r)
@@ -62,6 +68,7 @@ radv_amdgpu_winsys_virtual_unmap(struct radv_amdgpu_winsys_bo *bo,
range->offset + bo->va, 0, AMDGPU_VA_OP_UNMAP);
if (r)
abort();
+ radv_amdgpu_winsys_bo_destroy((struct radeon_winsys_bo *)range->bo);
}
static void
@@ -212,6 +219,8 @@ static void radv_amdgpu_winsys_bo_destroy(struct radeon_winsys_bo *_bo)
{
struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo);
+ if (p_atomic_dec_return(&bo->ref_count))
+ return;
if (bo->is_virtual) {
for (uint32_t i = 0; i < bo->range_count; ++i) {
radv_amdgpu_winsys_virtual_unmap(bo, bo->ranges + i);
@@ -273,6 +282,7 @@ radv_amdgpu_winsys_bo_create(struct radeon_winsys *_ws,
bo->size = size;
bo->ws = ws;
bo->is_virtual = !!(flags & RADEON_FLAG_VIRTUAL);
+ bo->ref_count = 1;
if (flags & RADEON_FLAG_VIRTUAL) {
bo->ranges = realloc(NULL, sizeof(struct radv_amdgpu_map_range));
diff --git a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.h b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.h
index c7d484bc8dd..4512e76b333 100644
--- a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.h
+++ b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.h
@@ -45,6 +45,7 @@ struct radv_amdgpu_winsys_bo {
uint64_t size;
struct radv_amdgpu_winsys *ws;
bool is_virtual;
+ int ref_count;
union {
/* physical bo */