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 <sroland@vmware.com>
This commit is contained in:
parent
d7f2dfb67e
commit
fbc3e030e6
|
@ -84,7 +84,35 @@
|
|||
#include <intrin.h>
|
||||
#include <assert.h>
|
||||
|
||||
#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
|
||||
|
|
Loading…
Reference in New Issue