> Date: Mon, 24 Jul 2023 12:05:34 +0900 > From: PHO <p...@cielonegro.org> > > I realized the cause of this: > [...] > There were cases where the function was destroying a condvar that it > didn't initialize! Ugh, this is the very reason why I dislike C...
Oops... Sorry, was blowing through the vmwgfx code a little too hastily there. Here's a patch to simplify it and make it easier to read; might work better.
diff --git a/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_fence.c b/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_fence.c index 970c6ee38235..68a654ddb29a 100644 --- a/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_fence.c +++ b/sys/external/bsd/drm2/dist/drm/vmwgfx/vmwgfx_fence.c @@ -195,87 +195,37 @@ static long vmw_fence_wait(struct dma_fence *f, bool intr, signed long timeout) if (likely(vmw_fence_obj_signaled(fence))) return timeout; + DRM_INIT_WAITQUEUE(&cb.wq, "vmwgfxwf"); + vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC); vmw_seqno_waiter_add(dev_priv); - spin_lock(f->lock); - - if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &f->flags)) - goto out; - - if (intr && signal_pending(current)) { - ret = -ERESTARTSYS; + if (likely(vmw_fence_obj_signaled(fence))) { + ret = timeout; goto out; } -#ifdef __NetBSD__ - DRM_INIT_WAITQUEUE(&cb.wq, "vmwgfxwf"); -#else - cb.task = current; -#endif - spin_unlock(f->lock); ret = dma_fence_add_callback(f, &cb.base, vmwgfx_wait_cb); - spin_lock(f->lock); - if (ret) + if (ret) { + ret = timeout; goto out; + } -#ifdef __NetBSD__ #define C (__vmw_fences_update(fman), dma_fence_is_signaled_locked(f)) + spin_lock(f->lock); if (intr) { DRM_SPIN_TIMED_WAIT_UNTIL(ret, &cb.wq, f->lock, timeout, C); } else { DRM_SPIN_TIMED_WAIT_NOINTR_UNTIL(ret, &cb.wq, f->lock, timeout, C); } -#else - for (;;) { - __vmw_fences_update(fman); - - /* - * We can use the barrier free __set_current_state() since - * DMA_FENCE_FLAG_SIGNALED_BIT + wakeup is protected by the - * fence spinlock. - */ - if (intr) - __set_current_state(TASK_INTERRUPTIBLE); - else - __set_current_state(TASK_UNINTERRUPTIBLE); - - if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &f->flags)) { - if (ret == 0 && timeout > 0) - ret = 1; - break; - } - - if (intr && signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - - if (ret == 0) - break; - - spin_unlock(f->lock); - - ret = schedule_timeout(ret); - - spin_lock(f->lock); - } - __set_current_state(TASK_RUNNING); - if (!list_empty(&cb.base.node)) - list_del(&cb.base.node); -#endif spin_unlock(f->lock); + dma_fence_remove_callback(f, &cb.base); - spin_lock(f->lock); -out: - spin_unlock(f->lock); -#ifdef __NetBSD__ - DRM_DESTROY_WAITQUEUE(&cb.wq); -#endif +out: vmw_seqno_waiter_remove(dev_priv); - vmw_seqno_waiter_remove(dev_priv); + DRM_DESTROY_WAITQUEUE(&cb.wq); return ret; }