summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libgo/config.h.in4
-rw-r--r--libgo/configure29
-rw-r--r--libgo/configure.ac14
-rw-r--r--libgo/runtime/go-semacquire.c32
4 files changed, 79 insertions, 0 deletions
diff --git a/libgo/config.h.in b/libgo/config.h.in
index 22d6f721e2d..18a51cc8f02 100644
--- a/libgo/config.h.in
+++ b/libgo/config.h.in
@@ -43,6 +43,10 @@
function for uint32 */
#undef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4
+/* Define to 1 if the compiler provides the __sync_fetch_and_add function for
+ uint32 */
+#undef HAVE_SYNC_FETCH_AND_ADD_4
+
/* Define to 1 if you have the <syscall.h> header file. */
#undef HAVE_SYSCALL_H
diff --git a/libgo/configure b/libgo/configure
index ddb61c00262..fbaac8e3d61 100644
--- a/libgo/configure
+++ b/libgo/configure
@@ -14206,6 +14206,35 @@ $as_echo "#define HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4 1" >>confdefs.h
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __sync_fetch_and_add_4" >&5
+$as_echo_n "checking for __sync_fetch_and_add_4... " >&6; }
+if test "${libgo_cv_func___sync_fetch_and_add_4+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+typedef unsigned int uint32 __attribute__ ((mode (SI)));
+uint32 i;
+int main() { return __sync_fetch_and_add (&i, 1); }
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ libgo_cv_func___sync_fetch_and_add_4=yes
+else
+ libgo_cv_func___sync_fetch_and_add_4=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_func___sync_fetch_and_add_4" >&5
+$as_echo "$libgo_cv_func___sync_fetch_and_add_4" >&6; }
+if test "$libgo_cv_func___sync_fetch_and_add_4" = "yes"; then
+
+$as_echo "#define HAVE_SYNC_FETCH_AND_ADD_4 1" >>confdefs.h
+
+fi
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -minline-all-stringops" >&5
$as_echo_n "checking whether compiler supports -minline-all-stringops... " >&6; }
if test "${libgo_cv_c_stringops+set}" = set; then :
diff --git a/libgo/configure.ac b/libgo/configure.ac
index 1c75b3ef6d2..da56610b579 100644
--- a/libgo/configure.ac
+++ b/libgo/configure.ac
@@ -396,6 +396,20 @@ if test "$libgo_cv_func___sync_bool_compare_and_swap_4" = "yes"; then
[Define to 1 if the compiler provides the __sync_bool_compare_and_swap function for uint32])
fi
+AC_CACHE_CHECK([for __sync_fetch_and_add_4],
+[libgo_cv_func___sync_fetch_and_add_4],
+[AC_LINK_IFELSE([
+typedef unsigned int uint32 __attribute__ ((mode (SI)));
+uint32 i;
+int main() { return __sync_fetch_and_add (&i, 1); }
+],
+[libgo_cv_func___sync_fetch_and_add_4=yes],
+[libgo_cv_func___sync_fetch_and_add_4=no])])
+if test "$libgo_cv_func___sync_fetch_and_add_4" = "yes"; then
+ AC_DEFINE(HAVE_SYNC_FETCH_AND_ADD_4, 1,
+ [Define to 1 if the compiler provides the __sync_fetch_and_add function for uint32])
+fi
+
dnl For x86 we want to use the -minline-all-stringops option to avoid
dnl forcing a stack split when calling memcpy and friends.
AC_CACHE_CHECK([whether compiler supports -minline-all-stringops],
diff --git a/libgo/runtime/go-semacquire.c b/libgo/runtime/go-semacquire.c
index 67a86ef695f..24c6a7388f6 100644
--- a/libgo/runtime/go-semacquire.c
+++ b/libgo/runtime/go-semacquire.c
@@ -117,3 +117,35 @@ semrelease (uint32 *addr)
__go_assert (i == 0);
}
}
+
+
+#ifndef HAVE_SYNC_FETCH_AND_ADD_4
+
+/* For targets which don't have the required sync support. Really
+ this should be provided by gcc itself. FIXME. */
+
+static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER;
+
+uint32
+__sync_fetch_and_add_4(uint32*, uint32)
+ __attribute__((visibility("hidden")));
+
+uint32
+__sync_fetch_and_add_4(uint32* ptr, uint32 add)
+{
+ int i;
+ uint32 ret;
+
+ i = pthread_mutex_lock(&sync_lock);
+ __go_assert(i == 0);
+
+ ret = *ptr;
+ *ptr += add;
+
+ i = pthread_mutex_unlock(&sync_lock);
+ __go_assert(i == 0);
+
+ return ret;
+}
+
+#endif