[dpdk-dev] [PATCH v3 12/12] service: relax barriers with C11 atomic operations

Van Haaren, Harry harry.van.haaren at intel.com
Fri Apr 3 13:58:34 CEST 2020


> From: Phil Yang <phil.yang at arm.com>
> Sent: Tuesday, March 17, 2020 1:18 AM
> To: thomas at monjalon.net; Van Haaren, Harry <harry.van.haaren at intel.com>;
> Ananyev, Konstantin <konstantin.ananyev at intel.com>;
> stephen at networkplumber.org; maxime.coquelin at redhat.com; dev at dpdk.org
> Cc: david.marchand at redhat.com; jerinj at marvell.com; hemant.agrawal at nxp.com;
> Honnappa.Nagarahalli at arm.com; gavin.hu at arm.com; ruifeng.wang at arm.com;
> joyce.kong at arm.com; nd at arm.com
> Subject: [PATCH v3 12/12] service: relax barriers with C11 atomic operations
> 
> To guarantee the inter-threads visibility of the shareable domain, it
> uses a lot of rte_smp_r/wmb in the service library. This patch relaxed
> these barriers for service by using c11 atomic one-way barrier operations.
> 
> Signed-off-by: Phil Yang <phil.yang at arm.com>
> Reviewed-by: Ruifeng Wang <ruifeng.wang at arm.com>
> Reviewed-by: Gavin Hu <gavin.hu at arm.com>
> ---
>  lib/librte_eal/common/rte_service.c | 45 ++++++++++++++++++++----------------
> -
>  1 file changed, 25 insertions(+), 20 deletions(-)
> 
> diff --git a/lib/librte_eal/common/rte_service.c
> b/lib/librte_eal/common/rte_service.c
> index c033224..d31663e 100644
> --- a/lib/librte_eal/common/rte_service.c
> +++ b/lib/librte_eal/common/rte_service.c
> @@ -179,9 +179,11 @@ rte_service_set_stats_enable(uint32_t id, int32_t
> enabled)
>  	SERVICE_VALID_GET_OR_ERR_RET(id, s, 0);
> 
>  	if (enabled)
> -		s->internal_flags |= SERVICE_F_STATS_ENABLED;
> +		__atomic_or_fetch(&s->internal_flags, SERVICE_F_STATS_ENABLED,
> +			__ATOMIC_RELEASE);
>  	else
> -		s->internal_flags &= ~(SERVICE_F_STATS_ENABLED);
> +		__atomic_and_fetch(&s->internal_flags,
> +			~(SERVICE_F_STATS_ENABLED), __ATOMIC_RELEASE);

Not sure why these have to become stores with RELEASE memory ordering?
(More occurances of same Q below, just answer here?)

>  	return 0;
>  }
> @@ -193,9 +195,11 @@ rte_service_set_runstate_mapped_check(uint32_t id,
> int32_t enabled)
>  	SERVICE_VALID_GET_OR_ERR_RET(id, s, 0);
> 
>  	if (enabled)
> -		s->internal_flags |= SERVICE_F_START_CHECK;
> +		__atomic_or_fetch(&s->internal_flags, SERVICE_F_START_CHECK,
> +			__ATOMIC_RELEASE);
>  	else
> -		s->internal_flags &= ~(SERVICE_F_START_CHECK);
> +		__atomic_and_fetch(&s->internal_flags, ~(SERVICE_F_START_CHECK),
> +			__ATOMIC_RELEASE);

Same as above, why do these require RELEASE?


Remainder of patch below seems to make sense - there's a wmb() involved hence RELEASE m/o.

