Last active
April 7, 2022 00:26
-
-
Save lionello/9166483 to your computer and use it in GitHub Desktop.
__sync_val_compare_and_swap for __uint128_t GCC built-in
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
__sync_val_compare_and_swap that works with __uint128_t, by Lionello Lunesu. | |
Placed in the public domain | |
*/ | |
#undef NDEBUG | |
#include <assert.h> | |
inline __uint128_t InterlockedCompareExchange128( volatile __uint128_t * src, __uint128_t cmp, __uint128_t with ) | |
{ | |
__asm__ __volatile__ | |
( | |
"lock cmpxchg16b %1" | |
: "+A" ( cmp ) | |
, "+m" ( *src ) | |
: "b" ( (long long)with ) | |
, "c" ( (long long)(with>>64) ) | |
: "cc" | |
); | |
return cmp; | |
} | |
int main(int argc, char* argv[]) | |
{ | |
__uint128_t a=0, b=0, c=0x0123456789ABCDEFULL; | |
c <<= 64; | |
c |= 0xFEDCBA9876543210ULL; | |
assert(b == InterlockedCompareExchange128(&a, b, c)); | |
assert(a == c); | |
assert(c == InterlockedCompareExchange128(&a, b, b)); | |
assert(a == c); | |
assert(c == InterlockedCompareExchange128(&a, c, b)); | |
assert(a == b); | |
assert(b == InterlockedCompareExchange128(&a, c, c)); | |
assert(a == b); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think you don't need to specify cc as clobber, since ccz is already an output; and similarly you can specify ComparandResult[0,1] as input/output results (+ instead of =) rather than specifying them separately as input and clobber.
So it simplifies to just
Also, don't need to mark it as 'volatile'. With memory clobber of destination, it won't be elided because it's aliased. This gives acqrel semantics; you can set blanket memory clobber if you want seqcst semantics.