When vq->inuse reaches vq->vring.num, instead of calling die(), yield
and retry. This is a temporary hack to avoid crashes when multiple
worker threads try to pop from an exhausted virtqueue.
The proper fix will involve coordination between worker threads to
prevent this condition entirely, but this keeps the system running for
now during multithreading development.
Signed-off-by: Laurent Vivier
---
virtio.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/virtio.c b/virtio.c
index d7016cc3d580..21bdcb3c9a4d 100644
--- a/virtio.c
+++ b/virtio.c
@@ -77,6 +77,7 @@
#include
#include
#include
+#include
#include
#include
@@ -531,6 +532,7 @@ int vu_queue_pop(const struct vu_dev *dev, struct vu_virtq *vq,
unsigned int head;
int ret;
+again:
if (!vq->vring.avail)
return -1;
@@ -542,8 +544,10 @@ int vu_queue_pop(const struct vu_dev *dev, struct vu_virtq *vq,
*/
smp_rmb();
- if (vq->inuse >= vq->vring.num)
- die("vhost-user queue size exceeded");
+ if (vq->inuse >= vq->vring.num) {
+ sched_yield();
+ goto again;
+ }
virtqueue_get_head(vq, vq->last_avail_idx++, &head);
--
2.54.0