From: Wathsala Vithanage <wathsala.vithanage@arm.com>
To: Honnappa Nagarahalli <honnappa.nagarahalli@arm.com>,
Konstantin Ananyev <konstantin.ananyev@huawei.com>
Cc: dev@dpdk.org, Wathsala Vithanage <wathsala.vithanage@arm.com>,
Ola Liljedahl <ola.liljedahl@arm.com>,
Dhruv Tripathi <dhruv.tripathi@arm.com>
Subject: [PATCH 1/1] ring: safe partial ordering for head/tail update
Date: Mon, 15 Sep 2025 18:54:50 +0000 [thread overview]
Message-ID: <20250915185451.533039-2-wathsala.vithanage@arm.com> (raw)
In-Reply-To: <20250915185451.533039-1-wathsala.vithanage@arm.com>
The function __rte_ring_headtail_move_head() assumes that the barrier
(fence) between the load of the head and the load-acquire of the
opposing tail guarantees the following: if a first thread reads tail
and then writes head and a second thread reads the new value of head
and then reads tail, then it should observe the same (or a later)
value of tail.
This assumption is incorrect under the C11 memory model. If the barrier
(fence) is intended to establish a total ordering of ring operations,
it fails to do so. Instead, the current implementation only enforces a
partial ordering, which can lead to unsafe interleavings. In particular,
some partial orders can cause underflows in free slot or available
element computations, potentially resulting in data corruption.
The issue manifests when a CPU first acts as a producer and later as a
consumer. In this scenario, the barrier assumption may fail when another
core takes the consumer role. A Herd7 litmus test in C11 can demonstrate
this violation. The problem has not been widely observed so far because:
(a) on strong memory models (e.g., x86-64) the assumption holds, and
(b) on relaxed models with RCsc semantics the ordering is still strong
enough to prevent hazards.
The problem becomes visible only on weaker models, when load-acquire is
implemented with RCpc semantics (e.g. some AArch64 CPUs which support
the LDAPR and LDAPUR instructions).
Three possible solutions exist:
1. Strengthen ordering by upgrading release/acquire semantics to
sequential consistency. This requires using seq-cst for stores,
loads, and CAS operations. However, this approach introduces a
significant performance penalty on relaxed-memory architectures.
2. Establish a safe partial order by enforcing a pair-wise
happens-before relationship between thread of same role by changing
the CAS and the preceding load of the head by converting them to
release and acquire respectively. This approach makes the original
barrier assumption unnecessary and allows its removal.
3. Retain partial ordering but ensure only safe partial orders are
committed. This can be done by detecting underflow conditions
(producer < consumer) and quashing the update in such cases.
This approach makes the original barrier assumption unnecessary
and allows its removal.
This patch implements solution (3) for performance reasons.
Signed-off-by: Wathsala Vithanage <wathsala.vithanage@arm.com>
Signed-off-by: Ola Liljedahl <ola.liljedahl@arm.com>
Reviewed-by: Honnappa Nagarahalli <honnappa.nagarahalli@arm.com>
Reviewed-by: Dhruv Tripathi <dhruv.tripathi@arm.com>
---
lib/ring/rte_ring_c11_pvt.h | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/lib/ring/rte_ring_c11_pvt.h b/lib/ring/rte_ring_c11_pvt.h
index b9388af0da..e5ac1f6b9e 100644
--- a/lib/ring/rte_ring_c11_pvt.h
+++ b/lib/ring/rte_ring_c11_pvt.h
@@ -83,9 +83,6 @@ __rte_ring_headtail_move_head(struct rte_ring_headtail *d,
/* Reset n to the initial burst count */
n = max;
- /* Ensure the head is read before tail */
- rte_atomic_thread_fence(rte_memory_order_acquire);
-
/* load-acquire synchronize with store-release of ht->tail
* in update_tail.
*/
@@ -99,6 +96,13 @@ __rte_ring_headtail_move_head(struct rte_ring_headtail *d,
*/
*entries = (capacity + stail - *old_head);
+ /*
+ * Ensure the entries calculation was not based on a stale
+ * and unsafe stail observation that causes underflow.
+ */
+ if ((int)*entries < 0)
+ *entries = 0;
+
/* check that we have enough room in ring */
if (unlikely(n > *entries))
n = (behavior == RTE_RING_QUEUE_FIXED) ?
--
2.43.0
next prev parent reply other threads:[~2025-09-15 18:56 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-15 18:54 [PATCH 0/1] ring: correct ordering issue in " Wathsala Vithanage
2025-09-15 18:54 ` Wathsala Vithanage [this message]
2025-09-16 15:42 ` [PATCH 1/1] ring: safe partial ordering for " Bruce Richardson
2025-09-16 18:19 ` Ola Liljedahl
2025-09-17 7:47 ` Bruce Richardson
2025-09-16 22:57 ` Konstantin Ananyev
2025-09-16 23:08 ` Konstantin Ananyev
[not found] ` <2a611c3cf926d752a54b7655c27d6df874a2d0de.camel@arm.com>
2025-09-17 7:58 ` Konstantin Ananyev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250915185451.533039-2-wathsala.vithanage@arm.com \
--to=wathsala.vithanage@arm.com \
--cc=dev@dpdk.org \
--cc=dhruv.tripathi@arm.com \
--cc=honnappa.nagarahalli@arm.com \
--cc=konstantin.ananyev@huawei.com \
--cc=ola.liljedahl@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).