On 01/11/2015 07:50 PM, Bill Fischofer wrote:
> Improve lockless buffer allocation by using offsets to extend tag length to
> avoid ABA issues. This also resolves Bug 1051.
> 
> Signed-off-by: Bill Fischofer <[email protected]>
> ---
>  .../include/odp_buffer_pool_internal.h             | 89 
> ++++++++++++++--------
>  platform/linux-generic/odp_buffer_pool.c           |  7 +-
>  2 files changed, 59 insertions(+), 37 deletions(-)
> 
> diff --git a/platform/linux-generic/include/odp_buffer_pool_internal.h 
> b/platform/linux-generic/include/odp_buffer_pool_internal.h
> index 2e48ac3..169e02d 100644
> --- a/platform/linux-generic/include/odp_buffer_pool_internal.h
> +++ b/platform/linux-generic/include/odp_buffer_pool_internal.h
> @@ -107,8 +107,8 @@ struct pool_entry_s {
>       size_t                  pool_size;
>       uint32_t                buf_align;
>       uint32_t                buf_stride;
> -     _odp_atomic_ptr_t       buf_freelist;
> -     _odp_atomic_ptr_t       blk_freelist;
> +     odp_atomic_u64_t        buf_freelist;
> +     odp_atomic_u64_t        blk_freelist;
>       odp_atomic_u32_t        bufcount;
>       odp_atomic_u32_t        blkcount;
>       odp_atomic_u64_t        bufallocs;
> @@ -142,57 +142,77 @@ extern void *pool_entry_ptr[];
>  #define pool_is_secure(pool) 0
>  #endif
>  
> -#define TAG_ALIGN ((size_t)16)
> +#define OFFSET_BITS ODP_BITSIZE((uint64_t)ODP_BUFFER_MAX_BUFFERS * \
> +                             (uint32_t)ODP_CONFIG_PACKET_BUF_LEN_MAX)

It seems with a current odp_config.h settings OFFSET_BITS will be ~41
bits. On 32-bit machine it is too much. I've made calculation manually,
so I can be wrong.

> +
> +#define MAX_OFFSET (1ULL << BUF_OFFSET_BITS)
> +#define TAG_BITS (64 - OFFSET_BITS)
> +#define TAG_ALIGN (1ULL << TAG_BITS)
> +
> +#define NULL_OFFSET (~0ULL)
> +#define NULL_DETAGGED_OFFSET ((~0ULL) >> TAG_BITS)
>  
>  #define odp_cs(ptr, old, new) \
> -     _odp_atomic_ptr_cmp_xchg_strong(&ptr, (void **)&old, (void *)new, \
> -                                     _ODP_MEMMODEL_SC, \
> -                                     _ODP_MEMMODEL_SC)
> +     _odp_atomic_u64_cmp_xchg_strong_mm(&ptr, (uint64_t *)&old, \
> +                                        (uint64_t)new, \
> +                                        _ODP_MEMMODEL_SC, _ODP_MEMMODEL_SC)

On 32-bit machine this doubles a size of data to exchange. What is an
expected performance impact?

> +
> +/* Helper functions for offset tagging to avoid ABA race conditions */
> +#define odp_tag(offset) \
> +     (((uint64_t)offset) & (TAG_ALIGN - 1))
>  
> -/* Helper functions for pointer tagging to avoid ABA race conditions */
> -#define odp_tag(ptr) \
> -     (((size_t)ptr) & (TAG_ALIGN - 1))
> +#define off2ptr(offset, base) \
> +     ((void *)((size_t)base + ((size_t)((uint64_t)offset >> TAG_BITS))))
>  
> -#define odp_detag(ptr) \
> -     ((void *)(((size_t)ptr) & -TAG_ALIGN))
> +#define odp_detag(offset, base) \
> +     (((uint64_t)offset >> TAG_BITS) == NULL_DETAGGED_OFFSET ? NULL : \
> +      off2ptr(offset, base))
>  
> -#define odp_retag(ptr, tag) \
> -     ((void *)(((size_t)ptr) | odp_tag(tag)))
> +#define ptr2off(ptr, base) \
> +     ((uint64_t)(ptr == NULL ? (NULL_DETAGGED_OFFSET << TAG_BITS) : \
> +                 (((uint64_t)((size_t)ptr - (size_t)base)) << TAG_BITS)))
> +
> +#define odp_retag(ptr, base, tag) (ptr2off(ptr, base) | odp_tag(tag))
>  
>  
>  static inline void *get_blk(struct pool_entry_s *pool)
>  {
> -     void *oldhead, *myhead, *newhead;
> +     uint64_t oldhead, newhead;
> +     void *myhead;
>  
> -     oldhead = _odp_atomic_ptr_load(&pool->blk_freelist, _ODP_MEMMODEL_ACQ);
> +     oldhead = odp_atomic_load_u64(&pool->blk_freelist);
>  
>       do {
> -             size_t tag = odp_tag(oldhead);
> -             myhead = odp_detag(oldhead);
> +             uint64_t tag = odp_tag(oldhead);
> +             myhead = odp_detag(oldhead, pool->pool_base_addr);
>               if (odp_unlikely(myhead == NULL))
>                       break;
> -             newhead = odp_retag(((odp_buf_blk_t *)myhead)->next, tag + 1);
> +             newhead = odp_retag(((odp_buf_blk_t *)myhead)->next,
> +                                 pool->pool_base_addr, tag + 1);
>       } while (odp_cs(pool->blk_freelist, oldhead, newhead) == 0);
>  
> -     if (odp_unlikely(myhead == NULL))
> +     if (odp_unlikely(myhead == NULL)) {
>               odp_atomic_inc_u64(&pool->blkempty);
> -     else
> +     } else {
> +             odp_atomic_inc_u64(&pool->blkallocs);

This seems to be a not related change.

>               odp_atomic_dec_u32(&pool->blkcount);
> +     }
>  
> -     return (void *)myhead;
> +     return myhead;
>  }


-- 
Taras Kondratiuk

_______________________________________________
lng-odp mailing list
[email protected]
http://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to