patches for DPDK stable branches
 help / color / mirror / Atom feed
From: Wathsala Vithanage <wathsala.vithanage@arm.com>
To: Kevin Traynor <ktraynor@redhat.com>
Cc: Ola Liljedahl <ola.liljedahl@arm.com>, dpdk stable <stable@dpdk.org>
Subject: Re: patch 'mcslock: fix memory ordering' has been queued to stable release 24.11.4
Date: Fri, 21 Nov 2025 09:22:55 -0600	[thread overview]
Message-ID: <0556d9f0-e765-4697-8150-8f1eba858cce@arm.com> (raw)
In-Reply-To: <20251121112128.485623-64-ktraynor@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 10253 bytes --]


On 11/21/25 05:20, Kevin Traynor wrote:
> Hi,
>
> FYI, your patch has been queued to stable release 24.11.4

Looks like it applied cleanly, Thanks
-- wathsala

>
> Note it hasn't been pushed tohttp://dpdk.org/browse/dpdk-stable yet.
> It will be pushed if I get no objections before 11/26/25. So please
> shout if anyone has objections.
>
> Also note that after the patch there's a diff of the upstream commit vs the
> patch applied to the branch. This will indicate if there was any rebasing
> needed to apply to the stable branch. If there were code changes for rebasing
> (ie: not only metadata diffs), please double check that the rebase was
> correctly done.
>
> Queued patches are on a temporary branch at:
> https://github.com/kevintraynor/dpdk-stable
>
> This queued commit can be viewed at:
> https://github.com/kevintraynor/dpdk-stable/commit/c9e3afaa776e94a0d8671bc547806fdc1e657269
>
> Thanks.
>
> Kevin
>
> ---
>  From c9e3afaa776e94a0d8671bc547806fdc1e657269 Mon Sep 17 00:00:00 2001
> From: Wathsala Vithanage<wathsala.vithanage@arm.com>
> Date: Tue, 11 Nov 2025 17:38:50 +0000
> Subject: [PATCH] mcslock: fix memory ordering
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> Content-Transfer-Encoding: 8bit
>
> [ upstream commit 8357af1cb3a359810bd56eab78ed104495c8094f ]
>
> Fix incorrect memory ordering in the MCS lock implementation by
> adding proper synchronizing edges to establish clear happens-before
> relationships between threads invoking lock() and unlock(). These
> synchronizing edges prevent potential deadlocks caused by improper
> ordering and are documented in detail through in-code comments.
>
> The previously relaxed load of the successor’s lock object pointer
> in unlock() has been upgraded to a load-acquire operation. This
> change ensures that the successor’s initialization does not
> overwrite the current lock holder’s update to the locked field,
> which could otherwise lead to deadlocks.
>
> Remove two unnecessary fences:
>
> The acquire fence in unlock() had no matching release fence, making
> it ineffective for enforcing memory order. The associated comment
> suggested it prevented speculative reordering, but such fences (data
> memory barriers) only establish memory ordering and do not control
> instruction speculation.
>
> The release-acquire fence pair in lock() was previously justified as
> preventing reordering between the load-acquire loop of me->locked
> and the store-release of prev->next. This is no longer needed, as the
> new synchronizing edges ensure a chain of happens-before
> relationships between memory operations of threads calling lock() and
> unlock().
>
> Fixes: 2173f3333b61d ("mcslock: add MCS queued lock implementation")
>
> Signed-off-by: Wathsala Vithanage<wathsala.vithanage@arm.com>
> Reviewed-by: Ola Liljedahl<ola.liljedahl@arm.com>
> ---
>   lib/eal/include/rte_mcslock.h | 100 ++++++++++++++++++++++------------
>   1 file changed, 64 insertions(+), 36 deletions(-)
>
> diff --git a/lib/eal/include/rte_mcslock.h b/lib/eal/include/rte_mcslock.h
> index bb218d2e50..0af7a94a06 100644
> --- a/lib/eal/include/rte_mcslock.h
> +++ b/lib/eal/include/rte_mcslock.h
> @@ -58,9 +58,19 @@ rte_mcslock_lock(RTE_ATOMIC(rte_mcslock_t *) *msl, rte_mcslock_t *me)
>   	rte_atomic_store_explicit(&me->next, NULL, rte_memory_order_relaxed);
>   
> -	/* If the queue is empty, the exchange operation is enough to acquire
> -	 * the lock. Hence, the exchange operation requires acquire semantics.
> -	 * The store to me->next above should complete before the node is
> -	 * visible to other CPUs/threads. Hence, the exchange operation requires
> -	 * release semantics as well.
> +	/*
> +	 * A0/R0: Queue might be empty, perform the exchange (RMW) with both acquire and
> +	 * release semantics:
> +	 * A0: Acquire — synchronizes with both R0 and R2.
> +	 *     Must synchronize with R0 to ensure that this thread observes predecessor's
> +	 *     initialization of its lock object or risk them overwriting this thread's
> +	 *     update to the next of the same object via store to prev->next.
> +	 *
> +	 *     Must synchronize with R2 the releasing CAS in unlock(), this will ensure
> +	 *     that all prior critical-section writes become visible to this thread.
> +	 *
> +	 * R0: Release — ensures the successor observes our initialization of me->next;
> +	 *     without it, me->next could be overwritten to NULL after the successor
> +	 *     sets its own address, causing deadlock. This release synchronizes with
> +	 *     A0 above.
>   	 */
>   	prev = rte_atomic_exchange_explicit(msl, me, rte_memory_order_acq_rel);
> @@ -71,22 +81,24 @@ rte_mcslock_lock(RTE_ATOMIC(rte_mcslock_t *) *msl, rte_mcslock_t *me)
>   		return;
>   	}
> -	/* The store to me->next above should also complete before the node is
> -	 * visible to predecessor thread releasing the lock. Hence, the store
> -	 * prev->next also requires release semantics. Note that, for example,
> -	 * on ARM, the release semantics in the exchange operation is not
> -	 * strong as a release fence and is not sufficient to enforce the
> -	 * desired order here.
> +
> +	/*
> +	 * R1: With the relaxed memory model of C/C++, it's essential that after
> +	 * we link ourselves by storing prev->next = me, the owner of prev must
> +	 * observe our prior initialization of me->locked. Otherwise it could
> +	 * clear me->locked before we set it to 1, which may deadlock.
> +	 * Perform a releasing store so the predecessor's acquire loads A2 and A3
> +	 * observes our initialization, establishing a happens-before from those
> +	 * writes.
>   	 */
>   	rte_atomic_store_explicit(&prev->next, me, rte_memory_order_release);
>   
> -	/* The while-load of me->locked should not move above the previous
> -	 * store to prev->next. Otherwise it will cause a deadlock. Need a
> -	 * store-load barrier.
> -	 */
> -	rte_atomic_thread_fence(rte_memory_order_acq_rel);
> -	/* If the lock has already been acquired, it first atomically
> +	/*
> +	 * A1: If the lock has already been acquired, it first atomically
>   	 * places the node at the end of the queue and then proceeds
>   	 * to spin on me->locked until the previous lock holder resets
> -	 * the me->locked using mcslock_unlock().
> +	 * the me->locked in rte_mcslock_unlock().
> +	 * This load must synchronize with store-release R3 to ensure that
> +	 * all updates to critical section by previous lock holder is visible
> +	 * to this thread after acquiring the lock.
>   	 */
>   	rte_wait_until_equal_32((uint32_t *)(uintptr_t)&me->locked, 0, rte_memory_order_acquire);
> @@ -104,28 +116,44 @@ static inline void
>   rte_mcslock_unlock(RTE_ATOMIC(rte_mcslock_t *) *msl, RTE_ATOMIC(rte_mcslock_t *) me)
>   {
> -	/* Check if there are more nodes in the queue. */
> -	if (likely(rte_atomic_load_explicit(&me->next, rte_memory_order_relaxed) == NULL)) {
> +	/*
> +	 * A2: Check whether a successor is already queued.
> +	 * Load me->next with acquire semantics so it can synchronize with the
> +	 * successor’s release store R1. This guarantees that the successor’s
> +	 * initialization of its lock object (me) is completed before we observe
> +	 * it here, preventing a race between this thread’s store-release to
> +	 * me->next->locked and the successor’s store to me->locked.
> +	 */
> +	if (likely(rte_atomic_load_explicit(&me->next, rte_memory_order_acquire) == NULL)) {
>   		/* No, last member in the queue. */
> -		rte_mcslock_t *save_me = rte_atomic_load_explicit(&me, rte_memory_order_relaxed);
> +		rte_mcslock_t *save_me = me;
>   
> -		/* Release the lock by setting it to NULL */
> +		/*
> +		 * R2: Try to release the lock by swinging *msl from save_me to NULL.
> +		 * Use release semantics so all critical section writes become
> +		 * visible to the next lock acquirer.
> +		 */
>   		if (likely(rte_atomic_compare_exchange_strong_explicit(msl, &save_me, NULL,
>   				rte_memory_order_release, rte_memory_order_relaxed)))
>   			return;
>   
> -		/* Speculative execution would be allowed to read in the
> -		 * while-loop first. This has the potential to cause a
> -		 * deadlock. Need a load barrier.
> -		 */
> -		rte_atomic_thread_fence(rte_memory_order_acquire);
> -		/* More nodes added to the queue by other CPUs.
> -		 * Wait until the next pointer is set.
> +		/*
> +		 * A3: Another thread was enqueued concurrently, so the CAS and the lock
> +		 * release failed. Wait until the successor sets our 'next' pointer.
> +		 * This load must synchronize with the successor’s release store (R1) to
> +		 * ensure that the successor’s initialization completes before we observe
> +		 * it here. This ordering prevents a race between this thread’s later
> +		 * store-release to me->next->locked and the successor’s store to me->locked.
>   		 */
>   		RTE_ATOMIC(uintptr_t) *next;
>   		next = (__rte_atomic uintptr_t *)&me->next;
> -		RTE_WAIT_UNTIL_MASKED(next, UINTPTR_MAX, !=, 0, rte_memory_order_relaxed);
> +		RTE_WAIT_UNTIL_MASKED(next, UINTPTR_MAX, !=, 0, rte_memory_order_acquire);
>   	}
>   
> -	/* Pass lock to next waiter. */
> +	/*
> +	 * R3: Pass the lock to the successor.
> +	 * Use a release store to synchronize with A1 when clearing me->next->locked
> +	 * so the successor observes our critical section writes after it sees locked
> +	 * become 0.
> +	 */
>   	rte_atomic_store_explicit(&me->next->locked, 0, rte_memory_order_release);
>   }
> @@ -150,9 +178,9 @@ rte_mcslock_trylock(RTE_ATOMIC(rte_mcslock_t *) *msl, rte_mcslock_t *me)
>   	rte_mcslock_t *expected = NULL;
>   
> -	/* The lock can be taken only when the queue is empty. Hence,
> -	 * the compare-exchange operation requires acquire semantics.
> -	 * The store to me->next above should complete before the node
> -	 * is visible to other CPUs/threads. Hence, the compare-exchange
> -	 * operation requires release semantics as well.
> +	/*
> +	 * A4/R4: The lock can be acquired only when the queue is empty.
> +	 * The compare-and-exchange operation must use acquire and release
> +	 * semantics for the same reasons described in the rte_mcslock_lock()
> +	 * function’s empty-queue case (see A0/R0 for details).
>   	 */
>   	return rte_atomic_compare_exchange_strong_explicit(msl, &expected, me,

[-- Attachment #2: Type: text/html, Size: 11107 bytes --]

  reply	other threads:[~2025-11-21 15:22 UTC|newest]

Thread overview: 100+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-21 11:19 patch 'test/hash: check memory allocation' " Kevin Traynor
2025-11-21 11:19 ` patch 'dmadev: fix debug build with tracepoints' " Kevin Traynor
2025-11-21 11:19 ` patch 'bus/cdx: fix device name in probing error message' " Kevin Traynor
2025-11-21 11:19 ` patch 'bus/cdx: fix release in probing for secondary process' " Kevin Traynor
2025-11-21 11:19 ` patch 'buildtools/pmdinfogen: fix warning with python 3.14' " Kevin Traynor
2025-11-21 11:19 ` patch 'net/iavf: fix build with clang 21' " Kevin Traynor
2025-11-21 11:19 ` patch 'test: " Kevin Traynor
2025-11-21 11:19 ` patch 'app/eventdev: " Kevin Traynor
2025-11-21 11:19 ` patch 'eventdev/crypto: " Kevin Traynor
2025-11-21 11:19 ` patch 'rawdev: " Kevin Traynor
2025-11-21 11:19 ` patch 'vdpa/mlx5: remove unused constant' " Kevin Traynor
2025-11-21 11:19 ` patch 'crypto/mlx5: remove unused constants' " Kevin Traynor
2025-11-21 11:19 ` patch 'regex/mlx5: remove useless " Kevin Traynor
2025-11-21 11:19 ` patch 'common/mlx5: " Kevin Traynor
2025-11-21 11:19 ` patch 'net/mlx5: " Kevin Traynor
2025-11-21 11:20 ` patch 'net/mlx5: remove unused macros' " Kevin Traynor
2025-11-21 11:20 ` patch 'doc: fix NVIDIA bifurcated driver presentation link' " Kevin Traynor
2025-11-21 11:20 ` patch 'app/dma-perf: fix use after free' " Kevin Traynor
2025-11-21 11:20 ` patch 'app/dma-perf: check buffer size' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/vmxnet3: disable RSS for single queue for ESX8.0+' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/dpaa: fix resource leak' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/txgbe: fix checksum error counter' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/ngbe: " Kevin Traynor
2025-11-21 11:20 ` patch 'net/txgbe: reduce memory size of ring descriptors' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/ngbe: " Kevin Traynor
2025-11-21 11:20 ` patch 'net/txgbe: fix VF Rx buffer size in config register' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/txgbe: remove duplicate Tx queue assignment' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/txgbe: add device arguments for FDIR' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/txgbe: fix maximum number of FDIR filters' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/txgbe: fix FDIR mode clearing' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/txgbe: fix FDIR drop action for L4 match packets' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/txgbe: fix FDIR filter for SCTP tunnel' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/txgbe: filter FDIR match flex bytes for " Kevin Traynor
2025-11-21 11:20 ` patch 'net/txgbe: fix FDIR rule raw relative for L3 packets' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/txgbe: fix FDIR input mask' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/txgbe: switch to FDIR when ntuple filter is full' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/txgbe: remove unsupported flow action mark' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/nfp: fix metering cleanup' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/bonding: fix MAC address propagation in 802.3ad mode' " Kevin Traynor
2025-11-21 11:20 ` patch 'app/testpmd: fix DCB Tx port' " Kevin Traynor
2025-11-21 11:20 ` patch 'app/testpmd: fix DCB Rx queues' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/e1000/base: fix crash on init with GCC 13' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/fm10k: fix build with GCC 16' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/mlx4: fix unnecessary comma' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/mlx5: fix unnecessary commas' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/mlx5: store MTU at Rx queue allocation time' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/mlx5: fix indirect RSS action hash' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/mlx5: remove counter alignment' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/mlx5: fix external queues access' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/mlx5: fix modify field action restriction' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/mlx5: fix meter mark allocation' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/mlx5: fix indirect meter index leak' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/mlx5: fix error reporting on masked indirect actions' " Kevin Traynor
2025-11-21 11:20 ` patch 'vhost: fix external buffer in VDUSE' " Kevin Traynor
2025-11-21 11:20 ` patch 'net: fix L2 length for GRE packets' " Kevin Traynor
2025-11-21 11:20 ` patch 'graph: fix xstats description allocation' " Kevin Traynor
2025-11-21 11:20 ` patch 'graph: fix updating edge with active graph' " Kevin Traynor
2025-11-21 11:20 ` patch 'app/pdump: remove hard-coded memory channels' " Kevin Traynor
2025-11-21 11:20 ` patch 'pdump: handle primary process exit' " Kevin Traynor
2025-11-21 11:20 ` patch 'telemetry: make socket handler typedef private' " Kevin Traynor
2025-11-21 11:20 ` patch 'usertools/telemetry: fix exporter default IP binding' " Kevin Traynor
2025-11-21 11:20 ` patch 'examples/l3fwd-power: fix telemetry command registration' " Kevin Traynor
2025-11-21 11:20 ` patch 'lib: fix backticks matching in Doxygen comments' " Kevin Traynor
2025-11-21 11:20 ` patch 'mcslock: fix memory ordering' " Kevin Traynor
2025-11-21 15:22   ` Wathsala Vithanage [this message]
2025-11-21 11:20 ` patch 'net/axgbe: fix build with GCC 16' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/dpaa2: fix duplicate call of close' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/dpaa2: clear active VDQ state when freeing Rx queues' " Kevin Traynor
2025-11-21 11:20 ` patch 'app/testpmd: fix flex item link parsing' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/ixgbe/base: fix PF link state request size' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/ice: fix path selection for QinQ Tx offload' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/ice: fix statistics' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/idpf: fix queue setup with TSO offload' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/iavf: fix check for PF Rx timestamp support' " Kevin Traynor
2025-11-21 11:20 ` patch 'net/iavf: fix Rx timestamp validity check' " Kevin Traynor
2025-11-21 23:41   ` Jacob Keller
2025-11-21 11:20 ` patch 'common/cnxk: fix max number of SQB buffers in clean up' " Kevin Traynor
2025-11-21 11:21 ` patch 'common/cnxk: fix null SQ access' " Kevin Traynor
2025-11-21 11:21 ` patch 'common/cnxk: fix format specifier for bandwidth profile ID' " Kevin Traynor
2025-11-21 11:21 ` patch 'common/cnxk: fix NIX Rx inject enabling' " Kevin Traynor
2025-11-21 11:21 ` patch 'net/cnxk: fix Rx inject LF' " Kevin Traynor
2025-11-21 11:21 ` patch 'net/cnxk: fix default meter pre-color' " Kevin Traynor
2025-11-21 11:21 ` patch 'crypto/qat: fix CCM request descriptor hash state size' " Kevin Traynor
2025-11-21 11:21 ` patch 'net/dpaa2: remove ethdev pointer from bus device' " Kevin Traynor
2025-11-21 11:21 ` patch 'app/flow-perf: fix rules array length' " Kevin Traynor
2025-11-21 11:21 ` patch 'net/mlx5: fix spurious CPU wakeups' " Kevin Traynor
2025-11-21 11:21 ` patch 'net/mlx5: fix IPv6 DSCP offset in HWS sync API' " Kevin Traynor
2025-11-21 11:21 ` patch 'net/mlx5: fix send to kernel action resources release' " Kevin Traynor
2025-11-21 11:21 ` patch 'net/mlx5: release representor interrupt handler' " Kevin Traynor
2025-11-21 11:21 ` patch 'common/mlx5: release unused mempool entries' " Kevin Traynor
2025-11-21 11:21 ` patch 'net/mlx5/hws: fix buddy memory allocation' " Kevin Traynor
2025-11-21 11:21 ` patch 'net/mlx5: fix uninitialized variable' " Kevin Traynor
2025-11-21 11:21 ` patch 'net/mlx5: fix flow tag indexes support on root table' " Kevin Traynor
2025-11-21 11:21 ` patch 'net/mlx5/hws: fix flow rule hash capability' " Kevin Traynor
2025-11-21 11:21 ` patch 'net/mlx5: fix null dereference in modify header' " Kevin Traynor
2025-11-21 11:21 ` patch 'net/mlx5: skip Rx control flow tables in isolated mode' " Kevin Traynor
2025-11-21 11:21 ` patch 'net/mlx5: fix crash on flow rule destruction' " Kevin Traynor
2025-11-21 11:21 ` patch 'net/mlx5: move auxiliary data inline' " Kevin Traynor
2025-11-21 11:21 ` patch 'net/mlx5/windows: fix match criteria in flow creation' " Kevin Traynor
2025-11-21 11:21 ` patch 'net: fix IPv6 link local compliance with RFC 4291' " Kevin Traynor

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=0556d9f0-e765-4697-8150-8f1eba858cce@arm.com \
    --to=wathsala.vithanage@arm.com \
    --cc=ktraynor@redhat.com \
    --cc=ola.liljedahl@arm.com \
    --cc=stable@dpdk.org \
    /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).