summaryrefslogtreecommitdiffstats
path: root/src/util/u_atomic.h
diff options
context:
space:
mode:
authorJosé Fonseca <[email protected]>2015-01-20 23:36:50 +0000
committerJose Fonseca <[email protected]>2015-01-30 15:24:34 +0000
commitfbc3e030e658c2c6d44bac084c3166d1fb737c7e (patch)
treecba809e1780162a9ed33626d0f02af72be5fe13d /src/util/u_atomic.h
parentd7f2dfb67ee9c50f221d35c840d3427e8f184209 (diff)
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 <[email protected]>
Diffstat (limited to 'src/util/u_atomic.h')
-rw-r--r--src/util/u_atomic.h30
1 files changed, 29 insertions, 1 deletions
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 <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