[mono/mono] [23 commits] 9dd59c1f: Remove unneeded NetBSD code path from atomic.h.

"alexrp ([email protected])" <[email protected]>
Newsgroups gmane.comp.gnome.mono.patches
Message-ID <00000141dbf7c8ab-929bc190-acc4-4ef4-b29d-fa9970b133e2-000000@email.amazonses.com>
   Branch: refs/heads/master
     Home: https://github.com/mono/mono
  Compare: https://github.com/mono/mono/compare/17d4130d1b86...e4d2cc49a03b

   Commit: 9dd59c1f1381ad7645039e33b7c2120078bfa349
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 13:57:24 GMT
      URL: https://github.com/mono/mono/commit/9dd59c1f1381ad7645039e33b7c2120078bfa349

Remove unneeded NetBSD code path from atomic.h.

Changed paths:
  M mono/utils/atomic.h

Modified: mono/utils/atomic.h
===================================================================
@@ -11,16 +11,6 @@
 #ifndef _WAPI_ATOMIC_H_
 #define _WAPI_ATOMIC_H_
 
-#if defined(__NetBSD__)
-#include <sys/param.h>
-
-#if __NetBSD_Version__ > 499004000
-#include <sys/atomic.h>
-#define HAVE_ATOMIC_OPS
-#endif
-
-#endif
-
 #include "config.h"
 #include <glib.h>
 
@@ -105,46 +95,6 @@ static inline gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64
 
 #endif
 
-
-#elif defined(__NetBSD__) && defined(HAVE_ATOMIC_OPS)
-
-static inline gint32 InterlockedCompareExchange(volatile gint32 *dest,
-       gint32 exch, gint32 comp)
-{
-       return atomic_cas_32((uint32_t*)dest, comp, exch);
-}
-
-static inline gpointer InterlockedCompareExchangePointer(volatile gpointer *dest, gpointer exch, gpointer comp)
-{
-       return atomic_cas_ptr(dest, comp, exch);
-}
-
-static inline gint32 InterlockedIncrement(volatile gint32 *val)
-{
-       return atomic_inc_32_nv((uint32_t*)val);
-}
-
-static inline gint32 InterlockedDecrement(volatile gint32 *val)
-{
-       return atomic_dec_32_nv((uint32_t*)val);
-}
-
-static inline gint32 InterlockedExchange(volatile gint32 *val, gint32 new_val)
-{
-       return atomic_swap_32((uint32_t*)val, new_val);
-}
-
-static inline gpointer InterlockedExchangePointer(volatile gpointer *val,
-               gpointer new_val)
-{
-       return atomic_swap_ptr(val, new_val);
-}
-
-static inline gint32 InterlockedExchangeAdd(volatile gint32 *val, gint32 add)
-{
-       return atomic_add_32_nv((uint32_t*)val, add) - add;
-}
-
 #elif (defined(sparc) || defined (__sparc__)) && defined(__GNUC__)
 
 G_GNUC_UNUSED 

   Commit: fd6f60245f2f6651bf93da05b9a0b7c60ab9ded3
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 13:57:24 GMT
      URL: https://github.com/mono/mono/commit/fd6f60245f2f6651bf93da05b9a0b7c60ab9ded3

Simplify the ifdeffery in atomic.c/.h a bit.

Changed paths:
  M mono/utils/atomic.c
  M mono/utils/atomic.h

Modified: mono/utils/atomic.c
===================================================================
@@ -13,7 +13,7 @@
 
 #include <mono/utils/atomic.h>
 
-#if defined (WAPI_NO_ATOMIC_ASM) || !defined (HAS_64BITS_ATOMICS)
+#if defined (WAPI_NO_ATOMIC_ASM) || defined (BROKEN_64BIT_ATOMICS_INTRINSIC)
 
 #include <pthread.h>
 
@@ -197,11 +197,13 @@ gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add)
 	return(ret);
 }
 
+#define NEED_64BIT_CMPXCHG_FALLBACK
+
 #endif
 
-#ifndef HAS_64BITS_ATOMICS
+#if defined (BROKEN_64BIT_ATOMICS_INTRINSIC)
 
-#if defined (TARGET_MACH) && defined (TARGET_ARM) && (defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7S__))
+#if defined (TARGET_MACH) && defined (TARGET_ARM) && defined (HAVE_ARMV7)
 
 gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)  __attribute__ ((naked));
 
@@ -240,6 +242,14 @@ gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add)
 
 #else
 
+#define NEED_64BIT_CMPXCHG_FALLBACK
+
+#endif
+
+#endif
+
+#if defined (NEED_64BIT_CMPXCHG_FALLBACK)
+
 gint64
 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)
 {
@@ -256,4 +266,3 @@ gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add)
 }
 
 #endif
-#endif

Modified: mono/utils/atomic.h
===================================================================
@@ -22,7 +22,6 @@
 #if defined(__WIN32__) || defined(_WIN32)
 
 #include <windows.h>
-#define HAS_64BITS_ATOMICS 1
 
 /* mingw is missing InterlockedCompareExchange64 () from winbase.h */
 #if HAVE_DECL_INTERLOCKEDCOMPAREEXCHANGE64==0
@@ -84,9 +83,7 @@ static inline gint32 InterlockedExchangeAdd(volatile gint32 *val, gint32 add)
 #define BROKEN_64BIT_ATOMICS_INTRINSIC 1
 #endif
 
-
 #if !defined (BROKEN_64BIT_ATOMICS_INTRINSIC)
-#define HAS_64BITS_ATOMICS 1
 
 static inline gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)
 {
@@ -505,8 +502,10 @@ static inline gint32 InterlockedExchangeAdd(gint32 volatile *val, gint32 add)
 
 #endif
 
-#ifndef HAS_64BITS_ATOMICS
+#if defined (WAPI_NO_ATOMIC_ASM) || defined (BROKEN_64BIT_ATOMICS_INTRINSIC)
+
 extern gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp);
+
 #endif
 
 #endif /* _WAPI_ATOMIC_H_ */

   Commit: a33ce0c39fe7aa04292eb2fa2d0c89da7ba02c6e
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 13:57:24 GMT
      URL: https://github.com/mono/mono/commit/a33ce0c39fe7aa04292eb2fa2d0c89da7ba02c6e

Use host preprocessor identifiers in atomic.c, not target.

Here we care about the system we run on, not the kind of
system that Mono is built to compile for.

Changed paths:
  M mono/utils/atomic.c

Modified: mono/utils/atomic.c
===================================================================
@@ -203,7 +203,7 @@ gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add)
 
 #if defined (BROKEN_64BIT_ATOMICS_INTRINSIC)
 
-#if defined (TARGET_MACH) && defined (TARGET_ARM) && defined (HAVE_ARMV7)
+#if defined (TARGET_MACH) && defined (__arm__) && defined (HAVE_ARMV7)
 
 gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)  __attribute__ ((naked));
 
@@ -232,7 +232,7 @@ gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add)
 	);
 }
 
-#elif defined (TARGET_MACH) && (defined (TARGET_X86) || defined (TARGET_AMD64))
+#elif defined (TARGET_MACH) && (defined (__i386__) || defined (__x86_64__))
 
 gint64
 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)

   Commit: bf0b8a1d1aa61d5123b2a812cc9c4665d2d97d93
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 13:57:24 GMT
      URL: https://github.com/mono/mono/commit/bf0b8a1d1aa61d5123b2a812cc9c4665d2d97d93

Remove unneeded ARM code from atomic.c.

Changed paths:
  M mono/utils/atomic.c

Modified: mono/utils/atomic.c
===================================================================
@@ -203,36 +203,7 @@ gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add)
 
 #if defined (BROKEN_64BIT_ATOMICS_INTRINSIC)
 
