On 15 October 2015 at 10:45, Petri Savolainen <[email protected]> wrote:
> Added 32 bit acquire load/cas and release store/add/sub calls. > You only have cas_acquire. Don't you see a need for cas_release? I use that in one lockless design. I see the beginning of a combinatorial explosion here. Why not just expose the atomic operations that take the memory ordering as a parameter? -- Ola > These are the minimum set of non-relaxed calls that are needed > for building lock-free algorithms. 64 bit versions can be added > later. > > Signed-off-by: Petri Savolainen <[email protected]> > --- > include/odp/api/atomic.h | 80 > ++++++++++++++++++++++++++++- > platform/linux-generic/include/odp/atomic.h | 32 ++++++++++++ > 2 files changed, 111 insertions(+), 1 deletion(-) > > diff --git a/include/odp/api/atomic.h b/include/odp/api/atomic.h > index 957d304..cbf241d 100644 > --- a/include/odp/api/atomic.h > +++ b/include/odp/api/atomic.h > @@ -21,7 +21,7 @@ extern "C" { > /** > * @defgroup odp_atomic ODP ATOMIC > * @details > - * <b> Atomic integers </b> > + * <b> Atomic integers using relaxed memory ordering </b> > * > * Atomic integer types (odp_atomic_u32_t and odp_atomic_u64_t) can be > used to > * implement e.g. shared counters. If not otherwise documented, > operations in > @@ -31,6 +31,18 @@ extern "C" { > * before or after the operation), only atomicity of the operation itself > is > * guaranteed. > * > + * <b> Operations with other than relaxed memory ordering </b> > + * > + * <b> An operation with RELEASE </b> memory ordering > (odp_atomic_xxx_rls_xxx()) > + * ensures that other threads loading the same atomic variable with > ACQUIRE > + * memory ordering see all stores (from the calling thread) that happened > before > + * this releasing store. > + * > + * <b> An operation with ACQUIRE </b> memory ordering > (odp_atomic_xxx_acq_xxx()) > + * ensures that the calling thread sees all stores (done by the releasing > + * thread) that happened before a RELEASE memory ordered store to the same > + * atomic variable. > + * > * @{ > */ > > @@ -265,6 +277,72 @@ void odp_atomic_dec_u64(odp_atomic_u64_t *atom); > int odp_atomic_cas_u64(odp_atomic_u64_t *atom, uint64_t *old_val, > uint64_t new_val); > > +/* > + * Operations with other than relaxed memory ordering > + * -------------------------------------------------- > + */ > + > +/** > + * Load value of atomic uint32 variable using ACQUIRE memory ordering > + * > + * Otherwise identical to odp_atomic_load_u32() but ensures ACQUIRE memory > + * ordering. > + * > + * @param atom Pointer to atomic variable > + * > + * @return Value of the variable > + */ > +uint32_t odp_atomic_load_acq_u32(odp_atomic_u32_t *atom); > + > +/** > + * Compare and swap atomic uint32 variable using ACQUIRE memory ordering > + * > + * Otherwise identical to odp_atomic_cas_u32() but ensures ACQUIRE memory > + * ordering. > + * > + * @param atom Pointer to atomic variable > + * @param[in,out] old_val Pointer to the old value of the atomic > variable. > + * Operation updates this value on failure. > + * @param new_val New value to be written into the atomic > variable > + * > + * @return 0 on failure, !0 on success > + */ > +int odp_atomic_cas_acq_u32(odp_atomic_u32_t *atom, uint32_t *old_val, > + uint32_t new_val); > + > +/** > + * Store value to atomic uint32 variable using RELEASE memory ordering > + * > + * Otherwise identical to odp_atomic_store_u32() but ensures RELEASE > memory > + * ordering. > + * > + * @param atom Pointer to atomic variable > + * @param val Value to store in the variable > + */ > +void odp_atomic_store_rls_u32(odp_atomic_u32_t *atom, uint32_t val); > + > +/** > + * Add to atomic uint32 variable using RELEASE memory ordering > + * > + * Otherwise identical to odp_atomic_add_u32() but ensures RELEASE memory > + * ordering. > + * > + * @param atom Pointer to atomic variable > + * @param val Value to be added to the variable > + */ > +void odp_atomic_add_rls_u32(odp_atomic_u32_t *atom, uint32_t val); > + > +/** > + * Subtract from atomic uint32 variable using RELEASE memory ordering > + * > + * Otherwise identical to odp_atomic_sub_u32() but ensures RELEASE memory > + * ordering. > + * > + * @param atom Pointer to atomic variable > + * @param val Value to be subtracted from the variable > + */ > +void odp_atomic_sub_rls_u32(odp_atomic_u32_t *atom, uint32_t val); > + > /** > * @} > */ > diff --git a/platform/linux-generic/include/odp/atomic.h > b/platform/linux-generic/include/odp/atomic.h > index 5a143a5..8f83c04 100644 > --- a/platform/linux-generic/include/odp/atomic.h > +++ b/platform/linux-generic/include/odp/atomic.h > @@ -204,6 +204,38 @@ static inline int odp_atomic_cas_u64(odp_atomic_u64_t > *atom, uint64_t *old_val, > __ATOMIC_RELAXED); > } > > +static inline uint32_t odp_atomic_load_acq_u32(odp_atomic_u32_t *atom) > +{ > + return __atomic_load_n(&atom->v, __ATOMIC_ACQUIRE); > +} > + > +static inline int odp_atomic_cas_acq_u32(odp_atomic_u32_t *atom, > + uint32_t *old_val, uint32_t > new_val) > +{ > + return __atomic_compare_exchange_n(&atom->v, old_val, new_val, > + 0 /* strong */, > + __ATOMIC_ACQUIRE, > + __ATOMIC_RELAXED); > +} > + > +static inline void odp_atomic_store_rls_u32(odp_atomic_u32_t *atom, > + uint32_t val) > +{ > + __atomic_store_n(&atom->v, val, __ATOMIC_RELEASE); > +} > + > +static inline void odp_atomic_add_rls_u32(odp_atomic_u32_t *atom, > + uint32_t val) > +{ > + (void)__atomic_fetch_add(&atom->v, val, __ATOMIC_RELEASE); > +} > + > +static inline void odp_atomic_sub_rls_u32(odp_atomic_u32_t *atom, > + uint32_t val) > +{ > + (void)__atomic_fetch_sub(&atom->v, val, __ATOMIC_RELEASE); > +} > + > /** > * @} > */ > -- > 2.6.0 > > _______________________________________________ > lng-odp mailing list > [email protected] > https://lists.linaro.org/mailman/listinfo/lng-odp >
_______________________________________________ lng-odp mailing list [email protected] https://lists.linaro.org/mailman/listinfo/lng-odp
