Mesa (master): util/u_atomic: Provide a _InterlockedCompareExchange8 for older MSVC.

Jose Fonseca jrfonseca at kemper.freedesktop.org
Fri Jan 30 15:25:59 UTC 2015


Module: Mesa
Branch: master
Commit: fbc3e030e658c2c6d44bac084c3166d1fb737c7e
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=fbc3e030e658c2c6d44bac084c3166d1fb737c7e

Author: José Fonseca <jfonseca at vmware.com>
Date:   Tue Jan 20 23:36:50 2015 +0000

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 at vmware.com>

---

 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 a528e01..cf7fff3 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




More information about the mesa-commit mailing list