-#if defined (TARGET_MACH) && defined (__arm__) && defined (HAVE_ARMV7)
-
-gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)  __attribute__ ((naked));
-
-gint64
-InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)
-{
-	__asm__ (
-	"push {r4, r5, r6, r7}\n"
-	"ldr r4, [sp, #16]\n"
-	"dmb\n"
-"1:\n"
-	"ldrexd	r6, r7, [r0]\n"
-	"cmp	r7, r4\n"
-	"bne 2f\n"
-	"cmp	r6, r3\n"
-	"bne	2f\n"
-	"strexd	r5, r1, r2, [r0]\n"
-	"cmp	r5, #0\n"
-	"bne	1b\n"
-"2:\n"
-	"dmb\n"
-	"mov	r0, r6\n"
-	"mov	r1, r7\n"
-	"pop {r4, r5, r6, r7}\n"
-	"bx	lr\n"
-	);
-}
-
-#elif defined (TARGET_MACH) && (defined (__i386__) || defined (__x86_64__))
+#if defined (TARGET_OSX)
 
 gint64
 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)

   Commit: a3632c6274fa78c7de1bcb8eb62c021861a205a9
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 13:57:25 GMT
      URL: https://github.com/mono/mono/commit/a3632c6274fa78c7de1bcb8eb62c021861a205a9

Use GCC atomics on s390x.

Changed paths:
  M configure.in
  M mono/utils/atomic.h

Modified: configure.in
===================================================================
@@ -2783,7 +2783,7 @@ esac
 dnl Use GCC atomic ops if they work on the target.
 if test x$GCC = "xyes"; then
 	case $TARGET in
-	X86 | AMD64 | ARM | POWERPC | POWERPC64 | MIPS)
+	X86 | AMD64 | ARM | POWERPC | POWERPC64 | MIPS | S390X)
 		AC_DEFINE(USE_GCC_ATOMIC_OPS, 1, [...])
 		;;
 	esac

Modified: mono/utils/atomic.h
===================================================================
@@ -252,126 +252,6 @@ static inline gint32 InterlockedExchangeAdd(volatile gint32 *_dest, gint32 add)
         return ret;
 }
 
-#elif __s390x__
-
-static inline gint32 
-InterlockedCompareExchange(volatile gint32 *dest,
-			   gint32 exch, gint32 comp)
-{
-	gint32 old;
-
-	__asm__ __volatile__ ("\tLA\t1,%0\n"
-			      "\tLR\t%1,%3\n"
-			      "\tCS\t%1,%2,0(1)\n"
-			      : "+m" (*dest), "=&r" (old)
-			      : "r" (exch), "r" (comp)
-			      : "1", "cc");	
-	return(old);
-}
-
-static inline gpointer 
-InterlockedCompareExchangePointer(volatile gpointer *dest, 
-				  gpointer exch, 
-			          gpointer comp)
-{
-	gpointer old;
-
-	__asm__ __volatile__ ("\tLA\t1,%0\n"
-			      "\tLGR\t%1,%3\n"
-			      "\tCSG\t%1,%2,0(1)\n"
-			      : "+m" (*dest), "=&r" (old)
-			      : "r" (exch), "r" (comp)
-			      : "1", "cc");
-
-	return(old);
-}
-
-static inline gint32 
-InterlockedIncrement(volatile gint32 *val)
-{
-	gint32 tmp;
-	
-	__asm__ __volatile__ ("\tLA\t2,%1\n"
-			      "0:\tLGF\t%0,%1\n"
-			      "\tLGFR\t1,%0\n"
-			      "\tAGHI\t1,1\n"
-			      "\tCS\t%0,1,0(2)\n"
-			      "\tJNZ\t0b\n"
-			      "\tLGFR\t%0,1"
-			      : "=r" (tmp), "+m" (*val)
-			      : : "1", "2", "cc");
-
-	return(tmp);
-}
-
-static inline gint32 
-InterlockedDecrement(volatile gint32 *val)
-{
-	gint32 tmp;
-	
-	__asm__ __volatile__ ("\tLA\t2,%1\n"
-			      "0:\tLGF\t%0,%1\n"
-			      "\tLGFR\t1,%0\n"
-			      "\tAGHI\t1,-1\n"
-			      "\tCS\t%0,1,0(2)\n"
-			      "\tJNZ\t0b\n"
-			      "\tLGFR\t%0,1"
-			      : "=r" (tmp), "+m" (*val)
-			      : : "1", "2", "cc");
-
-	return(tmp);
-}
-
-static inline gint32 
-InterlockedExchange(volatile gint32 *val, gint32 new_val)
-{
-	gint32 ret;
-	
-	__asm__ __volatile__ ("\tLA\t1,%0\n"
-			      "0:\tL\t%1,%0\n"
-			      "\tCS\t%1,%2,0(1)\n"
-			      "\tJNZ\t0b"
-			      : "+m" (*val), "=&r" (ret)
-			      : "r" (new_val)
-			      : "1", "cc");
-
-	return(ret);
-}
-
-static inline gpointer
-InterlockedExchangePointer(volatile gpointer *val, gpointer new_val)
-{
-	gpointer ret;
-	
-	__asm__ __volatile__ ("\tLA\t1,%0\n"
-			      "0:\tLG\t%1,%0\n"
-			      "\tCSG\t%1,%2,0(1)\n"
-			      "\tJNZ\t0b"
-			      : "+m" (*val), "=&r" (ret)
-			      : "r" (new_val)
-			      : "1", "cc");
-
-	return(ret);
-}
-
-static inline gint32 
-InterlockedExchangeAdd(volatile gint32 *val, gint32 add)
-{
-	gint32 ret;
-
-	__asm__ __volatile__ ("\tLA\t2,%1\n"
-			      "0:\tLGF\t%0,%1\n"
-			      "\tLGFR\t1,%0\n"
-			      "\tAGR\t1,%2\n"
-			      "\tCS\t%0,1,0(2)\n"
-			      "\tJNZ\t0b"
-			      : "=&r" (ret), "+m" (*val)
-			      : "r" (add) 
-			      : "1", "2", "cc");
-	
-	return(ret);
-}
-
 #elif defined(__ia64__)
 
 #ifdef __INTEL_COMPILER

   Commit: 6d2008b01354eb309464eb5ca5650dcef8714f41
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 13:57:25 GMT
      URL: https://github.com/mono/mono/commit/6d2008b01354eb309464eb5ca5650dcef8714f41

Remove MONO_ARCH_SAVE_REGS from threading icalls.

Changed paths:
  M mono/metadata/threads.c

