diff --git a/src/configure b/src/configure index 03b7ed65da..79e2020b01 100755 --- a/src/configure +++ b/src/configure @@ -8291,6 +8291,77 @@ _ACEOF enable_mzrt=yes fi +############## compare-and-swap ################ + +if test "${enable_mzrt}" = "yes" ; then + msg="for compare-and-swap" + { echo "$as_me:$LINENO: checking $msg" >&5 +echo $ECHO_N "checking $msg... $ECHO_C" >&6; } + if test "$cross_compiling" = yes; then + cas_available=no +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +int check1(long *addr, long old, long new_val) { + return __sync_bool_compare_and_swap(addr, old, new_val); + } + int check2(short *addr, short old, short new_val) { + return __sync_bool_compare_and_swap(addr, old, new_val); + } + int main() { + long l = 2; short s = 3; + return !check1(&l, 2, 4) || !check2(&s, 3, 6); + } +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cas_available=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +cas_available=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + { echo "$as_me:$LINENO: result: $cas_available" >&5 +echo "${ECHO_T}$cas_available" >&6; } + if test "${cas_available}" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define MZ_CAS_AVAILABLE 1 +_ACEOF + + fi +fi + + ############### OS threads ################### if test "${enable_mzrt}" = "yes" ; then diff --git a/src/racket/configure.ac b/src/racket/configure.ac index 02d5a372d1..0b774b9cb2 100644 --- a/src/racket/configure.ac +++ b/src/racket/configure.ac @@ -937,6 +937,29 @@ if test "${enable_futures}" = "yes" ; then enable_mzrt=yes fi +############## compare-and-swap ################ + +if test "${enable_mzrt}" = "yes" ; then + [ msg="for compare-and-swap" ] + AC_MSG_CHECKING($msg) + AC_TRY_RUN( + int check1(long *addr, long old, long new_val) { + return __sync_bool_compare_and_swap(addr, old, new_val); + } + int check2(short *addr, short old, short new_val) { + return __sync_bool_compare_and_swap(addr, old, new_val); + } + int main() { + long l = 2; short s = 3; + return !check1(&l, 2, 4) || !check2(&s, 3, 6); + }, cas_available=yes, cas_available=no, cas_available=no) + AC_MSG_RESULT($cas_available) + if test "${cas_available}" = "yes" ; then + AC_DEFINE(MZ_CAS_AVAILABLE,1,[Compare-and-swap available]) + fi +fi + + ############### OS threads ################### if test "${enable_mzrt}" = "yes" ; then diff --git a/src/racket/mzconfig.h.in b/src/racket/mzconfig.h.in index 4ccbb6877c..43f546d093 100644 --- a/src/racket/mzconfig.h.in +++ b/src/racket/mzconfig.h.in @@ -64,6 +64,9 @@ typedef unsigned long uintptr_t; #undef MZ_USE_PLACES #endif +/* Whether __sync_bool_compare_and_swap() works: */ +#undef MZ_CAS_AVAILABLE + /* Configure use of pthreads for the user-thread timer. */ #undef USE_PTHREAD_INSTEAD_OF_ITIMER diff --git a/src/racket/src/mzrt_cas.inc b/src/racket/src/mzrt_cas.inc index cc964f6722..af2835d06c 100644 --- a/src/racket/src/mzrt_cas.inc +++ b/src/racket/src/mzrt_cas.inc @@ -1,7 +1,9 @@ XFORM_NONGCING static MZ_INLINE int mz_MZRT_CAS(volatile mz_CAS_T *addr, mz_CAS_T old, mz_CAS_T new_val) XFORM_SKIP_PROC { -#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && ((__GNUC__ <= 3) || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)) +#ifdef MZ_CAS_AVAILABLE + return __sync_bool_compare_and_swap(addr, old, new_val); +#elif defined(__GNUC__) # if defined(__i386__) || defined(__x86_64__) # ifdef mz_CAS_64 # define CAS_I_SIZE "q" @@ -47,8 +49,6 @@ XFORM_NONGCING static MZ_INLINE int mz_MZRT_CAS(volatile mz_CAS_T *addr, mz_CAS_ # error mzrt_cas not defined on this platform # endif -#elif defined(__GNUC__) && !defined(__INTEL_COMPILER) - return __sync_bool_compare_and_swap(addr, old, new_val); #elif defined(_MSC_VER) # ifdef mz_CAS_64 return _InterlockedCompareExchange64((__int64 *)addr, (__int64)new_val, (__int64)old) == (__int64)old;