[PATCH vkd3d 5/7] libs/vkd3d: Make GPU VA allocator thread-safe.

Józef Kucia joseph.kucia at gmail.com
Mon Jan 15 06:49:05 CST 2018


From: Józef Kucia <jkucia at codeweavers.com>

Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---

Required by the test introduced in the next commit.

---
 libs/vkd3d/device.c        | 66 +++++++++++++++++++++++++++++++++++++++-------
 libs/vkd3d/vkd3d_private.h |  4 +--
 2 files changed, 59 insertions(+), 11 deletions(-)

diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index b7adb8ed797c..0750662890e5 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -920,19 +920,31 @@ static void d3d12_device_init_pipeline_cache(struct d3d12_device *device)
     }
 }
 
-/* FIXME: Allocator should be thread-safe. */
 D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate(struct vkd3d_gpu_va_allocator *allocator,
         size_t size, void *ptr)
 {
     D3D12_GPU_VIRTUAL_ADDRESS ceiling = ~(D3D12_GPU_VIRTUAL_ADDRESS)0;
     struct vkd3d_gpu_va_allocation *allocation;
+    int rc;
+
+    if ((rc = pthread_mutex_lock(&allocator->mutex)))
+    {
+        ERR("Failed to lock mutex, error %d.\n", rc);
+        return 0;
+    }
 
     if (!vkd3d_array_reserve((void **)&allocator->allocations, &allocator->allocations_size,
             allocator->allocation_count + 1, sizeof(*allocator->allocations)))
+    {
+        pthread_mutex_unlock(&allocator->mutex);
         return 0;
+    }
 
     if (size > ceiling || ceiling - size < allocator->floor)
+    {
+        pthread_mutex_unlock(&allocator->mutex);
         return 0;
+    }
 
     allocation = &allocator->allocations[allocator->allocation_count++];
     allocation->base = allocator->floor;
@@ -941,6 +953,8 @@ D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate(struct vkd3d_gpu_va_al
 
     allocator->floor += size;
 
+    pthread_mutex_unlock(&allocator->mutex);
+
     return allocation->base;
 }
 
@@ -959,35 +973,69 @@ static int vkd3d_gpu_va_allocation_compare(const void *k, const void *e)
 void *vkd3d_gpu_va_allocator_dereference(struct vkd3d_gpu_va_allocator *allocator, D3D12_GPU_VIRTUAL_ADDRESS address)
 {
     struct vkd3d_gpu_va_allocation *allocation;
+    int rc;
 
-    if (!(allocation = bsearch(&address, allocator->allocations, allocator->allocation_count,
-            sizeof(*allocation), vkd3d_gpu_va_allocation_compare)))
+    if ((rc = pthread_mutex_lock(&allocator->mutex)))
+    {
+        ERR("Failed to lock mutex, error %d.\n", rc);
         return NULL;
+    }
+
+    allocation = bsearch(&address, allocator->allocations, allocator->allocation_count,
+            sizeof(*allocation), vkd3d_gpu_va_allocation_compare);
+
+    pthread_mutex_unlock(&allocator->mutex);
 
-    return allocation->ptr;
+    return allocation ? allocation->ptr : NULL;
 }
 
 void vkd3d_gpu_va_allocator_free(struct vkd3d_gpu_va_allocator *allocator, D3D12_GPU_VIRTUAL_ADDRESS address)
 {
     struct vkd3d_gpu_va_allocation *allocation;
+    int rc;
 
-    if (!(allocation = bsearch(&address, allocator->allocations, allocator->allocation_count,
-            sizeof(*allocation), vkd3d_gpu_va_allocation_compare)))
+    if ((rc = pthread_mutex_lock(&allocator->mutex)))
+    {
+        ERR("Failed to lock mutex, error %d.\n", rc);
         return;
+    }
 
-    if (allocation->base == address)
+    allocation = bsearch(&address, allocator->allocations, allocator->allocation_count,
+            sizeof(*allocation), vkd3d_gpu_va_allocation_compare);
+    if (allocation && allocation->base == address)
         allocation->ptr = NULL;
+
+    pthread_mutex_unlock(&allocator->mutex);
 }
 
-void vkd3d_gpu_va_allocator_init(struct vkd3d_gpu_va_allocator *allocator)
+static bool vkd3d_gpu_va_allocator_init(struct vkd3d_gpu_va_allocator *allocator)
 {
+    int rc;
+
     memset(allocator, 0, sizeof(*allocator));
     allocator->floor = 0x1000;
+
+    if ((rc = pthread_mutex_init(&allocator->mutex, NULL)))
+    {
+        ERR("Failed to initialize mutex, error %d.\n", rc);
+        return false;
+    }
+
+    return true;
 }
 
-void vkd3d_gpu_va_allocator_cleanup(struct vkd3d_gpu_va_allocator *allocator)
+static void vkd3d_gpu_va_allocator_cleanup(struct vkd3d_gpu_va_allocator *allocator)
 {
+    int rc;
+
+    if ((rc = pthread_mutex_lock(&allocator->mutex)))
+    {
+        ERR("Failed to lock mutex, error %d.\n", rc);
+        return;
+    }
     vkd3d_free(allocator->allocations);
+    pthread_mutex_unlock(&allocator->mutex);
+    pthread_mutex_destroy(&allocator->mutex);
 }
 
 /* ID3D12Device */
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 1b0924f3b312..de5ed8e8576a 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -122,6 +122,8 @@ HRESULT vkd3d_fence_worker_stop(struct vkd3d_fence_worker *worker,
 
 struct vkd3d_gpu_va_allocator
 {
+    pthread_mutex_t mutex;
+
     D3D12_GPU_VIRTUAL_ADDRESS floor;
 
     struct vkd3d_gpu_va_allocation
@@ -136,12 +138,10 @@ struct vkd3d_gpu_va_allocator
 
 D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate(struct vkd3d_gpu_va_allocator *allocator,
         size_t size, void *ptr) DECLSPEC_HIDDEN;
-void vkd3d_gpu_va_allocator_cleanup(struct vkd3d_gpu_va_allocator *allocator) DECLSPEC_HIDDEN;
 void *vkd3d_gpu_va_allocator_dereference(struct vkd3d_gpu_va_allocator *allocator,
         D3D12_GPU_VIRTUAL_ADDRESS address) DECLSPEC_HIDDEN;
 void vkd3d_gpu_va_allocator_free(struct vkd3d_gpu_va_allocator *allocator,
         D3D12_GPU_VIRTUAL_ADDRESS address) DECLSPEC_HIDDEN;
-void vkd3d_gpu_va_allocator_init(struct vkd3d_gpu_va_allocator *allocator) DECLSPEC_HIDDEN;
 
 /* ID3D12Fence */
 struct d3d12_fence
-- 
2.13.6




More information about the wine-devel mailing list