On 05/11/16 00:50, Bill Fischofer wrote:


On Tue, May 10, 2016 at 11:19 AM, Maxim Uvarov <[email protected] <mailto:[email protected]>> wrote:

    Ola, can you please review this patch?

    Bill, Bala,

    I am not sure that this change is correct.

    There is 2 things:
    1. Align on 16 bytes:


The entire struct will be aligned on a 16 byte boundary if ODP_ATOMIC_U128 is defined. Otherwise it is 8 byte aligned because of the definition of odp_atomic_u64_t:

struct odp_atomic_u64_s {
uint64_t v; /**< Actual storage for the atomic variable */
#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
/* Some architectures do not support lock-free operations on 64-bit
* data types. We use a spin lock to ensure atomicity. */
char lock; /**< Spin lock (if needed) used to ensure atomic access */
#endif
} ODP_ALIGNED(sizeof(uint64_t)); /* Enforce alignement! */;


    typedef struct tick_buf_s {
        odp_atomic_u64_t exp_tck;/* Expiration tick or TMO_xxx */
        odp_buffer_t tmo_buf;/* ODP_BUFFER_INVALID if timer not active */
    #ifdef TB_NEEDS_PAD
        uint32_t pad;/* Need to be able to access padding for
    successful CAS */
    #endif
    } tick_buf_t
    #ifdef ODP_ATOMIC_U128
    ODP_ALIGNED(16) /* 16-byte atomic operations need properly aligned
    addresses */
    #endif
    ;

    2.  Static assert that there is exactly 16 bytes:
    ODP_STATIC_ASSERT(sizeof(tick_buf_t) == 16, "sizeof(tick_buf_t) ==
    16");

This is the bug. When __GCC_ATOMIC_LLONG_LOCK_FREE < 2 is true an extra char is inserted into the struct which pushes the total length to be > 16 bytes. The original bug arises because this is false when compiling with GCC but true when compiling with clang. In fact, when compiling with clang on Ubuntu 32-bit sizeof(tick_buf_t) == 24.

Yes, I but I calculated 21, maybe missed something:

struct odp_atomic_u64_s {
    uint64_t v; // 8 bytes
#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2
    char lock; // 9 bytes
#endif
} ODP_ALIGNED(sizeof(uint64_t)); /* Enforce alignement! */;



typedef struct tick_buf_s {
    odp_atomic_u64_t exp_tck; // 8 or 9 bytes
    odp_buffer_t tmo_buf; // 8 bytes due to it's pointer
#ifdef TB_NEEDS_PAD
    uint32_t pad; // 4 bytes
#endif
} tick_buf_t
#ifdef ODP_ATOMIC_U128
ODP_ALIGNED(16)
#endif
;

So maximum sizeof(tick_buf_t) is 8 + 9 + 4 = 21 bytes. So usage of 128 bit cmp operation is not valid.

_odp_atomic_u128_cmp_xchg_mm() function is not defined anywhere so this branch inside ifdef looks like dead :) So we should not go to that code anyhow so that removing static_assert might works for us.

So I think that right fix what we can do now is:
1. remove static_assert completely.
2. remove currently dead code under #ifdef ODP_ATOMIC_U128

Do you agree?

Maxim.



    As I understand from code, Ola did that to use u128 functions for
    atomic exchange and
    compare. For example here:

           tick_buf_t new, old;

            _odp_atomic_u128_xchg_mm((_odp_atomic_u128_t *)tb,
                         (_uint128_t *)&new,
                         (_uint128_t *)&old,
                         _ODP_MEMMODEL_ACQ_RLS);

    That assumes that this structure has to be exactly or less (in
    that case adding zero padding in the end) 16 bytes,
    I.e. 16 bytes * 8 bits  = 1 u128_t


No, it simply requires that the struct be at least 16 bytes long, which is why it works with clang if the ODP_STATIC_ASSERT is corrected.


    By modifying this assert you hide problem that tail of function
    can not be copied/compared, makes code
    unpredictable and this static assert useless. Of course we can
    fall to memcpy() if struct is lager than 16 bytes,
    but gain of current optimisation can be lost. So we have to think
    about real fix here...


The tail processing is identical if TB_NEEDS_PAD is true. Under clang this in fact is false so there is no tail and the copy code disappears.

I can't say I'm completely happy with the code even before this fix, but the fix is needed because you cannot force this struct as written to be exactly 16 bytes in all cases. This was the simplest fix and the result is that the timer tests pass in both 32-bit and 64-bit environments after it is applied. If there is a problem that the timer tests aren't catching then that's a bug against the timer tests, not the implementation, but I don't see any timer failures.


    Thanks,
    Maxim.

    On 05/10/16 09:00, Bala Manoharan wrote:

        Reviewed-by: Balasubramanian Manoharan
        <[email protected] <mailto:[email protected]>
        <mailto:[email protected]
        <mailto:[email protected]>>>

        On 10 May 2016 at 07:25, Bill Fischofer
        <[email protected] <mailto:[email protected]>
        <mailto:[email protected]
        <mailto:[email protected]>>> wrote:

            The tick_buf_t struct may be larger than 16 bytes when a
        lock char is
            needed so correct the ODP_STATIC_ASSERT to reflect this. This
            addresses
            bug https://bugs.linaro.org/show_bug.cgi?id=2211 when
        compiling with
            clang.

            Signed-off-by: Bill Fischofer <[email protected]
        <mailto:[email protected]>
            <mailto:[email protected]
        <mailto:[email protected]>>>
            ---
             platform/linux-generic/odp_timer.c | 2 +-
             1 file changed, 1 insertion(+), 1 deletion(-)

            diff --git a/platform/linux-generic/odp_timer.c
            b/platform/linux-generic/odp_timer.c
            index f4fb1f6..89ec5f5 100644
            --- a/platform/linux-generic/odp_timer.c
            +++ b/platform/linux-generic/odp_timer.c
            @@ -107,7 +107,7 @@ ODP_ALIGNED(16) /* 16-byte atomic
        operations
            need properly aligned addresses */
             #endif
             ;

            -ODP_STATIC_ASSERT(sizeof(tick_buf_t) == 16,
        "sizeof(tick_buf_t)
            == 16");
            +ODP_STATIC_ASSERT(sizeof(tick_buf_t) >= 16,
        "sizeof(tick_buf_t)
            >= 16");

             typedef struct odp_timer_s {
                    void *user_ptr;
            --
            2.7.4

            _______________________________________________
            lng-odp mailing list
        [email protected] <mailto:[email protected]>
        <mailto:[email protected]
        <mailto:[email protected]>>
        https://lists.linaro.org/mailman/listinfo/lng-odp




        _______________________________________________
        lng-odp mailing list
        [email protected] <mailto:[email protected]>
        https://lists.linaro.org/mailman/listinfo/lng-odp


    _______________________________________________
    lng-odp mailing list
    [email protected] <mailto:[email protected]>
    https://lists.linaro.org/mailman/listinfo/lng-odp



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

Reply via email to