Modified: mono/metadata/threads.c
===================================================================
@@ -1182,8 +1182,6 @@ HANDLE ves_icall_System_Threading_Thread_Thread_internal(MonoThread *this,
 
 void ves_icall_System_Threading_InternalThread_Thread_free_internal (MonoInternalThread *this, HANDLE thread)
 {
-	MONO_ARCH_SAVE_REGS;
-
 	THREAD_DEBUG (g_message ("%s: Closing thread %p, handle %p", __func__, this, thread));
 
 	if (thread)
@@ -1273,8 +1271,6 @@ void ves_icall_System_Threading_Thread_SpinWait_nop (void)
 gint32
 ves_icall_System_Threading_Thread_GetDomainID (void) 
 {
-	MONO_ARCH_SAVE_REGS;
-
 	return mono_domain_get()->domain_id;
 }
 
@@ -1640,8 +1636,6 @@ gboolean ves_icall_System_Threading_WaitHandle_WaitOne_internal(MonoObject *this
 	guint32 ret;
 	MonoInternalThread *thread = mono_thread_internal_current ();
 
-	MONO_ARCH_SAVE_REGS;
-
 	if (ms == -1)
 		ms = INFINITE;
 
@@ -1660,8 +1654,6 @@ HANDLE ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned,
 { 
 	HANDLE mutex;
 	
-	MONO_ARCH_SAVE_REGS;
-   
 	*created = TRUE;
 	
 	if (name == NULL) {
@@ -1678,8 +1670,6 @@ HANDLE ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned,
 }                                                                   
 
 MonoBoolean ves_icall_System_Threading_Mutex_ReleaseMutex_internal (HANDLE handle ) { 
-	MONO_ARCH_SAVE_REGS;
-
 	return(ReleaseMutex (handle));
 }
 
@@ -1689,8 +1679,6 @@ HANDLE ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoString *name,
 {
 	HANDLE ret;
 	
-	MONO_ARCH_SAVE_REGS;
-	
 	*error = ERROR_SUCCESS;
 	
 	ret = OpenMutex (rights, FALSE, mono_string_chars (name));
@@ -1706,8 +1694,6 @@ HANDLE ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 ini
 { 
 	HANDLE sem;
 	
-	MONO_ARCH_SAVE_REGS;
-   
 	*created = TRUE;
 	
 	if (name == NULL) {
@@ -1728,8 +1714,6 @@ gint32 ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (HANDLE ha
 { 
 	gint32 prevcount;
 	
-	MONO_ARCH_SAVE_REGS;
-
 	*fail = !ReleaseSemaphore (handle, releaseCount, &prevcount);
 
 	return (prevcount);
@@ -1739,8 +1723,6 @@ HANDLE ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (MonoString *
 {
 	HANDLE ret;
 	
-	MONO_ARCH_SAVE_REGS;
-	
 	*error = ERROR_SUCCESS;
 	
 	ret = OpenSemaphore (rights, FALSE, mono_string_chars (name));
@@ -1755,8 +1737,6 @@ HANDLE ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manua
 {
 	HANDLE event;
 	
-	MONO_ARCH_SAVE_REGS;
-
 	*created = TRUE;
 
 	if (name == NULL) {
@@ -1774,21 +1754,15 @@ HANDLE ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manua
 }
 
 gboolean ves_icall_System_Threading_Events_SetEvent_internal (HANDLE handle) {
-	MONO_ARCH_SAVE_REGS;
-
 	return (SetEvent(handle));
 }
 
 gboolean ves_icall_System_Threading_Events_ResetEvent_internal (HANDLE handle) {
-	MONO_ARCH_SAVE_REGS;
-
 	return (ResetEvent(handle));
 }
 
 void
 ves_icall_System_Threading_Events_CloseEvent_internal (HANDLE handle) {
-	MONO_ARCH_SAVE_REGS;
-
 	CloseHandle (handle);
 }
 
@@ -1798,8 +1772,6 @@ HANDLE ves_icall_System_Threading_Events_OpenEvent_internal (MonoString *name,
 {
 	HANDLE ret;
 	
-	MONO_ARCH_SAVE_REGS;
-	
 	*error = ERROR_SUCCESS;
 	
 	ret = OpenEvent (rights, FALSE, mono_string_chars (name));
@@ -1812,8 +1784,6 @@ HANDLE ves_icall_System_Threading_Events_OpenEvent_internal (MonoString *name,
 
 gint32 ves_icall_System_Threading_Interlocked_Increment_Int (gint32 *location)
 {
-	MONO_ARCH_SAVE_REGS;
-
 	return InterlockedIncrement (location);
 }
 
@@ -1821,8 +1791,6 @@ gint64 ves_icall_System_Threading_Interlocked_Increment_Long (gint64 *location)
 {
 	gint64 ret;
 
-	MONO_ARCH_SAVE_REGS;
-
 	mono_interlocked_lock ();
 
 	ret = ++ *location;
@@ -1835,8 +1803,6 @@ gint64 ves_icall_System_Threading_Interlocked_Increment_Long (gint64 *location)
 
 gint32 ves_icall_System_Threading_Interlocked_Decrement_Int (gint32 *location)
 {
-	MONO_ARCH_SAVE_REGS;
-
 	return InterlockedDecrement(location);
 }
 
@@ -1844,8 +1810,6 @@ gint64 ves_icall_System_Threading_Interlocked_Decrement_Long (gint64 * location)
 {
 	gint64 ret;
 
-	MONO_ARCH_SAVE_REGS;
-
 	mono_interlocked_lock ();
 
 	ret = -- *location;
@@ -1857,8 +1821,6 @@ gint64 ves_icall_System_Threading_Interlocked_Decrement_Long (gint64 * location)
 
 gint32 ves_icall_System_Threading_Interlocked_Exchange_Int (gint32 *location, gint32 value)
 {
-	MONO_ARCH_SAVE_REGS;
-
 	return InterlockedExchange(location, value);
 }
 
@@ -1879,8 +1841,6 @@ gfloat ves_icall_System_Threading_Interlocked_Exchange_Single (gfloat *location,
 {
 	IntFloatUnion val, ret;
 
-	MONO_ARCH_SAVE_REGS;
-
 	val.fval = value;
 	ret.ival = InterlockedExchange((gint32 *) location, val.ival);
 
@@ -1936,8 +1896,6 @@ gfloat ves_icall_System_Threading_Interlocked_Exchange_Single (gfloat *location,
 
 gint32 ves_icall_System_Threading_Interlocked_CompareExchange_Int(gint32 *location, gint32 value, gint32 comparand)
 {
-	MONO_ARCH_SAVE_REGS;
-
 	return InterlockedCompareExchange(location, value, comparand);
 }
 
@@ -1958,8 +1916,6 @@ gfloat ves_icall_System_Threading_Interlocked_CompareExchange_Single (gfloat *lo
 {
 	IntFloatUnion val, ret, cmp;
 
-	MONO_ARCH_SAVE_REGS;
-
 	val.fval = value;
 	cmp.fval = comparand;
 	ret.ival = InterlockedCompareExchange((gint32 *) location, val.ival, cmp.ival);

   Commit: 7fae16348a5d801fe8b1a79f534656bf74856a01
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 13:57:25 GMT
      URL: https://github.com/mono/mono/commit/7fae16348a5d801fe8b1a79f534656bf74856a01

Kill the Cygwin hack in mono-membar.h.

We only support GCC 4.x in Cygwin now.

Changed paths:
  M mono/utils/mono-membar.h

Modified: mono/utils/mono-membar.h
===================================================================
@@ -45,34 +45,6 @@ static inline void mono_memory_write_barrier (void)
 	_WriteBarrier ();
 	MemoryBarrier ();
 }
-#elif defined(__WIN32__) || defined(_WIN32)
-#include <windows.h>
-
-/* Since we only support GCC 3.x in Cygwin for
-   some arcane reason, we have to use inline
-   assembly to get fences (__sync_synchronize
-   is not available). */
-
-static inline void mono_memory_barrier (void)
-{
-	__asm__ __volatile__ (
-		"lock\n\t"
-		"addl\t$0,0(%%esp)\n\t"
-		:
-		:
-		: "memory"
-	);
-}
-
-static inline void mono_memory_read_barrier (void)
-{
-	mono_memory_barrier ();
-}
-
-static inline void mono_memory_write_barrier (void)
-{
-	mono_memory_barrier ();
-}
 #elif defined(USE_GCC_ATOMIC_OPS)
 static inline void mono_memory_barrier (void)
 {

   Commit: e601897f3f14145f9ff2d48981f87f8a0c7fef4a
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 13:57:25 GMT
      URL: https://github.com/mono/mono/commit/e601897f3f14145f9ff2d48981f87f8a0c7fef4a

Use mono_memory_barrier () for Thread.MemoryBarrier ().

This gets rid of the rather hacky lock-based barrier.

Changed paths:
  M mono/metadata/threads.c

Modified: mono/metadata/threads.c
===================================================================
@@ -2040,8 +2040,7 @@ gfloat ves_icall_System_Threading_Interlocked_CompareExchange_Single (gfloat *lo
 void
 ves_icall_System_Threading_Thread_MemoryBarrier (void)
 {
-	mono_threads_lock ();
-	mono_threads_unlock ();
+	mono_memory_barrier ();
 }
 
 void

   Commit: ec96b2dc2289e00a9c30a8b39b14c3f62ab484ed
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 15:59:21 GMT
      URL: https://github.com/mono/mono/commit/ec96b2dc2289e00a9c30a8b39b14c3f62ab484ed

Add implementations of various interlocked functions to atomic.c/.h.

Mainly 64-bit variants, but also InterlockedAdd ().

Changed paths:
  M mono/utils/atomic.c
  M mono/utils/atomic.h

Modified: mono/utils/atomic.c
===================================================================
@@ -82,6 +82,52 @@ gpointer InterlockedCompareExchangePointer(volatile gpointer *dest,
 	return(old);
 }
 
+gint32 InterlockedAdd(volatile gint32 *dest, gint32 add)
+{
+	gint32 ret;
+	int thr_ret;
+
+	mono_once(&spin_once, spin_init);
+
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
+
+	*dest += add;
+	ret= *dest;
+
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
+
+	pthread_cleanup_pop (0);
+
+	return(ret);
+}
+
+gint64 InterlockedAdd64(volatile gint64 *dest, gint64 add)
+{
+	gint64 ret;
+	int thr_ret;
+
+	mono_once(&spin_once, spin_init);
+
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
+
+	*dest += add;
+	ret= *dest;
+
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
+
+	pthread_cleanup_pop (0);
+
+	return(ret);
+}
+
 gint32 InterlockedIncrement(volatile gint32 *dest)
 {
 	gint32 ret;
@@ -105,6 +151,29 @@ gint32 InterlockedIncrement(volatile gint32 *dest)
 	return(ret);
 }
 
+gint64 InterlockedIncrement64(volatile gint64 *dest)
+{
+	gint64 ret;
+	int thr_ret;
+
+	mono_once(&spin_once, spin_init);
+
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
+
+	(*dest)++;
+	ret= *dest;
+
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
+
+	pthread_cleanup_pop (0);
+
+	return(ret);
+}
+
 gint32 InterlockedDecrement(volatile gint32 *dest)
 {
 	gint32 ret;
@@ -128,6 +197,29 @@ gint32 InterlockedDecrement(volatile gint32 *dest)
 	return(ret);
 }
 
+gint64 InterlockedDecrement64(volatile gint64 *dest)
+{
+	gint64 ret;
+	int thr_ret;
+
+	mono_once(&spin_once, spin_init);
+
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
+
+	(*dest)--;
+	ret= *dest;
+
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
+
+	pthread_cleanup_pop (0);
+
+	return(ret);
+}
+
 gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch)
 {
 	gint32 ret;
@@ -151,6 +243,29 @@ gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch)
 	return(ret);
 }
 
+gint64 InterlockedExchange64(volatile gint64 *dest, gint64 exch)
+{
+	gint64 ret;
+	int thr_ret;
+
+	mono_once(&spin_once, spin_init);
+
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
+
+	ret=*dest;
+	*dest=exch;
+
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
+
+	pthread_cleanup_pop (0);
+
+	return(ret);
+}
+
 gpointer InterlockedExchangePointer(volatile gpointer *dest, gpointer exch)
 {
 	gpointer ret;
@@ -197,6 +312,29 @@ gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add)
 	return(ret);
 }
 
+gint64 InterlockedExchangeAdd64(volatile gint64 *dest, gint64 add)
+{
+	gint64 ret;
+	int thr_ret;
+	
+	mono_once(&spin_once, spin_init);
+	
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
+
+	ret= *dest;
+	*dest+=add;
+	
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
+
+	pthread_cleanup_pop (0);
+
+	return(ret);
+}
+
 #define NEED_64BIT_CMPXCHG_FALLBACK
 
 #endif

Modified: mono/utils/atomic.h
===================================================================
@@ -45,6 +45,11 @@ static inline gpointer InterlockedCompareExchangePointer(volatile gpointer *dest
 	return __sync_val_compare_and_swap (dest, comp, exch);
 }
 
+static inline gint32 InterlockedAdd(volatile gint32 *dest, gint32 add)
+{
+	return __sync_add_and_fetch (dest, add);
+}
+
 static inline gint32 InterlockedIncrement(volatile gint32 *val)
 {
 	return __sync_add_and_fetch (val, 1);
@@ -90,8 +95,99 @@ static inline gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64
 	return __sync_val_compare_and_swap (dest, comp, exch);
 }
 
+static inline gint64 InterlockedAdd64(volatile gint64 *dest, gint64 add)
+{
+	return __sync_add_and_fetch (dest, add);
+}
+
+static inline gint64 InterlockedIncrement64(volatile gint64 *val)
+{
+	return __sync_add_and_fetch (val, 1);
+}
+
+static inline gint64 InterlockedDecrement64(volatile gint64 *val)
+{
+	return __sync_sub_and_fetch (val, 1);
+}
+
+static inline gint64 InterlockedExchangeAdd64(volatile gint64 *val, gint64 add)
+{
+	return __sync_fetch_and_add (val, add);
+}
+
+#else
+
+/* Implement 64-bit cmpxchg by hand or emulate it. */
+extern gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp);
+
+/* Implement all other 64-bit atomics in terms of a specialized CAS
+ * in this case, since chances are that the other 64-bit atomic
+ * intrinsics are broken too.
+ */
+
+static inline gint64 InterlockedExchangeAdd64(volatile gint64 *dest, gint64 add)
+{
+	gint64 old_val;
+	do {
+		old_val = *dest;
+	} while (InterlockedCompareExchange64 (dest, old_val + add, old_val) != old_val);
+	return old_val;
+}
+
+static inline gint64 InterlockedIncrement64(volatile gint64 *val)
+{
+	gint64 get, set;
+	do {
+		get = *val;
+		set = get + 1;
+	} while (InterlockedCompareExchange64 (val, set, get) != set);
+	return set;
+}
+
+static inline gint64 InterlockedDecrement64(volatile gint64 *val)
+{
+	gint64 get, set;
+	do {
+		get = *val;
+		set = get - 1;
+	} while (InterlockedCompareExchange64 (val, set, get) != set);
+	return set;
+}
+
+static inline gint64 InterlockedAdd64(volatile gint64 *dest, gint64 add)
+{
+	gint64 get, set;
+	do {
+		get = *dest;
+		set = get + add;
+	} while (InterlockedCompareExchange64 (dest, set, get) != set);
+	return set;
+}
+
+static inline gint64 InterlockedRead64(volatile gint64 *src)
+{
+	return InterlockedCompareExchange64 (src, 0, 0);
+}
+
 #endif
 
+/* We always implement this in terms of a 64-bit cmpxchg since
+ * GCC doesn't have an intrisic to model it anyway. */
+static inline gint64 InterlockedExchange64(volatile gint64 *val, gint64 new_val)
+{
+	gint64 old_val;
+	do {
+		old_val = *val;
+	} while (InterlockedCompareExchange64 (val, new_val, old_val) != old_val);
+	return old_val;
+}
+
+static inline void InterlockedWrite64(volatile gint64 *dst, gint64 val)
+{
+	/* Nothing useful from GCC at all, so fall back to CAS. */
+	InterlockedExchange64 (dst, val);
+}
+
 #elif (defined(sparc) || defined (__sparc__)) && defined(__GNUC__)
 
 G_GNUC_UNUSED 
@@ -373,18 +469,19 @@ static inline gint32 InterlockedExchangeAdd(gint32 volatile *val, gint32 add)
 #define WAPI_NO_ATOMIC_ASM
 
 extern gint32 InterlockedCompareExchange(volatile gint32 *dest, gint32 exch, gint32 comp);
+extern gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp);
 extern gpointer InterlockedCompareExchangePointer(volatile gpointer *dest, gpointer exch, gpointer comp);
+extern gint32 InterlockedAdd(volatile gint32 *dest, gint32 add);
+extern gint64 InterlockedAdd64(volatile gint64 *dest, gint64 add);
 extern gint32 InterlockedIncrement(volatile gint32 *dest);
+extern gint64 InterlockedIncrement64(volatile gint64 *dest);
 extern gint32 InterlockedDecrement(volatile gint32 *dest);
+extern gint64 InterlockedDecrement64(volatile gint64 *dest);
 extern gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch);
+extern gint64 InterlockedExchange64(volatile gint64 *dest, gint64 exch);
 extern gpointer InterlockedExchangePointer(volatile gpointer *dest, gpointer exch);
 extern gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add);
-
-#endif
-
-#if defined (WAPI_NO_ATOMIC_ASM) || defined (BROKEN_64BIT_ATOMICS_INTRINSIC)
-
-extern gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp);
+extern gint64 InterlockedExchangeAdd64(volatile gint64 *dest, gint64 add);
 
 #endif
 

   Commit: a92cfede81a7d91a699cab0ee325517c2415b6a7
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 15:59:25 GMT
      URL: https://github.com/mono/mono/commit/a92cfede81a7d91a699cab0ee325517c2415b6a7

Add interlocked read/write functions to atomic.c/.h.

These are guaranteed to have sequential consistency regardless
of the bitness of the machine they run on.

Changed paths:
  M mono/utils/atomic.c
  M mono/utils/atomic.h

Modified: mono/utils/atomic.c
===================================================================
@@ -335,6 +335,88 @@ gint64 InterlockedExchangeAdd64(volatile gint64 *dest, gint64 add)
 	return(ret);
 }
 
+gint32 InterlockedRead(volatile gint32 *src)
+{
+	gint32 ret;
+	int thr_ret;
+	
+	mono_once(&spin_once, spin_init);
+	
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
+
+	ret= *src;
+	
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
+
+	pthread_cleanup_pop (0);
+
+	return(ret);
+}
+
+gint64 InterlockedRead64(volatile gint64 *src)
+{
+	gint64 ret;
+	int thr_ret;
+	
+	mono_once(&spin_once, spin_init);
+	
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
+
+	ret= *src;
+	
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
+
+	pthread_cleanup_pop (0);
+
+	return(ret);
+}
+
+void InterlockedWrite(volatile gint32 *dst, gint32 val)
+{
+	int thr_ret;
+	
+	mono_once(&spin_once, spin_init);
+	
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
+
+	*dst=val;
+	
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
+	
+	pthread_cleanup_pop (0);
+}
+
+void InterlockedWrite64(volatile gint64 *dst, gint64 val)
+{
+	int thr_ret;
+	
+	mono_once(&spin_once, spin_init);
+	
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
+
+	*dst=val;
+	
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
+	
+	pthread_cleanup_pop (0);
+}
+ 
 #define NEED_64BIT_CMPXCHG_FALLBACK
 
 #endif

Modified: mono/utils/atomic.h
===================================================================
@@ -31,6 +31,30 @@ static inline gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64
 }
 #endif
 
+/* And now for some dirty hacks... The Windows API doesn't
+ * provide any useful primitives for this (other than getting
+ * into architecture-specific madness), so use CAS. */
+
+static inline gint32 InterlockedRead(volatile gint32 *src)
+{
+	return InterlockedCompareExchange (src, 0, 0);
+}
+
+static inline gint64 InterlockedRead64(volatile gint64 *src)
+{
+	return InterlockedCompareExchange64 (src, 0, 0);
+}
+
+static inline void InterlockedWrite(volatile gint32 *dst, gint32 val)
+{
+	InterlockedExchange (dst, val);
+}
+
+static inline void InterlockedWrite64(volatile gint64 *dst, gint64 val)
+{
+	InterlockedExchange64 (dst, val);
+}
+
 /* Prefer GCC atomic ops if the target supports it (see configure.in). */
 #elif defined(USE_GCC_ATOMIC_OPS)
 
@@ -84,6 +108,19 @@ static inline gint32 InterlockedExchangeAdd(volatile gint32 *val, gint32 add)
 	return __sync_fetch_and_add (val, add);
 }
 
+static inline gint32 InterlockedRead(volatile gint32 *src)
+{
+	/* Kind of a hack, but GCC doesn't give us anything better, and it's
+	   certainly not as bad as using a CAS loop. */
+	return __sync_fetch_and_add (src, 0);
+}
+
+static inline void InterlockedWrite(volatile gint32 *dst, gint32 val)
+{
+	/* Nothing useful from GCC at all, so fall back to CAS. */
+	InterlockedExchange (dst, val);
+}
+
 #if defined (TARGET_OSX)
 #define BROKEN_64BIT_ATOMICS_INTRINSIC 1
 #endif
@@ -115,6 +152,12 @@ static inline gint64 InterlockedExchangeAdd64(volatile gint64 *val, gint64 add)
 	return __sync_fetch_and_add (val, add);
 }
 
+static inline gint64 InterlockedRead64(volatile gint64 *src)
+{
+	/* Kind of a hack, but GCC doesn't give us anything better. */
+	return __sync_fetch_and_add (src, 0);
+}
+
 #else
 
 /* Implement 64-bit cmpxchg by hand or emulate it. */
@@ -482,6 +525,10 @@ static inline gint32 InterlockedExchangeAdd(gint32 volatile *val, gint32 add)
 extern gpointer InterlockedExchangePointer(volatile gpointer *dest, gpointer exch);
 extern gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add);
 extern gint64 InterlockedExchangeAdd64(volatile gint64 *dest, gint64 add);
+extern gint32 InterlockedRead(volatile gint32 *src);
+extern gint64 InterlockedRead64(volatile gint64 *src);
+extern void InterlockedWrite(volatile gint32 *dst, gint32 val);
+extern void InterlockedWrite64(volatile gint64 *dst, gint64 val);
 
 #endif
 

   Commit: e48f61dc843526bae70b9ff3bd5edae67ce97a77
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 15:59:26 GMT
      URL: https://github.com/mono/mono/commit/e48f61dc843526bae70b9ff3bd5edae67ce97a77

Move definition of NEED_64BIT_CMPXCHG_FALLBACK to top of atomic.c.

Changed paths:
  M mono/utils/atomic.c

Modified: mono/utils/atomic.c
===================================================================
@@ -19,6 +19,8 @@
 
 static pthread_mutex_t spin = PTHREAD_MUTEX_INITIALIZER;
 
+#define NEED_64BIT_CMPXCHG_FALLBACK
+
 #endif
 
 #ifdef WAPI_NO_ATOMIC_ASM
@@ -416,8 +418,6 @@ void InterlockedWrite64(volatile gint64 *dst, gint64 val)
 	
 	pthread_cleanup_pop (0);
 }
- 
-#define NEED_64BIT_CMPXCHG_FALLBACK
 
 #endif
 
@@ -433,8 +433,6 @@ void InterlockedWrite64(volatile gint64 *dst, gint64 val)
 
 #else
 
-#define NEED_64BIT_CMPXCHG_FALLBACK
-
 #endif
 
 #endif

   Commit: e02b11b7081a3dcd02d4b6b01e6e0f92d46b7cb6
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 15:59:26 GMT
      URL: https://github.com/mono/mono/commit/e02b11b7081a3dcd02d4b6b01e6e0f92d46b7cb6

Use __sync_sub_and_fetch () for atomic decrements for clarity.

Changed paths:
  M mono/utils/atomic.h

Modified: mono/utils/atomic.h
===================================================================
@@ -81,7 +81,7 @@ static inline gint32 InterlockedIncrement(volatile gint32 *val)
 
 static inline gint32 InterlockedDecrement(volatile gint32 *val)
 {
-	return __sync_add_and_fetch (val, -1);
+	return __sync_sub_and_fetch (val, 1);
 }
 
 static inline gint32 InterlockedExchange(volatile gint32 *val, gint32 new_val)

   Commit: ab90040305d003b6c06c842e788e682495117514
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 15:59:27 GMT
      URL: https://github.com/mono/mono/commit/ab90040305d003b6c06c842e788e682495117514

Use InterlockedRead64 () for Interlocked.Read (long&).

Changed paths:
  M mono/metadata/threads.c

Modified: mono/metadata/threads.c
===================================================================
@@ -2023,18 +2023,7 @@ gfloat ves_icall_System_Threading_Interlocked_CompareExchange_Single (gfloat *lo
 gint64 
 ves_icall_System_Threading_Interlocked_Read_Long (gint64 *location)
 {
-#if SIZEOF_VOID_P == 8
-	/* 64 bit reads are already atomic */
-	return *location;
-#else
-	gint64 res;
-
-	mono_interlocked_lock ();
-	res = *location;
-	mono_interlocked_unlock ();
-
-	return res;
-#endif
+	return InterlockedRead64 (location);
 }
 
 void

   Commit: bb62cced7ef4145ad1feb5c1acdc5c324ce1ec23
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 15:59:27 GMT
      URL: https://github.com/mono/mono/commit/bb62cced7ef4145ad1feb5c1acdc5c324ce1ec23

Use InterlockedIncrement64 () for Interlocked.Increment (long&).

Changed paths:
  M mono/metadata/threads.c

Modified: mono/metadata/threads.c
===================================================================
@@ -1789,16 +1789,7 @@ gint32 ves_icall_System_Threading_Interlocked_Increment_Int (gint32 *location)
 
 gint64 ves_icall_System_Threading_Interlocked_Increment_Long (gint64 *location)
 {
-	gint64 ret;
-
-	mono_interlocked_lock ();
-
-	ret = ++ *location;
-	
-	mono_interlocked_unlock ();
-
-	
-	return ret;
+	return InterlockedIncrement64 (location);
 }
 
 gint32 ves_icall_System_Threading_Interlocked_Decrement_Int (gint32 *location)

   Commit: 15f9be5d0367b5d5ee168b038878d098ee51d5aa
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 15:59:28 GMT
      URL: https://github.com/mono/mono/commit/15f9be5d0367b5d5ee168b038878d098ee51d5aa

Use InterlockedDecrement64 () for Interlocked.Decrement (long&).

Changed paths:
  M mono/metadata/threads.c

Modified: mono/metadata/threads.c
===================================================================
@@ -1799,15 +1799,7 @@ gint32 ves_icall_System_Threading_Interlocked_Decrement_Int (gint32 *location)
 
 gint64 ves_icall_System_Threading_Interlocked_Decrement_Long (gint64 * location)
 {
-	gint64 ret;
-
-	mono_interlocked_lock ();
-
-	ret = -- *location;
-	
-	mono_interlocked_unlock ();
-
-	return ret;
+	return InterlockedDecrement64 (location);
 }
 
 gint32 ves_icall_System_Threading_Interlocked_Exchange_Int (gint32 *location, gint32 value)

   Commit: b9db6c2071f2c2cfa36cc32a0150eacdff586376
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 15:59:28 GMT
      URL: https://github.com/mono/mono/commit/b9db6c2071f2c2cfa36cc32a0150eacdff586376

Use InterlockedExchange64 () for Interlocked.Exchange (long&, long).

Changed paths:
  M mono/metadata/threads.c

Modified: mono/metadata/threads.c
===================================================================
@@ -1833,22 +1833,7 @@ gfloat ves_icall_System_Threading_Interlocked_Exchange_Single (gfloat *location,
 gint64 
 ves_icall_System_Threading_Interlocked_Exchange_Long (gint64 *location, gint64 value)
 {
-#if SIZEOF_VOID_P == 8
-	return (gint64) InterlockedExchangePointer((gpointer *) location, (gpointer)value);
-#else
-	gint64 res;
-
-	/* 
-	 * According to MSDN, this function is only atomic with regards to the 
-	 * other Interlocked functions on 32 bit platforms.
-	 */
-	mono_interlocked_lock ();
-	res = *location;
-	*location = value;
-	mono_interlocked_unlock ();
-
-	return res;
-#endif
+	return InterlockedExchange64 (location, value);
 }
 
 gdouble 

   Commit: d785b33891091153ced9e632129badc7262efca9
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 15:59:28 GMT
      URL: https://github.com/mono/mono/commit/d785b33891091153ced9e632129badc7262efca9

Use InterlockedExchange64 () for Interlocked.Exchange (double&, double).

Changed paths:
  M mono/metadata/threads.c

Modified: mono/metadata/threads.c
===================================================================
@@ -1839,27 +1839,12 @@ gfloat ves_icall_System_Threading_Interlocked_Exchange_Single (gfloat *location,
 gdouble 
 ves_icall_System_Threading_Interlocked_Exchange_Double (gdouble *location, gdouble value)
 {
-#if SIZEOF_VOID_P == 8
 	LongDoubleUnion val, ret;
 
 	val.fval = value;
-	ret.ival = (gint64)InterlockedExchangePointer((gpointer *) location, (gpointer)val.ival);
+	ret.ival = (gint64)InterlockedExchange64((gint64 *) location, val.ival);
 
 	return ret.fval;
-#else
-	gdouble res;
-
-	/* 
-	 * According to MSDN, this function is only atomic with regards to the 
-	 * other Interlocked functions on 32 bit platforms.
-	 */
-	mono_interlocked_lock ();
-	res = *location;
-	*location = value;
-	mono_interlocked_unlock ();
-
-	return res;
-#endif
 }
 
 gint32 ves_icall_System_Threading_Interlocked_CompareExchange_Int(gint32 *location, gint32 value, gint32 comparand)

   Commit: 89a99c26341d0c09e30fb263c5a08fe80aa21369
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 15:59:29 GMT
      URL: https://github.com/mono/mono/commit/89a99c26341d0c09e30fb263c5a08fe80aa21369

Use InterlockedAdd () for Interlocked.Add (int&, int).

Changed paths:
  M mono/metadata/threads.c

Modified: mono/metadata/threads.c
===================================================================
@@ -1943,14 +1943,7 @@ gfloat ves_icall_System_Threading_Interlocked_CompareExchange_Single (gfloat *lo
 	mono_raise_exception (mono_get_exception_not_implemented (NULL));
 	return 0;
 #else
-	gint32 orig;
-
-	mono_interlocked_lock ();
-	orig = *location;
-	*location = orig + value;
-	mono_interlocked_unlock ();
-
-	return orig + value;
+	return InterlockedAdd (location, value);
 #endif
 }
 

   Commit: 421e1beea55d26d767dbd857e2f2276e3c6c2bee
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 15:59:29 GMT
      URL: https://github.com/mono/mono/commit/421e1beea55d26d767dbd857e2f2276e3c6c2bee

Use InterlockedAdd64 () for Interlocked.Add (long&, long).

Changed paths:
  M mono/metadata/threads.c

Modified: mono/metadata/threads.c
===================================================================
@@ -1955,14 +1955,7 @@ gfloat ves_icall_System_Threading_Interlocked_CompareExchange_Single (gfloat *lo
 	mono_raise_exception (mono_get_exception_not_implemented (NULL));
 	return 0;
 #else
-	gint64 orig;
-
-	mono_interlocked_lock ();
-	orig = *location;
-	*location = orig + value;
-	mono_interlocked_unlock ();
-
-	return orig + value;
+	return InterlockedAdd64 (location, value);
 #endif
 }
 

   Commit: 53398c4641b2dc2f55d577778b13cca8ef223b40
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 15:59:30 GMT
      URL: https://github.com/mono/mono/commit/53398c4641b2dc2f55d577778b13cca8ef223b40

Correct our implementation of Thread.VolatileRead ()/VolatileWrite ().

We have various issues:

* All of the functions assumed that doing volatile loads/stores was
  enough, when load-acquire, store-release semantics were actually
  needed. This may have worked before purely by chance. We now use
  proper memory barriers so that we don't have to hope for the
  compiler and CPU to do the right thing.
* Removes the hack for 64-bit quantities on 32-bit systems. This is
  no longer needed now that we use explicit memory barriers in
  these functions. Also, these functions are not supposed to do
  atomic reads/writes in the first place - they're purely about the
  memory barrier semantics.
* The VolatileWrite (object&, object) overload was not using the
  volatile qualifier at all, thus not getting volatile semantics
  as per: http://gcc.gnu.org/onlinedocs/gcc/Volatiles.html

Changed paths:
  M mono/metadata/threads.c

Modified: mono/metadata/threads.c
===================================================================
@@ -48,6 +48,7 @@
 #include <mono/utils/hazard-pointer.h>
 #include <mono/utils/mono-tls.h>
 #include <mono/utils/atomic.h>
+#include <mono/utils/mono-memory-model.h>
 
 #include <mono/metadata/gc-internal.h>
 
@@ -2395,114 +2396,120 @@ void mono_thread_stop (MonoThread *thread)
 gint8
 ves_icall_System_Threading_Thread_VolatileRead1 (void *ptr)
 {
-	return *((volatile gint8 *) (ptr));
+	gint8 tmp;
+	mono_atomic_load_acquire (tmp, gint8, (volatile gint8 *) ptr);
+	return tmp;
 }
 
 gint16
 ves_icall_System_Threading_Thread_VolatileRead2 (void *ptr)
 {
-	return *((volatile gint16 *) (ptr));
+	gint16 tmp;
+	mono_atomic_load_acquire (tmp, gint16, (volatile gint16 *) ptr);
+	return tmp;
 }
 
 gint32
 ves_icall_System_Threading_Thread_VolatileRead4 (void *ptr)
 {
-	return *((volatile gint32 *) (ptr));
+	gint32 tmp;
+	mono_atomic_load_acquire (tmp, gint32, (volatile gint32 *) ptr);
+	return tmp;
 }
 
 gint64
 ves_icall_System_Threading_Thread_VolatileRead8 (void *ptr)
 {
-#if SIZEOF_VOID_P == 8
-	return *((volatile gint64 *) (ptr));
-#else
-	if ((size_t)ptr & 0x7) {
-		gint64 value;
-		mono_interlocked_lock ();
-		value = *(gint64 *)ptr;
-		mono_interlocked_unlock ();
-		return value;
-	}
-	return InterlockedCompareExchange64 (ptr, 0, 0); /*Must ensure atomicity of the operation. */
-#endif
+	gint64 tmp;
+	mono_atomic_load_acquire (tmp, gint64, (volatile gint64 *) ptr);
+	return tmp;
 }
 
 void *
 ves_icall_System_Threading_Thread_VolatileReadIntPtr (void *ptr)
 {
-	return (void *)  *((volatile void **) ptr);
+	volatile void *tmp;
+	mono_atomic_load_acquire (tmp, volatile void *, (volatile void **) ptr);
+	return (void *) tmp;
 }
 
 double
 ves_icall_System_Threading_Thread_VolatileReadDouble (void *ptr)
 {
-	return *((volatile double *) (ptr));
+	double tmp;
+	mono_atomic_load_acquire (tmp, double, (volatile double *) ptr);
+	return tmp;
 }
 
 float
 ves_icall_System_Threading_Thread_VolatileReadFloat (void *ptr)
 {
-	return *((volatile float *) (ptr));
+	float tmp;
+	mono_atomic_load_acquire (tmp, float, (volatile float *) ptr);
+	return tmp;
 }
 
 MonoObject*
 ves_icall_System_Threading_Volatile_Read_T (void *ptr)
 {
-	return (MonoObject*)*((volatile MonoObject**)ptr);
+	volatile MonoObject *tmp;
+	mono_atomic_load_acquire (tmp, volatile MonoObject *, (volatile MonoObject **) ptr);
+	return (MonoObject *) tmp;
 }
 
 void
 ves_icall_System_Threading_Thread_VolatileWrite1 (void *ptr, gint8 value)
 {
-	*((volatile gint8 *) ptr) = value;
+	mono_atomic_store_release ((volatile gint8 *) ptr, value);
 }
 
 void
 ves_icall_System_Threading_Thread_VolatileWrite2 (void *ptr, gint16 value)
 {
-	*((volatile gint16 *) ptr) = value;
+	mono_atomic_store_release ((volatile gint16 *) ptr, value);
 }
 
 void
 ves_icall_System_Threading_Thread_VolatileWrite4 (void *ptr, gint32 value)
 {
-	*((volatile gint32 *) ptr) = value;
+	mono_atomic_store_release ((volatile gint32 *) ptr, value);
 }
 
 void
 ves_icall_System_Threading_Thread_VolatileWrite8 (void *ptr, gint64 value)
 {
-	*((volatile gint64 *) ptr) = value;
+	mono_atomic_store_release ((volatile gint64 *) ptr, value);
 }
 
 void
 ves_icall_System_Threading_Thread_VolatileWriteIntPtr (void *ptr, void *value)
 {
-	*((volatile void **) ptr) = value;
+	mono_atomic_store_release ((volatile void **) ptr, value);
 }
 
 void
 ves_icall_System_Threading_Thread_VolatileWriteObject (void *ptr, void *value)
 {
-	mono_gc_wbarrier_generic_store (ptr, value);
+	mono_atomic_store_release ((volatile MonoObject **) ptr, value);
+	mono_gc_wbarrier_generic_nostore (ptr);
 }
 
 void
 ves_icall_System_Threading_Thread_VolatileWriteDouble (void *ptr, double value)
 {
-	*((volatile double *) ptr) = value;
+	mono_atomic_store_release ((volatile double *) ptr, value);
 }
 
 void
 ves_icall_System_Threading_Thread_VolatileWriteFloat (void *ptr, float value)
 {
-	*((volatile float *) ptr) = value;
+	mono_atomic_store_release ((volatile float *) ptr, value);
 }
 
 void
 ves_icall_System_Threading_Volatile_Write_T (void *ptr, MonoObject *value)
 {
-	*((volatile MonoObject **) ptr) = value;
+	mono_atomic_store_release ((volatile MonoObject **) ptr, value);
 	mono_gc_wbarrier_generic_nostore (ptr);
 }
 

   Commit: 1b9ca03c22742450102f5c9c53eb953365212973
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 16:08:05 GMT
      URL: https://github.com/mono/mono/commit/1b9ca03c22742450102f5c9c53eb953365212973

Use slow 64-bit cmpxchg for 32-bit ARM, MIPS, and PowerPC.

GCC doesn't provide a 64-bit __sync_val_compare_and_swap intrinsic
for these architectures.

Changed paths:
  M mono/utils/atomic.h

Modified: mono/utils/atomic.h
===================================================================
@@ -121,7 +121,7 @@ static inline void InterlockedWrite(volatile gint32 *dst, gint32 val)
 	InterlockedExchange (dst, val);
 }
 
-#if defined (TARGET_OSX)
+#if defined (TARGET_OSX) || defined (__arm__) || (defined (__mips__) && !defined (__mips64)) || (defined (__powerpc__) && !defined (__powerpc64__))
 #define BROKEN_64BIT_ATOMICS_INTRINSIC 1
 #endif
 

   Commit: 55d338134d006f070bb533484337e4c9e485be86
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 16:08:15 GMT
      URL: https://github.com/mono/mono/commit/55d338134d006f070bb533484337e4c9e485be86

Add an extension point in atomic.c.

Changed paths:
  M mono/utils/atomic.c

Modified: mono/utils/atomic.c
===================================================================
@@ -421,7 +421,7 @@ void InterlockedWrite64(volatile gint64 *dst, gint64 val)
 
 #endif
 
-#if defined (BROKEN_64BIT_ATOMICS_INTRINSIC)
+#if defined (NEED_64BIT_CMPXCHG_FALLBACK)
 
 #if defined (TARGET_OSX)
 
@@ -431,13 +431,13 @@ void InterlockedWrite64(volatile gint64 *dst, gint64 val)
 	return __sync_val_compare_and_swap (dest, comp, exch);
 }
 
-#else
-
-#endif
+#elif defined (HAVE_64BIT_CMPXCHG_FALLBACK)
 
+#ifdef ENABLE_EXTENSION_MODULE
+#include "../../../mono-extensions/mono/utils/atomic.c"
 #endif
 
-#if defined (NEED_64BIT_CMPXCHG_FALLBACK)
+#else
 
 gint64
 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)
@@ -455,3 +455,5 @@ void InterlockedWrite64(volatile gint64 *dst, gint64 val)
 }
 
 #endif
+
+#endif

   Commit: e4d2cc49a03b2cb7b31cddfd630e319bc4d344a1
   Author: Alex Rønne Petersen <[email protected]> 
     Date: 2013-10-21 16:08:16 GMT
      URL: https://github.com/mono/mono/commit/e4d2cc49a03b2cb7b31cddfd630e319bc4d344a1

Add mono_gc_wbarrier_generic_store_atomic () function.

This is used in place of mono_gc_wbarrier_generic_store () when
we need the store to be atomic with release semantics.

Changed paths:
  M docs/current-api
  M docs/public-api
  M mono/metadata/boehm-gc.c
  M mono/metadata/null-gc.c
  M mono/metadata/object.h
  M mono/metadata/sgen-gc.c
  M mono/metadata/threads.c
  M msvc/mono.def
  M msvc/monosgen.def

Modified: docs/current-api
===================================================================
@@ -307,6 +307,7 @@ mono_gc_out_of_memory
 mono_gc_wbarrier_arrayref_copy
 mono_gc_wbarrier_generic_nostore
 mono_gc_wbarrier_generic_store
+mono_gc_wbarrier_generic_store_atomic
 mono_gc_wbarrier_object_copy
 mono_gc_wbarrier_set_arrayref
 mono_gc_wbarrier_set_field

Modified: docs/public-api
===================================================================
@@ -307,6 +307,7 @@ mono_gc_out_of_memory
 mono_gc_wbarrier_arrayref_copy
 mono_gc_wbarrier_generic_nostore
 mono_gc_wbarrier_generic_store
+mono_gc_wbarrier_generic_store_atomic
 mono_gc_wbarrier_object_copy
 mono_gc_wbarrier_set_arrayref
 mono_gc_wbarrier_set_field

Modified: mono/metadata/boehm-gc.c
===================================================================
@@ -22,6 +22,7 @@
 #include <mono/metadata/marshal.h>
 #include <mono/metadata/runtime.h>
 #include <mono/utils/mono-logger-internal.h>
+#include <mono/utils/mono-memory-model.h>
 #include <mono/utils/mono-time.h>
 #include <mono/utils/mono-threads.h>
 #include <mono/utils/dtrace.h>
@@ -624,6 +625,12 @@
 }
 
 void
+mono_gc_wbarrier_generic_store_atomic (gpointer ptr, MonoObject *value)
+{
+	mono_atomic_store_release ((volatile MonoObject **) ptr, value);
+}
+
+void
 mono_gc_wbarrier_generic_nostore (gpointer ptr)
 {
 }

Modified: mono/metadata/null-gc.c
===================================================================
@@ -193,6 +193,12 @@
 }
 
 void
+mono_gc_wbarrier_generic_store_atomic (gpointer ptr, MonoObject *value)
+{
+	mono_atomic_store_release ((volatile MonoObject **) ptr, value);
+}
+
+void
 mono_gc_wbarrier_generic_nostore (gpointer ptr)
 {
 }

Modified: mono/metadata/object.h
===================================================================
@@ -316,6 +316,7 @@
 MONO_API void mono_gc_wbarrier_set_arrayref  (MonoArray *arr, void* slot_ptr, MonoObject* value);
 MONO_API void mono_gc_wbarrier_arrayref_copy (void* dest_ptr, void* src_ptr, int count);
 MONO_API void mono_gc_wbarrier_generic_store (void* ptr, MonoObject* value);
+MONO_API void mono_gc_wbarrier_generic_store_atomic (void *ptr, MonoObject *value);
 MONO_API void mono_gc_wbarrier_generic_nostore (void* ptr);
 MONO_API void mono_gc_wbarrier_value_copy    (void* dest, void* src, int count, MonoClass *klass);
 MONO_API void mono_gc_wbarrier_object_copy   (MonoObject* obj, MonoObject *src);

Modified: mono/metadata/sgen-gc.c
===================================================================
@@ -317,6 +317,7 @@ enum {
 static int stat_wbarrier_set_arrayref = 0;
 static int stat_wbarrier_arrayref_copy = 0;
 static int stat_wbarrier_generic_store = 0;
+static int stat_wbarrier_generic_store_atomic = 0;
 static int stat_wbarrier_set_root = 0;
 static int stat_wbarrier_value_copy = 0;
 static int stat_wbarrier_object_copy = 0;
@@ -2234,6 +2235,7 @@ struct _EphemeronLinkNode {
 	mono_counters_register ("WBarrier set arrayref", MONO_COUNTER_GC | MONO_COUNTER_INT, &stat_wbarrier_set_arrayref);
 	mono_counters_register ("WBarrier arrayref copy", MONO_COUNTER_GC | MONO_COUNTER_INT, &stat_wbarrier_arrayref_copy);
 	mono_counters_register ("WBarrier generic store called", MONO_COUNTER_GC | MONO_COUNTER_INT, &stat_wbarrier_generic_store);
+	mono_counters_register ("WBarrier generic atomic store called", MONO_COUNTER_GC | MONO_COUNTER_INT, &stat_wbarrier_generic_store_atomic);
 	mono_counters_register ("WBarrier set root", MONO_COUNTER_GC | MONO_COUNTER_INT, &stat_wbarrier_set_root);
 	mono_counters_register ("WBarrier value copy", MONO_COUNTER_GC | MONO_COUNTER_INT, &stat_wbarrier_value_copy);
 	mono_counters_register ("WBarrier object copy", MONO_COUNTER_GC | MONO_COUNTER_INT, &stat_wbarrier_object_copy);
@@ -4388,6 +4390,24 @@ struct _EphemeronLinkNode {
 	sgen_dummy_use (value);
 }
 
+/* Same as mono_gc_wbarrier_generic_store () but performs the store
+ * as an atomic operation with release semantics.
+ */
+void
+mono_gc_wbarrier_generic_store_atomic (gpointer ptr, MonoObject *value)
+{
+	HEAVY_STAT (++stat_wbarrier_generic_store_atomic);
+
+	SGEN_LOG (8, "Wbarrier atomic store at %p to %p (%s)", ptr, value, value ? safe_name (value) : "null");
+
+	mono_atomic_store_release ((volatile MonoObject **) ptr, value);
+
+	if (ptr_in_nursery (value))
+		mono_gc_wbarrier_generic_nostore (ptr);
+
+	sgen_dummy_use (value);
+}
+
 void mono_gc_wbarrier_value_copy_bitmap (gpointer _dest, gpointer _src, int size, unsigned bitmap)
 {
 	mword *dest = _dest;

Modified: mono/metadata/threads.c
===================================================================
@@ -2490,8 +2490,7 @@ void mono_thread_stop (MonoThread *thread)
 void
 ves_icall_System_Threading_Thread_VolatileWriteObject (void *ptr, void *value)
 {
-	mono_atomic_store_release ((volatile MonoObject **) ptr, value);
-	mono_gc_wbarrier_generic_nostore (ptr);
+	mono_gc_wbarrier_generic_store_atomic (ptr, value);
 }
 
 void
@@ -2509,8 +2508,7 @@ void mono_thread_stop (MonoThread *thread)
 void
 ves_icall_System_Threading_Volatile_Write_T (void *ptr, MonoObject *value)
 {
-	mono_atomic_store_release ((volatile MonoObject **) ptr, value);
-	mono_gc_wbarrier_generic_nostore (ptr);
+	mono_gc_wbarrier_generic_store_atomic (ptr, value);
 }
 
 void

Modified: msvc/mono.def
===================================================================
@@ -331,6 +331,7 @@ mono_gc_walk_heap
 mono_gc_wbarrier_arrayref_copy
 mono_gc_wbarrier_generic_nostore
 mono_gc_wbarrier_generic_store
+mono_gc_wbarrier_generic_store_atomic
 mono_gc_wbarrier_object_copy
 mono_gc_wbarrier_set_arrayref
 mono_gc_wbarrier_set_field

Modified: msvc/monosgen.def
===================================================================
@@ -331,6 +331,7 @@ mono_gc_walk_heap
 mono_gc_wbarrier_arrayref_copy
 mono_gc_wbarrier_generic_nostore
 mono_gc_wbarrier_generic_store
+mono_gc_wbarrier_generic_store_atomic
 mono_gc_wbarrier_object_copy
 mono_gc_wbarrier_set_arrayref
 mono_gc_wbarrier_set_field
_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.