[Gc] Various fixes for libatomic_ops

Ivan Maidanski ivmai at mail.ru
Wed Oct 29 16:10:36 PST 2008


Hi!

The patch does the following:
- support for Borland, Watcom, DigitalMars C/C++ compilers (lastest) is added (treated mostly as VC++) - now, GC could be built with threads support by these compilers same as for GC v6 (+THREAD_LOCAL_ALLOC +PARALLEL_MARK);
- AO_OLD_STYLE_INTERLOCKED_COMPARE_EXCHANGE macro is added for compilers (eg., DMC) still having old-style (pointer-based) InterlockedCompareExchange() declaration ("msftc/x86.h" file);
- _ReadWriteBarrier() intrinsic is used also for Win32 if at least VC++ 2005;
- the comment is corrected for AO_TS_val enum definition ("test_and_set_t_is_ao_t.h" file);
- "standard_ao_double_t.h" file is simplified (and a check for VC++ removed);
- ASSUME_VISTA is renamed to AO_ASSUME_VISTA in "msftc/x86.h" file;
- low/high value parts are swapped in AO_compare_double_and_swap_double_full()
for x64 (in "gcc/x86_64.h", "msftc/x86.h", "msftc/x86_64.h" files) since val1 is the lower part (lesser address) of AO_double_t and x86/x64 is a little-endian CPU
(look into correct AO_compare_double_and_swap_double_full() in "gcc/x86.h" and AO_compare_double_and_swap_double_emulation());
- AO_ASM_X64_AVAILABLE is added in "msftc/x86_64.c" file for future versions of VC++;
- AO_CASDOUBLE_MISSING macro removed (replaced with the opposite AO_CMPXCHG16B_AVAILABLE) in "msftc/x86_64.c" file;
- _InterlockedCompareExchange128() intrinsic is used to implement AO_compare_double_and_swap_double_full() if VC++ 2008 (and AO_CMPXCHG16B_AVAILABLE defined) in "msftc/x86_64.c" file;
- "standard_ao_double_t.h" is included from "msftc/x86_64.c" file (same as for "gcc/x86_64.c").

Bye.

-------------- next part --------------
diff -ru bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/gcc/x86_64.h updated/bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/gcc/x86_64.h
--- bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/gcc/x86_64.h	2008-10-22 06:12:17.000000000 +0400
+++ updated/bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/gcc/x86_64.h	2008-10-30 02:14:10.073089500 +0300
@@ -148,8 +148,9 @@
 
 #ifdef AO_CMPXCHG16B_AVAILABLE
 /* NEC LE-IT: older AMD Opterons are missing this instruction.
- * On these machines SIGILL will be thrown. Define AO_CASDOUBLE_MISSING
- * to have an emulated (lock based) version available */ 
+ * On these machines SIGILL will be thrown.
+ * Define AO_WEAK_DOUBLE_CAS_EMULATION to have an emulated
+ * (lock based) version available */ 
 /* HB: Changed this to not define either by default.  There are
  * enough machines and tool chains around on which cmpxchg16b
  * doesn't work.  And the emulation is unsafe by our usual rules.
@@ -164,10 +165,10 @@
   __asm__ __volatile__("lock; cmpxchg16b %0; setz %1"
 	    	       		: "=m"(*addr), "=q"(result)
 		       			: "m"(*addr),
-		       			  "d" (old_val1),
-		       			  "a" (old_val2),
-		         		  "c" (new_val1),
-		         		  "b" (new_val2)  : "memory");
+		       			  "d" (old_val2),
+		       			  "a" (old_val1),
+		         		  "c" (new_val2),
+		         		  "b" (new_val1)  : "memory");
   return (int) result;
 }
 #define AO_HAVE_compare_double_and_swap_double_full
diff -ru bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/msftc/x86.h updated/bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/msftc/x86.h
--- bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/msftc/x86.h	2008-01-08 05:51:12.000000000 +0300
+++ updated/bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/msftc/x86.h	2008-10-30 01:10:30.000000000 +0300
@@ -22,7 +22,7 @@
 
 /* The following really assume we have a 486 or better. 		*/
 /* If ASSUME_WINDOWS98 is defined, we assume Windows 98 or newer.	*/
