From patchwork Tue Jul 7 15:54:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phil Yang X-Patchwork-Id: 73458 X-Patchwork-Delegate: jerinj@marvell.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 20827A00BE; Tue, 7 Jul 2020 17:55:32 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 76D2A1DEB8; Tue, 7 Jul 2020 17:55:25 +0200 (CEST) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by dpdk.org (Postfix) with ESMTP id F22A11DEB3; Tue, 7 Jul 2020 17:55:23 +0200 (CEST) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 72041D6E; Tue, 7 Jul 2020 08:55:23 -0700 (PDT) Received: from phil-VirtualBox.arm.com (A010647.Arm.com [10.170.226.105]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 2CBFB3F68F; Tue, 7 Jul 2020 08:55:18 -0700 (PDT) From: Phil Yang To: jerinj@marvell.com, dev@dpdk.org Cc: thomas@monjalon.net, erik.g.carrillo@intel.com, Honnappa.Nagarahalli@arm.com, drc@linux.vnet.ibm.com, Ruifeng.Wang@arm.com, Dharmik.Thakkar@arm.com, nd@arm.com, david.marchand@redhat.com, mdr@ashroe.eu, nhorman@tuxdriver.com, dodji@redhat.com, stable@dpdk.org Date: Tue, 7 Jul 2020 23:54:51 +0800 Message-Id: <1594137293-22468-2-git-send-email-phil.yang@arm.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1594137293-22468-1-git-send-email-phil.yang@arm.com> References: <1594120403-17643-1-git-send-email-phil.yang@arm.com> <1594137293-22468-1-git-send-email-phil.yang@arm.com> Subject: [dpdk-dev] [PATCH v4 2/4] eventdev: use C11 atomics for lcore timer armed flag X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The in_use flag is a per core variable which is not shared between lcores in the normal case and the access of this variable should be ordered on the same core. However, if non-EAL thread pick the highest lcore to insert timers into, there is the possibility of conflicts on this flag between threads. Then the atomic compare-and-swap operation is needed. Use the C11 atomics instead of the generic rte_atomic operations to avoid the unnecessary barrier on aarch64. Cc: stable@dpdk.org Signed-off-by: Phil Yang Reviewed-by: Dharmik Thakkar Reviewed-by: Ruifeng Wang Acked-by: Erik Gabriel Carrillo --- v4: 1.Change 'CAS' to 'compare-and-swap' to pass the coding style check. 2.Cc to stable release. (Honnappa) v2: 1. Make the code comments more accurate. (Erik) 2. Define the in_use flag as an unsigned type. (Stephen) lib/librte_eventdev/rte_event_timer_adapter.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/librte_eventdev/rte_event_timer_adapter.c b/lib/librte_eventdev/rte_event_timer_adapter.c index 370ea40..4ed3013 100644 --- a/lib/librte_eventdev/rte_event_timer_adapter.c +++ b/lib/librte_eventdev/rte_event_timer_adapter.c @@ -554,7 +554,7 @@ struct swtim { uint32_t timer_data_id; /* Track which cores have actually armed a timer */ struct { - rte_atomic16_t v; + uint16_t v; } __rte_cache_aligned in_use[RTE_MAX_LCORE]; /* Track which cores' timer lists should be polled */ unsigned int poll_lcores[RTE_MAX_LCORE]; @@ -606,7 +606,8 @@ swtim_callback(struct rte_timer *tim) "with immediate expiry value"); } - if (unlikely(rte_atomic16_test_and_set(&sw->in_use[lcore].v))) { + if (unlikely(sw->in_use[lcore].v == 0)) { + sw->in_use[lcore].v = 1; n_lcores = __atomic_fetch_add(&sw->n_poll_lcores, 1, __ATOMIC_RELAXED); __atomic_store_n(&sw->poll_lcores[n_lcores], lcore, @@ -834,7 +835,7 @@ swtim_init(struct rte_event_timer_adapter *adapter) /* Initialize the variables that track in-use timer lists */ for (i = 0; i < RTE_MAX_LCORE; i++) - rte_atomic16_init(&sw->in_use[i].v); + sw->in_use[i].v = 0; /* Initialize the timer subsystem and allocate timer data instance */ ret = rte_timer_subsystem_init(); @@ -1017,6 +1018,8 @@ __swtim_arm_burst(const struct rte_event_timer_adapter *adapter, struct rte_timer *tim, *tims[nb_evtims]; uint64_t cycles; int n_lcores; + /* Timer list for this lcore is not in use. */ + uint16_t exp_state = 0; #ifdef RTE_LIBRTE_EVENTDEV_DEBUG /* Check that the service is running. */ @@ -1035,8 +1038,12 @@ __swtim_arm_burst(const struct rte_event_timer_adapter *adapter, /* If this is the first time we're arming an event timer on this lcore, * mark this lcore as "in use"; this will cause the service * function to process the timer list that corresponds to this lcore. + * The atomic compare-and-swap operation can prevent the race condition + * on in_use flag between multiple non-EAL threads. */ - if (unlikely(rte_atomic16_test_and_set(&sw->in_use[lcore_id].v))) { + if (unlikely(__atomic_compare_exchange_n(&sw->in_use[lcore_id].v, + &exp_state, 1, 0, + __ATOMIC_RELAXED, __ATOMIC_RELAXED))) { EVTIM_LOG_DBG("Adding lcore id = %u to list of lcores to poll", lcore_id); n_lcores = __atomic_fetch_add(&sw->n_poll_lcores, 1,