radeonsi: prevent a deadlock in util_queue_add_job with too many GL contexts
authorMarek Olšák <marek.olsak@amd.com>
Mon, 10 Jul 2017 19:59:43 +0000 (21:59 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Mon, 17 Jul 2017 14:57:25 +0000 (10:57 -0400)
If the queue is full, util_queue_add_job will wait while bo_fence_lock is
held.

It pb_slab wants to reuse a buffer, it will lock the pb_slab mutex and
try to check BO fence busyness, but it has to wait for bo_fence_lock to get
released. Both bo_fence_lock and pb_slab mutex are locked now.

When the CS thread unreferences and releases a suballocated buffer,
it will try to lock the pb_slab mutex and has to wait. The CS thread
can't finish its job in order to free a queue slot and unblock
util_queue_add_job ==> deadlock.

Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c

index 30f4dfb769d7b9f780cb3561ca261daf3152fe6c..837c1e2aae01de23ffba43111bccccf3629783c2 100644 (file)
@@ -316,7 +316,8 @@ amdgpu_winsys_create(int fd, unsigned flags,
    (void) mtx_init(&ws->global_bo_list_lock, mtx_plain);
    (void) mtx_init(&ws->bo_fence_lock, mtx_plain);
 
-   if (!util_queue_init(&ws->cs_queue, "amdgpu_cs", 8, 1, 0)) {
+   if (!util_queue_init(&ws->cs_queue, "amdgpu_cs", 8, 1,
+                        UTIL_QUEUE_INIT_RESIZE_IF_FULL)) {
       amdgpu_winsys_destroy(&ws->base);
       mtx_unlock(&dev_tab_mutex);
       return NULL;