-/* If ASSUME_VISTA is defined, we assume Windows Server 2003, Vista	*/
+/* If AO_ASSUME_VISTA is defined, we assume Windows Server 2003, Vista	*/
 /* or later.								*/
 
 #include "../all_aligned_atomic_load_store.h"
@@ -136,10 +136,11 @@
 {
     __asm
     {
-	mov	eax,AO_TS_SET		;
+	mov	eax,0xff		; /* AO_TS_SET */
 	mov	ebx,addr		;
 	xchg	byte ptr [ebx],al	;
     }
+    /* Ignore possible "missing return value" warning here. */
 }
 
 #define AO_HAVE_test_and_set_full
@@ -150,9 +151,15 @@
 AO_compare_and_swap_full(volatile AO_t *addr,
 		  	 AO_t old, AO_t new_val) 
 {
+# ifdef AO_OLD_STYLE_INTERLOCKED_COMPARE_EXCHANGE
+    return _InterlockedCompareExchange((PVOID volatile *)addr,
+                                       (PVOID)new_val, (PVOID)old)
+	   == (PVOID)old;
+# else
     return _InterlockedCompareExchange((LONG volatile *)addr,
                                        (LONG)new_val, (LONG)old)
 	   == (LONG)old;
+# endif
 }
 
 #define AO_HAVE_compare_and_swap_full
@@ -162,7 +169,7 @@
 #  error wrong architecture
 #endif
 
-#ifdef ASSUME_VISTA
+#ifdef AO_ASSUME_VISTA
 /* NEC LE-IT: whenever we run on a pentium class machine we have that
  * certain function */
 
@@ -174,8 +181,8 @@
         			       AO_t old_val1, AO_t old_val2,
                			       AO_t new_val1, AO_t new_val2) 
 {
-    __int64 oldv = (__int64)old_val2 | ((__int64)old_val1 << 32);
-    __int64 newv = (__int64)new_val2 | ((__int64)new_val1 << 32);
+    __int64 oldv = (__int64)old_val1 | ((__int64)old_val2 << 32);
+    __int64 newv = (__int64)new_val1 | ((__int64)new_val2 << 32);
     return _InterlockedCompareExchange64((__int64 volatile *)addr,
                                        newv, oldv) == oldv;
 }
@@ -192,6 +199,6 @@
 }
 #define AO_HAVE_double_compare_and_swap_full
 #endif // __cplusplus
-#endif /* ASSUME_VISTA */
+#endif /* AO_ASSUME_VISTA */
 
 #include "../ao_t_is_int.h"
diff -ru bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/msftc/x86_64.h updated/bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/msftc/x86_64.h
--- bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/msftc/x86_64.h	2008-01-07 09:11:52.000000000 +0300
+++ updated/bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/msftc/x86_64.h	2008-10-29 23:13:56.000000000 +0300
@@ -34,17 +34,14 @@
 
 #include "../ordered_except_wr.h"
 
-#if 0
-FIXME: Need to reimplement testandset
-
-#include "../test_and_set_t_is_char.h"
-
+#ifdef AO_ASM_X64_AVAILABLE
+# include "../test_and_set_t_is_char.h"
 #else
-
-#include "../test_and_set_t_is_ao_t.h"
-
+# include "../test_and_set_t_is_ao_t.h"
 #endif
 
+#include "../standard_ao_double_t.h"
+
 #include <windows.h>
 	/* Seems like over-kill, but that's what MSDN recommends.	*/
 	/* And apparently winbase.h is not always self-contained.	*/
@@ -138,49 +135,71 @@
 
 #define AO_HAVE_compare_and_swap_full
 
