Sudhanshu
Sudhanshu

Reputation: 51

Could somebody verify the correctness of the following inline assembly code gcc for compare and set?

The function as it looks to me is working fine. I am trying to implement a counter for a multi threaded application. As the counter value can be beyond the integer range, I using 64 bit for it. I am not very sure about the thread safety as, here we are dealing with 64 bit numbers.

UINT64 get_and_increment(volatile UINT64* dest) {

   UINT64 old_value, new_value;
   bool result = false;
   while(!result)   {
        old_value = *dest;
        new_value = old_value + 1;

        __asm__ volatile    (
                            "lock cmpxchg %3, %1 \n setzb %0"
                            : "=m"(result), "+m" (*dest)
                            : "a" (old_value), "r"(new_value)
                            );
   }
   return old_value;
}

Thanks

Sudhanshu Shukla

Upvotes: 0

Views: 311

Answers (1)

ephemient
ephemient

Reputation: 204718

Why not use GCC's built-in atomic intrinsics?

UINT64 get_and_increment(volatile UINT64* dest) {
    UINT64 old_value, new_value;
    do {
        old_value = *dest;
        new_value = old_value + 1;
    } while (!__sync_bool_compare_and_swap(dest, old_value, new_value));
    return old_value;
}

Or even

UINT64 get_and_increment(volatile UINT64* dest) {
    return __sync_fetch_and_add(dest, 1);
}

That being said, your assembly won't work on 32-bit platforms (lack of a 64-bit lock cmpxchg), and would be simpler written as lock xadd without a loop, but otherwise looks like it would work on 64-bit.

Upvotes: 2

Related Questions