From fbc3e030e658c2c6d44bac084c3166d1fb737c7e Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Tue, 20 Jan 2015 23:36:50 +0000 Subject: util/u_atomic: Provide a _InterlockedCompareExchange8 for older MSVC. Fixes build with Windows SDK 7.0.7600. Tested with u_atomic_test, both on x86 and x86_64. Reviewed-by: Roland Scheidegger --- src/util/u_atomic.h | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/util/u_atomic.h b/src/util/u_atomic.h index a528e01bc98..cf7fff3f35b 100644 --- a/src/util/u_atomic.h +++ b/src/util/u_atomic.h @@ -84,7 +84,35 @@ #include #include -#pragma intrinsic(_InterlockedCompareExchange8) +#if _MSC_VER < 1600 + +/* Implement _InterlockedCompareExchange8 in terms of InterlockedCompareExchange16 */ +static __inline +char _InterlockedCompareExchange8(char volatile *Destination8, char Exchange8, char Comparand8) +{ + INT_PTR DestinationAddr = (INT_PTR)Destination8; + short volatile *Destination16 = (short volatile *)(DestinationAddr & ~1); + const short Shift8 = (DestinationAddr & 1) * 8; + const short Mask8 = 0xff << Shift8; + short Initial16 = *Destination16; + char Initial8 = Initial16 >> Shift8; + while (Initial8 == Comparand8) { + /* initial *Destination8 matches, so try exchange it while keeping the + * neighboring byte untouched */ + short Exchange16 = (Initial16 & ~Mask8) | ((short)Exchange8 << Shift8); + short Comparand16 = Initial16; + short Initial16 = InterlockedCompareExchange16(Destination16, Exchange16, Comparand16); + if (Initial16 == Comparand16) { + /* succeeded */ + return Comparand8; + } + /* something changed, retry with the new initial value */ + Initial8 = Initial16 >> Shift8; + } + return Initial8; +} + +#endif /* _MSC_VER < 1600 */ /* MSVC supports decltype keyword, but it's only supported on C++ and doesn't * quite work here; and if a C++-only solution is worthwhile, then it would be -- cgit v1.2.3