On 10.02.2017 19:06, Joe Savage wrote:
> Add an example application implementing lock-free IPv4 fragmentation
> and reassembly functionality using ODP's packet "concat" and "split".
> 
> Signed-off-by: Joe Savage <joe.sav...@arm.com>
> Reviewed-and-tested-by: Bill Fischofer <bill.fischo...@linaro.org>
> ---
> (This code contribution is provided under the terms of agreement 
> LES-LTM-21309)
> 

> diff --git a/example/ipfragreass/odp_ipfragreass_atomics.h 
> b/example/ipfragreass/odp_ipfragreass_atomics.h
> new file mode 100644
> index 0000000..bebe3d3
> --- /dev/null
> +++ b/example/ipfragreass/odp_ipfragreass_atomics.h
> @@ -0,0 +1,130 @@
> +/* Copyright (c) 2017, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +#ifndef ODP_FRAGREASS_PP_ATOMICS_H_
> +#define ODP_FRAGREASS_PP_ATOMICS_H_
> +
> +#include <example_debug.h>
> +
> +#if defined(__arm__) || defined(__aarch64__)
> +#if defined(__aarch64__)
> +static inline __int128 lld(__int128 *var, int mo);
> +static inline uint32_t scd(__int128 *var, __int128 neu, int mo);

Is there any reason to have prototypes, then main function, then lld/scd
implementation? What about moving lld/scd upwards, so that there would
be no extra prototypes?

> +static inline bool arm_atomic_strong_compare_exchange_16(__int128 *var,
> +                                                      __int128 *exp,
> +                                                      __int128 neu,
> +                                                      int mo_success,
> +                                                      int mo_failure
> +                                                      EXAMPLE_UNUSED)
> +{
> +     register __int128 old;
> +     register __int128 expected = *exp;
> +     int ll_mo, sc_mo;
> +
> +     ll_mo = (mo_success != __ATOMIC_RELAXED &&
> +              mo_success != __ATOMIC_RELEASE) ? __ATOMIC_ACQUIRE
> +                                              : __ATOMIC_RELAXED;
> +     sc_mo = (mo_success == __ATOMIC_RELEASE ||
> +              mo_success == __ATOMIC_ACQ_REL ||
> +              mo_success == __ATOMIC_SEQ_CST) ? __ATOMIC_RELEASE
> +                                              : __ATOMIC_RELAXED;
> +
> +     /*
> +      * To prevent spurious failures and ensure atomicity, we must write some
> +      * value back -- whether it's the value we wanted to write, or the value
> +      * that is currently there. Repeat until we perform a successful write.
> +      */
> +     do {
> +             old = lld(var, ll_mo);
> +     } while (scd(var, old == expected ? neu : old, sc_mo));
> +
> +     *exp = old;
> +     return (old == expected);
> +}
> +
> +static inline __int128 lld(__int128 *var, int mo)
> +{
> +     __int128 old;
> +
> +     if (mo == __ATOMIC_ACQUIRE)
> +             __asm__ volatile("ldaxp %0, %H0, [%1]" : "=&r" (old)
> +                              : "r" (var) : "memory");
> +     else /* mo == __ATOMIC_RELAXED */
> +             __asm__ volatile("ldxp %0, %H0, [%1]" : "=&r" (old)
> +                              : "r" (var) : );
> +     return old;
> +}
> +
> +static inline uint32_t scd(__int128 *var, __int128 neu, int mo)
> +{
> +     uint32_t ret;
> +
> +     if (mo == __ATOMIC_RELEASE)
> +             __asm__ volatile("stlxp %w0, %1, %H1, [%2]" : "=&r" (ret)
> +                              : "r" (neu), "r" (var) : "memory");
> +     else /* mo == __ATOMIC_RELAXED */
> +             __asm__ volatile("stxp %w0, %1, %H1, [%2]" : "=&r" (ret)
> +                              : "r" (neu), "r" (var) : );
> +     return ret;
> +}

-- 
With best wishes
Dmitry

Reply via email to