Mesa (main): venus: print warnings when stuck in busy waits

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Jul 28 23:03:16 UTC 2021


Module: Mesa
Branch: main
Commit: a94192f69d1d9388ad2e27ccbdc92dccc660ee6a
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=a94192f69d1d9388ad2e27ccbdc92dccc660ee6a

Author: Chia-I Wu <olvaffe at gmail.com>
Date:   Wed Jul 28 11:13:38 2021 -0700

venus: print warnings when stuck in busy waits

The first warning is printed after stuck in vn_relax for at least about
3.5s.  The actual time can be much longer depending on the
kernel/load/hw.

Signed-off-by: Chia-I Wu <olvaffe at gmail.com>
Reviewed-by: Yiwei Zhang <zzyiwei at chromium.org>
Reviewed-by: Ryan Neph <ryanneph at google.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12115>

---

 src/virtio/vulkan/vn_common.c | 13 ++++++++++++-
 src/virtio/vulkan/vn_common.h |  2 +-
 src/virtio/vulkan/vn_device.c |  2 +-
 src/virtio/vulkan/vn_queue.c  |  2 +-
 src/virtio/vulkan/vn_ring.c   |  4 ++--
 5 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/src/virtio/vulkan/vn_common.c b/src/virtio/vulkan/vn_common.c
index 91ba2f6e9c2..e728a7971d2 100644
--- a/src/virtio/vulkan/vn_common.c
+++ b/src/virtio/vulkan/vn_common.c
@@ -62,10 +62,15 @@ vn_log_result(struct vn_instance *instance,
 }
 
 void
-vn_relax(uint32_t *iter)
+vn_relax(uint32_t *iter, const char *reason)
 {
+   /* Yield for the first 2^busy_wait_order times and then sleep for
+    * base_sleep_us microseconds for the same number of times.  After that,
+    * keep doubling both sleep length and count.
+    */
    const uint32_t busy_wait_order = 4;
    const uint32_t base_sleep_us = 10;
+   const uint32_t warn_order = 12;
 
    (*iter)++;
    if (*iter < (1 << busy_wait_order)) {
@@ -73,6 +78,12 @@ vn_relax(uint32_t *iter)
       return;
    }
 
+   /* warn occasionally if we have slept at least 1.28ms for 2048 times (plus
+    * another 2047 shorter sleeps)
+    */
+   if (unlikely(*iter % (1 << warn_order) == 0))
+      vn_log(NULL, "stuck in %s wait with iter at %d", reason, *iter);
+
    const uint32_t shift = util_last_bit(*iter) - busy_wait_order - 1;
    os_time_sleep(base_sleep_us << shift);
 }
diff --git a/src/virtio/vulkan/vn_common.h b/src/virtio/vulkan/vn_common.h
index 80780efccc2..0a357f3c6bf 100644
--- a/src/virtio/vulkan/vn_common.h
+++ b/src/virtio/vulkan/vn_common.h
@@ -133,7 +133,7 @@ vn_log_result(struct vn_instance *instance,
               const char *where);
 
 void
-vn_relax(uint32_t *iter);
+vn_relax(uint32_t *iter, const char *reason);
 
 static_assert(sizeof(vn_object_id) >= sizeof(uintptr_t), "");
 
diff --git a/src/virtio/vulkan/vn_device.c b/src/virtio/vulkan/vn_device.c
index bb9f1fc8039..d20a6c6ba04 100644
--- a/src/virtio/vulkan/vn_device.c
+++ b/src/virtio/vulkan/vn_device.c
@@ -303,7 +303,7 @@ vn_instance_wait_roundtrip(struct vn_instance *instance,
       const uint32_t cur = atomic_load_explicit(ptr, memory_order_acquire);
       if (cur >= roundtrip_seqno || roundtrip_seqno - cur >= INT32_MAX)
          break;
-      vn_relax(&iter);
+      vn_relax(&iter, "roundtrip");
    } while (true);
 }
 
diff --git a/src/virtio/vulkan/vn_queue.c b/src/virtio/vulkan/vn_queue.c
index 21aea4d0df4..26ccc9be09c 100644
--- a/src/virtio/vulkan/vn_queue.c
+++ b/src/virtio/vulkan/vn_queue.c
@@ -613,7 +613,7 @@ vn_update_sync_result(VkResult result, int64_t abs_timeout, uint32_t *iter)
           os_time_get_nano() >= abs_timeout)
          result = VK_TIMEOUT;
       else
-         vn_relax(iter);
+         vn_relax(iter, "client");
       break;
    default:
       assert(result == VK_SUCCESS || result < 0);
diff --git a/src/virtio/vulkan/vn_ring.c b/src/virtio/vulkan/vn_ring.c
index 2448836fad9..29a2884776e 100644
--- a/src/virtio/vulkan/vn_ring.c
+++ b/src/virtio/vulkan/vn_ring.c
@@ -100,7 +100,7 @@ vn_ring_wait_seqno(const struct vn_ring *ring, uint32_t seqno)
       const uint32_t head = vn_ring_load_head(ring);
       if (vn_ring_ge_seqno(ring, head, seqno))
          return head;
-      vn_relax(&iter);
+      vn_relax(&iter, "ring seqno");
    } while (true);
 }
 
@@ -115,7 +115,7 @@ vn_ring_wait_space(const struct vn_ring *ring, uint32_t size)
       const uint32_t head = vn_ring_load_head(ring);
       if (ring->cur + size - head <= VN_RING_BUFFER_SIZE)
          return head;
-      vn_relax(&iter);
+      vn_relax(&iter, "ring space");
    } while (true);
 }
 



More information about the mesa-commit mailing list