From 2737281010345613bf9583a19b18ecd13c1d1f81 Mon Sep 17 00:00:00 2001 From: Jian Jun Chen Date: Mon, 10 Jul 2023 14:20:32 +0800 Subject: [PATCH] dm: virtio: add per queue mutex ACRN virtio devices are using a per device mutex to protect the concurrent operations on the device's PIO/MMIO. This introduces big contention in fast IO hence downgrades the IO performance, for example virtio-blk with asyncio enabled. This patch introduces per queue mutex to relieve such issues. Currently the per queue mutex is only used in the asycio path when iothread is enabled. Tracked-On: #8612 Signed-off-by: Jian Jun Chen Acked-by: Wang, Yu1 --- devicemodel/hw/pci/virtio/virtio.c | 28 +++++++++++++++++++++++----- devicemodel/include/virtio.h | 1 + 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/devicemodel/hw/pci/virtio/virtio.c b/devicemodel/hw/pci/virtio/virtio.c index 67b86522e..0a3bd18d7 100644 --- a/devicemodel/hw/pci/virtio/virtio.c +++ b/devicemodel/hw/pci/virtio/virtio.c @@ -68,11 +68,10 @@ void iothread_handler(void *arg) struct virtio_vq_info *vq = &base->queues[idx]; if (viothrd->iothread_run) { - if (base->mtx) - pthread_mutex_lock(base->mtx); + pthread_mutex_lock(&vq->mtx); + /* only vq specific data can be accessed in qnotify callback */ (*viothrd->iothread_run)(base, vq); - if (base->mtx) - pthread_mutex_unlock(base->mtx); + pthread_mutex_unlock(&vq->mtx); } } @@ -194,13 +193,27 @@ virtio_linkup(struct virtio_base *base, struct virtio_ops *vops, struct virtio_vq_info *queues, int backend_type) { - int i; + int i, rc; + pthread_mutexattr_t attr; /* base and pci_virtio_dev addresses must match */ if ((void *)base != pci_virtio_dev) { pr_err("virtio_base and pci_virtio_dev addresses don't match!\n"); return; } + + rc = pthread_mutexattr_init(&attr); + if (rc) { + pr_err("%s, pthread_mutexattr_init failed\n", __func__); + return; + } + + rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + if (rc) { + pr_err("%s, pthread_mutexattr_settype failed\n", __func__); + return; + } + base->vops = vops; base->dev = dev; dev->arg = base; @@ -210,6 +223,11 @@ virtio_linkup(struct virtio_base *base, struct virtio_ops *vops, for (i = 0; i < vops->nvq; i++) { queues[i].base = base; queues[i].num = i; + rc = pthread_mutex_init(&queues[i].mtx, &attr); + if (rc) { + pr_err("%s, pthread_mutex_init failed\n", __func__); + return; + } } } diff --git a/devicemodel/include/virtio.h b/devicemodel/include/virtio.h index c14ba1f62..718b84e5d 100644 --- a/devicemodel/include/virtio.h +++ b/devicemodel/include/virtio.h @@ -439,6 +439,7 @@ struct virtio_vq_info { struct virtio_base *base; /**< backpointer to virtio_base */ uint16_t num; /**< the num'th queue in the virtio_base */ + pthread_mutex_t mtx; /**< per queue mutex */ uint16_t flags; /**< flags (see above) */ uint16_t last_avail; /**< a recent value of avail->idx */