Calling rte_vhost_enqueue_burst() simultaneously from different threads
for the same queue_id requires additional SMP memory barrier to avoid
reordering of used->idx and last_used_idx updates.

In case of virtio_dev_rx() memory barrier rte_mb() simply moved one
instruction higher.

Signed-off-by: Ilya Maximets <i.maximets at samsung.com>
---
 lib/librte_vhost/vhost_rxtx.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/lib/librte_vhost/vhost_rxtx.c b/lib/librte_vhost/vhost_rxtx.c
index a8e2582..4d37aa3 100644
--- a/lib/librte_vhost/vhost_rxtx.c
+++ b/lib/librte_vhost/vhost_rxtx.c
@@ -323,13 +323,16 @@ virtio_dev_rx(struct virtio_net *dev, uint16_t queue_id,
                rte_pause();

        *(volatile uint16_t *)&vq->used->idx += count;
-       vq->last_used_idx = res_end_idx;
        vhost_log_used_vring(dev, vq,
                offsetof(struct vring_used, idx),
                sizeof(vq->used->idx));

-       /* flush used->idx update before we read avail->flags. */
+       /*
+        * Flush used->idx update to make it visible to virtio and all other
+        * threads before allowing to modify it.
+        */
        rte_mb();
+       vq->last_used_idx = res_end_idx;

        /* Kick the guest if necessary. */
        if (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT))
@@ -645,19 +648,24 @@ virtio_dev_merge_rx(struct virtio_net *dev, uint16_t 
queue_id,
                        rte_pause();

                *(volatile uint16_t *)&vq->used->idx += entry_success;
+               /*
+                * Flush used->idx update to make it visible to all
+                * other threads before allowing to modify it.
+                */
+               rte_smp_wmb();
+
                vq->last_used_idx = res_cur_idx;
        }

 merge_rx_exit:
        if (likely(pkt_idx)) {
-               /* flush used->idx update before we read avail->flags. */
+               /* Flush used->idx update to make it visible to virtio. */
                rte_mb();

                /* Kick the guest if necessary. */
                if (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT))
                        eventfd_write(vq->callfd, (eventfd_t)1);
        }
-
        return pkt_idx;
 }

-- 
2.5.0

Reply via email to