Convert allow_queuing, while_queuing, started, and dev_attached from
rte_atomic32_t to RTE_ATOMIC(uint32_t) and replace rte_atomic32_*()
with rte_atomic_*_explicit().

The data-path / control-thread handshake on allow_queuing and
while_queuing is a Dekker-style mutual-visibility pattern: each side
stores its own flag and then loads the peer's. Both legs must be
seq_cst to forbid store-load reordering; anything weaker permits both
sides to miss each other. The previous rte_atomic32_set/read compiled
to plain volatile stores/loads and provided no such ordering, so this
also closes a latent ordering hole on weakly-ordered ISAs.

The data-path exit store of while_queuing=0 is release, ordering
preceding slot accesses before the control thread observes the data
path as idle.

Signed-off-by: Stephen Hemminger <[email protected]>
---
 drivers/net/vhost/rte_eth_vhost.c | 62 ++++++++++++++++++++-----------
 1 file changed, 40 insertions(+), 22 deletions(-)

diff --git a/drivers/net/vhost/rte_eth_vhost.c 
b/drivers/net/vhost/rte_eth_vhost.c
index 2e3a007966..2acf670c94 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -73,8 +73,8 @@ struct vhost_stats {
 
 struct vhost_queue {
        int vid;
-       rte_atomic32_t allow_queuing;
-       rte_atomic32_t while_queuing;
+       RTE_ATOMIC(uint32_t) allow_queuing;
+       RTE_ATOMIC(uint32_t) while_queuing;
        struct pmd_internal *internal;
        struct rte_mempool *mb_pool;
        uint16_t port;
@@ -406,12 +406,19 @@ eth_vhost_rx(void *q, struct rte_mbuf **bufs, uint16_t 
nb_bufs)
        uint16_t i, nb_rx = 0;
        uint16_t nb_receive = nb_bufs;
 
-       if (unlikely(rte_atomic32_read(&r->allow_queuing) == 0))
+       /* Fast-path early exit; racy load is fine here -- if we miss a
+        * transition we get caught by the seq_cst check below.
+        */
+       if (unlikely(rte_atomic_load_explicit(&r->allow_queuing, 
rte_memory_order_relaxed) == 0))
                return 0;
 
-       rte_atomic32_set(&r->while_queuing, 1);
-
-       if (unlikely(rte_atomic32_read(&r->allow_queuing) == 0))
+       /* Announce presence, then re-check. The store and the following
+        * load MUST both be seq_cst so they are totally ordered with the
+        * control thread's store-to-allow_queuing / load-of-while_queuing
+        * pair. Anything weaker permits both sides to miss each other.
+        */
+       rte_atomic_store_explicit(&r->while_queuing, 1, 
rte_memory_order_seq_cst);
+       if (unlikely(rte_atomic_load_explicit(&r->allow_queuing, 
rte_memory_order_seq_cst) == 0))
                goto out;
 
        /* Dequeue packets from guest TX queue */
@@ -446,7 +453,7 @@ eth_vhost_rx(void *q, struct rte_mbuf **bufs, uint16_t 
nb_bufs)
        }
 
 out:
-       rte_atomic32_set(&r->while_queuing, 0);
+       rte_atomic_store_explicit(&r->while_queuing, 0, 
rte_memory_order_release);
 
        return nb_rx;
 }
@@ -460,12 +467,19 @@ eth_vhost_tx(void *q, struct rte_mbuf **bufs, uint16_t 
nb_bufs)
        uint64_t nb_bytes = 0;
        uint64_t nb_missed = 0;
 
-       if (unlikely(rte_atomic32_read(&r->allow_queuing) == 0))
+       /* Fast-path early exit; racy load is fine here -- if we miss a
+        * transition we get caught by the seq_cst check below.
+        */
+       if (unlikely(rte_atomic_load_explicit(&r->allow_queuing, 
rte_memory_order_relaxed) == 0))
                return 0;
 
-       rte_atomic32_set(&r->while_queuing, 1);
-
-       if (unlikely(rte_atomic32_read(&r->allow_queuing) == 0))
+       /* Announce presence, then re-check. The store and the following
+        * load MUST both be seq_cst so they are totally ordered with the
+        * control thread's store-to-allow_queuing / load-of-while_queuing
+        * pair. Anything weaker permits both sides to miss each other.
+        */
+       rte_atomic_store_explicit(&r->while_queuing, 1, 
rte_memory_order_seq_cst);
+       if (unlikely(rte_atomic_load_explicit(&r->allow_queuing, 
rte_memory_order_seq_cst) == 0))
                goto out;
 
        for (i = 0; i < nb_bufs; i++) {
@@ -515,7 +529,7 @@ eth_vhost_tx(void *q, struct rte_mbuf **bufs, uint16_t 
nb_bufs)
        for (i = 0; likely(i < nb_tx); i++)
                rte_pktmbuf_free(bufs[i]);
 out:
-       rte_atomic32_set(&r->while_queuing, 0);
+       rte_atomic_store_explicit(&r->while_queuing, 0, 
rte_memory_order_release);
 
        return nb_tx;
 }
@@ -771,11 +785,13 @@ update_queuing_status(struct rte_eth_dev *dev, bool 
wait_queuing)
                vq = dev->data->rx_queues[i];
                if (vq == NULL)
                        continue;
-               if (allow_queuing && state->cur[vq->virtqueue_id])
-                       rte_atomic32_set(&vq->allow_queuing, 1);
-               else
-                       rte_atomic32_set(&vq->allow_queuing, 0);
-               while (wait_queuing && rte_atomic32_read(&vq->while_queuing))
+
+               rte_atomic_store_explicit(&vq->allow_queuing,
+                                         (allow_queuing && 
state->cur[vq->virtqueue_id]),
+                                         rte_memory_order_seq_cst);
+
+               while (wait_queuing &&
+                      rte_atomic_load_explicit(&vq->while_queuing, 
rte_memory_order_seq_cst))
                        rte_pause();
        }
 
@@ -783,11 +799,13 @@ update_queuing_status(struct rte_eth_dev *dev, bool 
wait_queuing)
                vq = dev->data->tx_queues[i];
                if (vq == NULL)
                        continue;
-               if (allow_queuing && state->cur[vq->virtqueue_id])
-                       rte_atomic32_set(&vq->allow_queuing, 1);
-               else
-                       rte_atomic32_set(&vq->allow_queuing, 0);
-               while (wait_queuing && rte_atomic32_read(&vq->while_queuing))
+
+               rte_atomic_store_explicit(&vq->allow_queuing,
+                                         (allow_queuing && 
state->cur[vq->virtqueue_id]),
+                                         rte_memory_order_seq_cst);
+
+               while (wait_queuing &&
+                      rte_atomic_load_explicit(&vq->while_queuing, 
rte_memory_order_seq_cst))
                        rte_pause();
        }
 }
-- 
2.53.0

Reply via email to