[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