@@ -13,7 +13,7 @@ dnl Copyright (c) 2008-2018 Cisco Systems, Inc. All rights reserved.
1313dnl Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved.
1414dnl Copyright (c) 2015-2017 Research Organization for Information Science
1515dnl and Technology (RIST). All rights reserved.
16- dnl Copyright (c) 2014-2017 Los Alamos National Security, LLC. All rights
16+ dnl Copyright (c) 2014-2018 Los Alamos National Security, LLC. All rights
1717dnl reserved.
1818dnl Copyright (c) 2017 Amazon.com, Inc. or its affiliates. All Rights
1919dnl reserved.
@@ -122,6 +122,58 @@ int main(int argc, char** argv)
122122}
123123] ] )
124124
125+ dnl This is a C test to see if 128-bit __atomic_compare_exchange_n()
126+ dnl actually works (e.g., it compiles and links successfully on
127+ dnl ARM64+clang, but returns incorrect answers as of August 2018).
128+ AC_DEFUN ( [ OPAL_ATOMIC_COMPARE_EXCHANGE_STRONG_TEST_SOURCE] ,[ [
129+ #include <stdint.h>
130+ #include <stdbool.h>
131+ #include <stdlib.h>
132+ #include <stdatomic.h>
133+
134+ typedef union {
135+ uint64_t fake@<:@ 2@:>@ ;
136+ _Atomic __int128 real;
137+ } ompi128;
138+
139+ static void test1(void)
140+ {
141+ // As of Aug 2018, we could not figure out a way to assign 128-bit
142+ // constants -- the compilers would not accept it. So use a fake
143+ // union to assign 2 uin64_t's to make a single __int128.
144+ ompi128 ptr = { .fake = { 0xFFEEDDCCBBAA0099, 0x8877665544332211 }};
145+ ompi128 expected = { .fake = { 0x11EEDDCCBBAA0099, 0x88776655443322FF }};
146+ ompi128 desired = { .fake = { 0x1122DDCCBBAA0099, 0x887766554433EEFF }};
147+ bool r = atomic_compare_exchange_strong (&ptr.real, &expected.real,
148+ desired.real, true,
149+ atomic_relaxed, atomic_relaxed);
150+ if ( !(r == false && ptr.real == expected.real)) {
151+ exit(1);
152+ }
153+ }
154+
155+ static void test2(void)
156+ {
157+ ompi128 ptr = { .fake = { 0xFFEEDDCCBBAA0099, 0x8877665544332211 }};
158+ ompi128 expected = ptr;
159+ ompi128 desired = { .fake = { 0x1122DDCCBBAA0099, 0x887766554433EEFF }};
160+ bool r = atomic_compare_exchange_strong (&ptr.real, &expected.real,
161+ desired.real, true,
162+ atomic_relaxed, atomic_relaxed);
163+ if (!(r == true && ptr.real == desired.real)) {
164+ exit(2);
165+ }
166+ }
167+
168+ vvvvvvvvvvvvvvvvvvvv
169+ int main(int argc, char** argv)
170+ {
171+ test1();
172+ test2();
173+ return 0;
174+ }
175+ ] ] )
176+
125177dnl ------------------------------------------------------------------
126178
127179dnl
@@ -329,6 +381,71 @@ __atomic_add_fetch(&tmp64, 1, __ATOMIC_RELAXED);],
329381 OPAL_CHECK_GCC_BUILTIN_CSWAP_INT128
330382] )
331383
384+ AC_DEFUN ( [ OPAL_CHECK_C11_CSWAP_INT128] , [
385+ OPAL_VAR_SCOPE_PUSH([ atomic_compare_exchange_result atomic_compare_exchange_CFLAGS_save atomic_compare_exchange_LIBS_save] )
386+
387+ atomic_compare_exchange_CFLAGS_save=$CFLAGS
388+ atomic_compare_exchange_LIBS_save=$LIBS
389+
390+ # Do we have C11 atomics on 128-bit integers?
391+ # Use a special macro because we need to check with a few different
392+ # CFLAGS/LIBS.
393+ OPAL_ASM_CHECK_ATOMIC_FUNC([ atomic_compare_exchange_strong_16] ,
394+ [ AC_LANG_SOURCE ( OPAL_ATOMIC_COMPARE_EXCHANGE_STRONG_TEST_SOURCE ) ] ,
395+ [ atomic_compare_exchange_result=1] ,
396+ [ atomic_compare_exchange_result=0] )
397+
398+ # If we have it and it works, check to make sure it is always lock
399+ # free.
400+ AS_IF ( [ test $atomic_compare_exchange_result -eq 1] ,
401+ [ AC_MSG_CHECKING ( [ if C11 __int128 atomic compare-and-swap is always lock-free] )
402+ AC_RUN_IFELSE ( [ AC_LANG_PROGRAM ( [ #include <stdatomic.h>] , [ _Atomic __int128_t x; if (!atomic_is_lock_free(&x)) { return 1; }] ) ] ,
403+ [ AC_MSG_RESULT ( [ yes] ) ] ,
404+ [ atomic_compare_exchange_result=0
405+ # If this test fails, need to reset CFLAGS/LIBS (the
406+ # above tests atomically set CFLAGS/LIBS or not; this
407+ # test is running after the fact, so we have to undo
408+ # the side-effects of setting CFLAGS/LIBS if the above
409+ # tests passed).
410+ CFLAGS=$atomic_compare_exchange_CFLAGS_save
411+ LIBS=$atomic_compare_exchange_LIBS_save
412+ AC_MSG_RESULT ( [ no] ) ] ,
413+ [ AC_MSG_RESULT ( [ cannot test -- assume yes (cross compiling)] ) ] )
414+ ] )
415+
416+ AC_DEFINE_UNQUOTED ( [ OPAL_HAVE_C11_CSWAP_INT128] ,
417+ [ $atomic_compare_exchange_result] ,
418+ [ Whether C11 atomic compare swap is both supported and lock-free on 128-bit values] )
419+
420+ dnl If we could not find decent support for 128-bits atomic let's
421+ dnl try the GCC _sync
422+ AS_IF ( [ test $atomic_compare_exchange_result -eq 0] ,
423+ [ OPAL_CHECK_SYNC_BUILTIN_CSWAP_INT128] )
424+
425+ OPAL_VAR_SCOPE_POP
426+ ] )
427+
428+ AC_DEFUN ( [ OPAL_CHECK_GCC_ATOMIC_BUILTINS] , [
429+ AC_MSG_CHECKING ( [ for __atomic builtin atomics] )
430+
431+ AC_TRY_LINK ( [
432+ #include <stdint.h>
433+ uint32_t tmp, old = 0;
434+ uint64_t tmp64, old64 = 0;] , [
435+ __atomic_thread_fence(__ATOMIC_SEQ_CST);
436+ __atomic_compare_exchange_n(&tmp, &old, 1, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
437+ __atomic_add_fetch(&tmp, 1, __ATOMIC_RELAXED);
438+ __atomic_compare_exchange_n(&tmp64, &old64, 1, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
439+ __atomic_add_fetch(&tmp64, 1, __ATOMIC_RELAXED);] ,
440+ [ AC_MSG_RESULT ( [ yes] )
441+ $1 ] ,
442+ [ AC_MSG_RESULT ( [ no] )
443+ $2 ] )
444+
445+ # Check for 128-bit support
446+ OPAL_CHECK_GCC_BUILTIN_CSWAP_INT128
447+ ] )
448+
332449
333450dnl #################################################################
334451dnl
@@ -1020,17 +1137,27 @@ AC_DEFUN([OPAL_CONFIG_ASM],[
10201137 AC_REQUIRE ( [ OPAL_SETUP_CC] )
10211138 AC_REQUIRE ( [ AM_PROG_AS ] )
10221139
1140+ AC_ARG_ENABLE ( [ c11-atomics] ,[ AC_HELP_STRING ([ --enable-c11-atomics] ,
1141+ [ Enable use of C11 atomics if available (default: enabled)] )] )
1142+
10231143 AC_ARG_ENABLE ( [ builtin-atomics] ,
10241144 [ AC_HELP_STRING ([ --enable-builtin-atomics] ,
1025- [ Enable use of __sync builtin atomics (default: enabled)] )] )
1026-
1027- opal_cv_asm_builtin="BUILTIN_NO"
1028- AS_IF ( [ test "$opal_cv_asm_builtin" = "BUILTIN_NO" && test "$enable_builtin_atomics" != "no"] ,
1029- [ OPAL_CHECK_GCC_ATOMIC_BUILTINS([ opal_cv_asm_builtin="BUILTIN_GCC"] , [ ] )] )
1030- AS_IF ( [ test "$opal_cv_asm_builtin" = "BUILTIN_NO" && test "$enable_builtin_atomics" != "no"] ,
1031- [ OPAL_CHECK_SYNC_BUILTINS([ opal_cv_asm_builtin="BUILTIN_SYNC"] , [ ] )] )
1032- AS_IF ( [ test "$opal_cv_asm_builtin" = "BUILTIN_NO" && test "$enable_builtin_atomics" = "yes"] ,
1033- [ AC_MSG_ERROR ( [ __sync builtin atomics requested but not found.] ) ] )
1145+ [ Enable use of __sync builtin atomics (default: disabled)] )] )
1146+
1147+ OPAL_CHECK_C11_CSWAP_INT128
1148+
1149+ if test "x$enable_c11_atomics" != "xno" && test "$opal_cv_c11_supported" = "yes" ; then
1150+ opal_cv_asm_builtin="BUILTIN_C11"
1151+ OPAL_CHECK_C11_CSWAP_INT128
1152+ else
1153+ opal_cv_asm_builtin="BUILTIN_NO"
1154+ AS_IF ( [ test "$opal_cv_asm_builtin" = "BUILTIN_NO" && test "$enable_builtin_atomics" = "yes"] ,
1155+ [ OPAL_CHECK_GCC_ATOMIC_BUILTINS([ opal_cv_asm_builtin="BUILTIN_GCC"] , [ ] )] )
1156+ AS_IF ( [ test "$opal_cv_asm_builtin" = "BUILTIN_NO" && test "$enable_builtin_atomics" = "yes"] ,
1157+ [ OPAL_CHECK_SYNC_BUILTINS([ opal_cv_asm_builtin="BUILTIN_SYNC"] , [ ] )] )
1158+ AS_IF ( [ test "$opal_cv_asm_builtin" = "BUILTIN_NO" && test "$enable_builtin_atomics" = "yes"] ,
1159+ [ AC_MSG_ERROR ( [ __sync builtin atomics requested but not found.] ) ] )
1160+ fi
10341161
10351162 OPAL_CHECK_ASM_PROC
10361163 OPAL_CHECK_ASM_TEXT
0 commit comments