[Pkg-mono-svn-commits] [mono] 09/23: Add interlocked read/write functions to atomic.c/.h.

Jo Shields directhex at alioth.debian.org
Wed Oct 23 22:14:30 UTC 2013


This is an automated email from the git hooks/post-receive script.

directhex pushed a commit to branch master-experimental-patches/atomics_support_on_fringe_32bit_platforms
in repository mono.

commit b37681e25ce03a65caca92ae299664c7c1621572
Author: Alex Rønne Petersen <alexrp at xamarin.com>
Date:   Wed Sep 25 19:59:37 2013 +0200

    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.
    (cherry picked from commit a92cfede81a7d91a699cab0ee325517c2415b6a7)
---
 mono/utils/atomic.c |   82 +++++++++++++++++++++++++++++++++++++++++++++++++++
 mono/utils/atomic.h |   47 +++++++++++++++++++++++++++++
 2 files changed, 129 insertions(+)

diff --git a/mono/utils/atomic.c b/mono/utils/atomic.c
index b0b3bf7..e8388b9 100755
--- a/mono/utils/atomic.c
+++ b/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
diff --git a/mono/utils/atomic.h b/mono/utils/atomic.h
index 7da7d51..95fd771 100755
--- a/mono/utils/atomic.h
+++ b/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 @@ extern gint64 InterlockedExchange64(volatile gint64 *dest, gint64 exch);
 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
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mono/packages/mono.git



More information about the Pkg-mono-svn-commits mailing list