>  	return 0;
>  }
> @@ -264,8 +268,8 @@ rte_service_component_register(const struct
> rte_service_spec *spec,
>  	s->spec = *spec;
>  	s->internal_flags |= SERVICE_F_REGISTERED | SERVICE_F_START_CHECK;
> 
> -	rte_smp_wmb();
> -	rte_service_count++;
> +	/* make sure the counter update after the state change. */
> +	__atomic_add_fetch(&rte_service_count, 1, __ATOMIC_RELEASE);

This makes sense to me - the RELEASE ensures that previous stores to the
s->internal_flags are visible to other cores before rte_service_count
increments atomically.


>  	if (id_ptr)
>  		*id_ptr = free_slot;
> @@ -281,9 +285,10 @@ rte_service_component_unregister(uint32_t id)
>  	SERVICE_VALID_GET_OR_ERR_RET(id, s, -EINVAL);
> 
>  	rte_service_count--;
> -	rte_smp_wmb();
> 
> -	s->internal_flags &= ~(SERVICE_F_REGISTERED);
> +	/* make sure the counter update before the state change. */
> +	__atomic_and_fetch(&s->internal_flags, ~(SERVICE_F_REGISTERED),
> +			   __ATOMIC_RELEASE);
> 
>  	/* clear the run-bit in all cores */
>  	for (i = 0; i < RTE_MAX_LCORE; i++)
> @@ -301,11 +306,12 @@ rte_service_component_runstate_set(uint32_t id, uint32_t
> runstate)
>  	SERVICE_VALID_GET_OR_ERR_RET(id, s, -EINVAL);
> 
>  	if (runstate)
> -		s->comp_runstate = RUNSTATE_RUNNING;
> +		__atomic_store_n(&s->comp_runstate, RUNSTATE_RUNNING,
> +				__ATOMIC_RELEASE);
>  	else
> -		s->comp_runstate = RUNSTATE_STOPPED;
> +		__atomic_store_n(&s->comp_runstate, RUNSTATE_STOPPED,
> +				__ATOMIC_RELEASE);
> 
> -	rte_smp_wmb();
>  	return 0;
>  }
>
> 
> @@ -316,11 +322,12 @@ rte_service_runstate_set(uint32_t id, uint32_t runstate)
>  	SERVICE_VALID_GET_OR_ERR_RET(id, s, -EINVAL);
> 
>  	if (runstate)
> -		s->app_runstate = RUNSTATE_RUNNING;
> +		__atomic_store_n(&s->app_runstate, RUNSTATE_RUNNING,
> +				__ATOMIC_RELEASE);
>  	else
> -		s->app_runstate = RUNSTATE_STOPPED;
> +		__atomic_store_n(&s->app_runstate, RUNSTATE_STOPPED,
> +				__ATOMIC_RELEASE);
> 
> -	rte_smp_wmb();
>  	return 0;
>  }
> 
> @@ -442,7 +449,8 @@ service_runner_func(void *arg)
>  	const int lcore = rte_lcore_id();
>  	struct core_state *cs = &lcore_states[lcore];
> 
> -	while (lcore_states[lcore].runstate == RUNSTATE_RUNNING) {
> +	while (__atomic_load_n(&cs->runstate,
> +		    __ATOMIC_ACQUIRE) == RUNSTATE_RUNNING) {
>  		const uint64_t service_mask = cs->service_mask;
> 
>  		for (i = 0; i < RTE_SERVICE_NUM_MAX; i++) {
> @@ -453,8 +461,6 @@ service_runner_func(void *arg)
>  		}
> 
>  		cs->loops++;
> -
> -		rte_smp_rmb();
>  	}
> 
>  	lcore_config[lcore].state = WAIT;
> @@ -663,9 +669,8 @@ rte_service_lcore_add(uint32_t lcore)
> 
>  	/* ensure that after adding a core the mask and state are defaults */
>  	lcore_states[lcore].service_mask = 0;
> -	lcore_states[lcore].runstate = RUNSTATE_STOPPED;
> -
> -	rte_smp_wmb();
> +	__atomic_store_n(&lcore_states[lcore].runstate, RUNSTATE_STOPPED,
> +			__ATOMIC_RELEASE);
> 
>  	return rte_eal_wait_lcore(lcore);
>  }
> --
> 2.7.4



More information about the dev mailing list