-#if 0
-FIXME: (__asm not supported)
+#ifdef AO_ASM_X64_AVAILABLE
+
 AO_INLINE AO_TS_VAL_t
 AO_test_and_set_full(volatile AO_TS_t *addr)
 {
     __asm
     {
-	mov	eax,AO_TS_SET		;
-	mov	ebx,addr		;
-	xchg	byte ptr [ebx],al	;
+	mov	rax,AO_TS_SET		;
+	mov	rbx,addr		;
+	xchg	byte ptr [rbx],al	;
     }
 }
 
 #define AO_HAVE_test_and_set_full
 
-FIXME: (__asm not supported)
-NEC LE-IT: Don't have a working Win64 environment here at the moment.
-AO_compare_double_and_swap_double_full needs implementation for Win64
-But there is no _InterlockedCompareExchange128 in the WinAPI, so we
-need basically whats given below.
-Also see gcc/x86_64.h for partial old opteron workaround:
+#endif /* AO_ASM_X64_AVAILABLE */
+
+#ifdef AO_CMPXCHG16B_AVAILABLE
+
+/* AO_compare_double_and_swap_double_full needs implementation for Win64.
+ * Also see ../gcc/x86_64.h for partial old Opteron workaround.
+ */
+
+# if _MSC_VER >= 1500
+
+#pragma intrinsic (_InterlockedCompareExchange128)
 
-#ifndef AO_CASDOUBLE_MISSING
+AO_INLINE int
+AO_compare_double_and_swap_double_full(volatile AO_double_t *addr,
+				       AO_t old_val1, AO_t old_val2,
+		                       AO_t new_val1, AO_t new_val2)
+{
+   __int64 comparandResult[2];
+   comparandResult[0] = old_val1; /* low */
+   comparandResult[1] = old_val2; /* high */
+   return _InterlockedCompareExchange128((volatile __int64 *)addr,
+		new_val2 /* high */, new_val1 /* low */, comparandResult);
+}
+
+#   define AO_HAVE_compare_double_and_swap_double_full
+
+# elif defined(AO_ASM_X64_AVAILABLE)
+
+ /* If there is no intrinsic _InterlockedCompareExchange128 then we
+  * need basically what's given below.
+  */
 
 AO_INLINE int
 AO_compare_double_and_swap_double_full(volatile AO_double_t *addr,
 				       AO_t old_val1, AO_t old_val2,
 		                       AO_t new_val1, AO_t new_val2)
 {
-	char result;
 	__asm
 	{
-		mov	rdx,QWORD PTR [old_val]
-		mov	rax,QWORD PTR [old_val + 8]
-		mov	rcx,QWORD PTR [new_val]
-		mov	rbx,QWORD PTR [new_val + 8]
-		lock cmpxchg16b	[addr]
-		setz result;
+		mov	rdx,QWORD PTR [old_val2]	;
+		mov	rax,QWORD PTR [old_val1]	;
+		mov	rcx,QWORD PTR [new_val2]	;
+		mov	rbx,QWORD PTR [new_val1]	;
+		lock cmpxchg16b	[addr]			;
+		setz	rax				;
 	}
-	return result;
 }
-#endif // AO_CASDOUBLE_MISSING
-#define AO_HAVE_compare_double_and_swap_double_full
 
-#endif /* 0 */
+#   define AO_HAVE_compare_double_and_swap_double_full
+
+# endif /* _MSC_VER >= 1500 || AO_ASM_X64_AVAILABLE */
 
+#endif /* AO_CMPXCHG16B_AVAILABLE */
diff -ru bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/standard_ao_double_t.h updated/bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/standard_ao_double_t.h
--- bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/standard_ao_double_t.h	2008-01-09 23:11:44.000000000 +0300
+++ updated/bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/standard_ao_double_t.h	2008-10-29 21:08:10.000000000 +0300
@@ -4,27 +4,16 @@
 *   	   to align	it on 16 byte boundary (as required by cmpxchg16.
 * Similar things could be done for PowerPC 64bit using a VMX data type...	*/
 
-#if defined(__GNUC__)
-# if defined(__x86_64__)
-# include<xmmintrin.h>
-   typedef __m128 double_ptr_storage;
-#  define AO_HAVE_DOUBLE_PTR_STORAGE
-# endif /* __x86_64__ */
+#if (defined(__x86_64__) && defined(__GNUC__)) || defined(_WIN64)
+# include <xmmintrin.h>
+  typedef __m128 double_ptr_storage;
+#elif defined(_WIN32) && !defined(__GNUC__)
+  typedef unsigned __int64 double_ptr_storage;
+#else
+  typedef unsigned long long double_ptr_storage;
 #endif
 
-#ifdef _MSC_VER
-# ifdef _WIN64
-   typedef __m128 double_ptr_storage;
-#  define AO_HAVE_DOUBLE_PTR_STORAGE
-# elif _WIN32
-   typedef unsigned __int64 double_ptr_storage;
-#  define AO_HAVE_DOUBLE_PTR_STORAGE
-# endif
-#endif
-
-#ifndef AO_HAVE_DOUBLE_PTR_STORAGE
-   typedef unsigned long long double_ptr_storage;
-#endif
+# define AO_HAVE_DOUBLE_PTR_STORAGE
 
 typedef union {
     double_ptr_storage AO_whole;
diff -ru bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/test_and_set_t_is_ao_t.h updated/bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/test_and_set_t_is_ao_t.h
--- bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/test_and_set_t_is_ao_t.h	2006-07-12 04:29:31.000000000 +0400
+++ updated/bdwgc/libatomic_ops-1.2/src/atomic_ops/sysdeps/test_and_set_t_is_ao_t.h	2008-10-29 22:07:22.000000000 +0300
@@ -23,7 +23,7 @@
 /*
  * These are common definitions for architectures on which test_and_set
  * operates on pointer-sized quantities, the "clear" value contains
- * all zeroes, and the "set" value contains all ones.
+ * all zeroes, and the "set" value contains only one lowest bit set.
  * This can be used if test_and_set is synthesized from compare_and_swap.
  */
 typedef enum {AO_TS_clear = 0, AO_TS_set = 1} AO_TS_val; 
diff -ru bdwgc/libatomic_ops-1.2/src/atomic_ops.h updated/bdwgc/libatomic_ops-1.2/src/atomic_ops.h
--- bdwgc/libatomic_ops-1.2/src/atomic_ops.h	2008-10-22 06:12:17.000000000 +0400
+++ updated/bdwgc/libatomic_ops-1.2/src/atomic_ops.h	2008-10-29 21:32:20.000000000 +0300
@@ -147,7 +147,8 @@
 #define AO_TS_INITIALIZER (AO_t)AO_TS_CLEAR
 
 /* Platform-dependent stuff:					*/
-#if defined(__GNUC__) || defined(_MSC_VER) || defined(__INTEL_COMPILER)
+#if defined(__GNUC__) || defined(_MSC_VER) || defined(__INTEL_COMPILER) \
+	|| defined(__DMC__) || defined(__WATCOMC__)
 # define AO_INLINE static __inline
 #else
 # define AO_INLINE static
@@ -155,8 +156,9 @@
 
 #if defined(__GNUC__) && !defined(__INTEL_COMPILER)
 # define AO_compiler_barrier() __asm__ __volatile__("" : : : "memory")
-#elif defined(_MSC_VER)
-# if defined(_AMD64_)
+#elif defined(_MSC_VER) || defined(__DMC__) || defined(__BORLANDC__) \
+	|| defined(__WATCOMC__)
+# if defined(_AMD64_) || _MSC_VER >= 1400
 #   pragma intrinsic(_ReadWriteBarrier)
 #   define AO_compiler_barrier() _ReadWriteBarrier()
 	/* We assume this does not generate a fence instruction.	*/
@@ -257,7 +259,8 @@
 #   define AO_CAN_EMUL_CAS
 #endif
 
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) || defined(__DMC__) || defined(__BORLANDC__) \
+	|| (defined(__WATCOMC__) && defined(__NT__))
 # if defined(_AMD64_)
 #   include "atomic_ops/sysdeps/msftc/x86_64.h"
 # elif _M_IX86 >= 400


More information about the Gc mailing list