Skip to content

xl: Use C11 builtin atomics if available. #8528

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 47 additions & 7 deletions config/opal_setup_cc.m4
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,46 @@ AC_DEFUN([OPAL_PROG_CC_C11_HELPER],[

opal_prog_cc_c11_helper_CFLAGS_save=$CFLAGS
CFLAGS="$CFLAGS $1"
OPAL_C_COMPILER_VENDOR([opal_c_vendor])

OPAL_CC_HELPER([if $CC $1 supports C11 _Thread_local], [opal_prog_cc_c11_helper__Thread_local_available],
[],[[static _Thread_local int foo = 1;++foo;]])


OPAL_CC_HELPER([if $CC $1 has stdatomic.h], [opal_prog_cc_c11_helper_atomic_has_stdatomic_h],
[[#include <stdatomic.h>]], [])
if test $opal_prog_cc_c11_helper_atomic_has_stdatomic_h -eq 0; then
if test "$opal_cv_c_compiler_vendor" = "ibm"; then
AC_REQUIRE([AC_PROG_GREP])
tmp=`which gcc`
if test $? -eq 0; then
stdatomic_include_path=""
AC_MSG_CHECKING([if gcc has stdatomic.h])
AC_LANG_CONFTEST([AC_LANG_SOURCE([
#include<stdatomic.h>
int main() { }
]
)])
stdatomic_include_path=`gcc -M conftest.c | $GREP stdatomic.h`
if test -z "$stdatomic_include_path"; then
AC_MSG_WARN([stdatomic.h cannot be found. Fallback to C99 atomics.])
else
stdatomic_include_path="${stdatomic_include_path#"${stdatomic_include_path%%[![:space:]]*}"}"
stdatomic_include_path=${stdatomic_include_path%stdatomic.h}
CFLAGS="$CFLAGS -I$stdatomic_include_path"
opal_prog_cc_c11_helper_CFLAGS_save="$opal_prog_cc_c11_helper_CFLAGS -I$stdatomic_include_path"
opal_prog_cc_c11_helper_atomic_has_stdatomic_h=1
AC_MSG_RESULT([stdatomic.h is available])
AC_MSG_RESULT([Adding $stdatomic_include_path to include path. Using C11 atomics.])
fi
else
AC_MSG_WARN([No gcc found. Not checking for stdatomic.h include. Fallback to C99 atomics.])
fi
else
AC_MSG_WARN([Not checking for gcc stdatomic.h include. Fallback to C99 atomics.])
fi
fi

OPAL_CC_HELPER([if $CC $1 supports C11 atomic variables], [opal_prog_cc_c11_helper_atomic_var_available],
[[#include <stdatomic.h>]], [[static atomic_long foo = 1;++foo;]])

Expand All @@ -65,9 +101,9 @@ AC_DEFUN([OPAL_PROG_CC_C11_HELPER],[

OPAL_CC_HELPER([if $CC $1 supports C11 atomic_fetch_xor_explicit], [opal_prog_cc_c11_helper_atomic_fetch_xor_explicit_available],
[[#include <stdatomic.h>
#include <stdint.h>]],[[_Atomic uint32_t a; uint32_t b; atomic_fetch_xor_explicit(&a, b, memory_order_relaxed);]])
#include <stdint.h>]],[[_Atomic uint32_t a; uint32_t b; atomic_fetch_xor_explicit(&a, b, memory_order_relaxed);]])

AS_IF([test $opal_prog_cc_c11_helper__Thread_local_available -eq 1 && test $opal_prog_cc_c11_helper_atomic_var_available -eq 1 && test $opal_prog_cc_c11_helper_atomic_fetch_xor_explicit_available -eq 1],
AS_IF([test $opal_prog_cc_c11_helper__Thread_local_available -eq 1 && test $opal_prog_cc_c11_helper_atomic_var_available -eq 1],
[$2],
[$3])

Expand Down Expand Up @@ -166,7 +202,7 @@ AC_DEFUN([OPAL_SETUP_CC],[
if test $opal_cv_c11_supported = no ; then
# It is not currently an error if C11 support is not available. Uncomment the
# following lines and update the warning when we require a C11 compiler.
# AC_MSG_WARNING([Open MPI requires a C11 (or newer) compiler])
# AC_MSG_WARN([Open MPI requires a C11 (or newer) compiler])
# AC_MSG_ERROR([Aborting.])
# From Open MPI 1.7 on we require a C99 compiant compiler
AC_PROG_CC_C99
Expand Down Expand Up @@ -287,16 +323,20 @@ AC_DEFUN([OPAL_SETUP_CC],[
OPAL_CFLAGS_BEFORE_PICKY="$CFLAGS"

if test $WANT_PICKY_COMPILER -eq 1; then
_OPAL_CHECK_SPECIFIC_CFLAGS(-Wundef, Wundef)
if test "$opal_cv_c_compiler_vendor" != "portland group"; then
_OPAL_CHECK_SPECIFIC_CFLAGS(-Wundef, Wundef)
_OPAL_CHECK_SPECIFIC_CFLAGS(-Wmissing-prototypes, Wmissing_prototypes)
_OPAL_CHECK_SPECIFIC_CFLAGS(-Wstrict-prototypes, Wstrict_prototypes)
fi
_OPAL_CHECK_SPECIFIC_CFLAGS(-Wno-long-long, Wno_long_long, int main() { long long x; })
_OPAL_CHECK_SPECIFIC_CFLAGS(-Wsign-compare, Wsign_compare)
_OPAL_CHECK_SPECIFIC_CFLAGS(-Wmissing-prototypes, Wmissing_prototypes)
_OPAL_CHECK_SPECIFIC_CFLAGS(-Wstrict-prototypes, Wstrict_prototypes)
_OPAL_CHECK_SPECIFIC_CFLAGS(-Wcomment, Wcomment)
_OPAL_CHECK_SPECIFIC_CFLAGS(-Werror-implicit-function-declaration, Werror_implicit_function_declaration)
_OPAL_CHECK_SPECIFIC_CFLAGS(-Wno-long-double, Wno_long_double, int main() { long double x; })
_OPAL_CHECK_SPECIFIC_CFLAGS(-fno-strict-aliasing, fno_strict_aliasing, int main() { long double x; })
_OPAL_CHECK_SPECIFIC_CFLAGS(-pedantic, pedantic)
if test "$opal_cv_c_compiler_vendor" != "ibm" && test "$opal_cv_c_compiler_vendor" != "portland group"; then
_OPAL_CHECK_SPECIFIC_CFLAGS(-pedantic, pedantic)
fi
_OPAL_CHECK_SPECIFIC_CFLAGS(-Wall, Wall)
fi

Expand Down
14 changes: 14 additions & 0 deletions ompi/mca/osc/rdma/osc_rdma_active_target.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,20 @@ static void ompi_osc_rdma_check_posts (ompi_osc_rdma_module_t *module)
}
}

#if defined(__ibmxl__)
// Work around an xl optimization bug that would cause the compiler to segv.
//
// xl doesn't like something about caching and checking the return value of
// ompi_osc_rdma_lock_compare_exchange() below when the opt-level is high.
// For now work around this bug by lowering the optimization on this function
// with xl compilers.
//
// Found on:
// $. xlc --version
// IBM XL C/C++ for Linux, V16.1.1 (5725-C73, 5765-J13)
// Version: 16.01.0001.0008
#pragma option_override(ompi_osc_rdma_post_peer, "opt(level,0)")
#endif
static int ompi_osc_rdma_post_peer (ompi_osc_rdma_module_t *module, ompi_osc_rdma_peer_t *peer)
{
uint64_t target = (uint64_t) (intptr_t) peer->state + offsetof (ompi_osc_rdma_state_t, post_index);
Expand Down
2 changes: 1 addition & 1 deletion opal/include/opal/opal_portable_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@
# else
# define PLATFORM_COMPILER_XLC_C 1
# endif
# define PLATFORM_COMPILER_VERSION __xlC__
# define PLATFORM_COMPILER_VERSION __ibmxl_version__
# define PLATFORM_COMPILER_VERSION_INT(maj,min,pat) \
( ((maj) << 8) | ((min) << 4) | (pat) )

Expand Down
9 changes: 3 additions & 6 deletions opal/include/opal/sys/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ BEGIN_C_DECLS
* to use an int or unsigned char as the lock value - the user is not
* informed either way.
*/
#ifndef OPAL_USE_ATOMIC_FLAG_OPAL_LOCK
struct opal_atomic_lock_t {
union {
opal_atomic_int32_t lock; /**< The lock address (an integer) */
Expand All @@ -105,7 +106,7 @@ struct opal_atomic_lock_t {
} u;
};
typedef struct opal_atomic_lock_t opal_atomic_lock_t;

#endif
/**********************************************************************
*
* Set or unset these macros in the architecture-specific atomic.h
Expand Down Expand Up @@ -164,7 +165,7 @@ enum {
*********************************************************************/
#if defined(DOXYGEN)
/* don't include system-level gorp when generating doxygen files */
#elif OPAL_ASSEMBLY_BUILTIN == OPAL_BUILTIN_GCC
#elif OPAL_ASSEMBLY_BUILTIN == OPAL_BUILTIN_GCC || OPAL_ASSEMBLY_ARCH == OPAL_POWERPC32 || OPAL_ASSEMBLY_ARCH == OPAL_POWERPC64
#include "opal/sys/gcc_builtin/atomic.h"
#elif OPAL_ASSEMBLY_ARCH == OPAL_X86_64
#include "opal/sys/x86_64/atomic.h"
Expand All @@ -174,10 +175,6 @@ enum {
#include "opal/sys/arm64/atomic.h"
#elif OPAL_ASSEMBLY_ARCH == OPAL_IA32
#include "opal/sys/ia32/atomic.h"
#elif OPAL_ASSEMBLY_ARCH == OPAL_POWERPC32
#include "opal/sys/powerpc/atomic.h"
#elif OPAL_ASSEMBLY_ARCH == OPAL_POWERPC64
#include "opal/sys/powerpc/atomic.h"
#endif

#ifndef DOXYGEN
Expand Down
42 changes: 41 additions & 1 deletion opal/include/opal/sys/atomic_stdc.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,28 @@ static inline void opal_atomic_rmb (void)
#define opal_atomic_compare_exchange_strong_acq(addr, oldval, newval) atomic_compare_exchange_strong_explicit (addr, oldval, newval, memory_order_acquire, memory_order_relaxed)
#define opal_atomic_compare_exchange_strong_rel(addr, oldval, newval) atomic_compare_exchange_strong_explicit (addr, oldval, newval, memory_order_release, memory_order_relaxed)

#if defined(__PGI) || defined(__ibmxl__)
#define opal_atomic_swap_32(addr, value) atomic_exchange_explicit (addr, value, memory_order_relaxed)
#define opal_atomic_swap_64(addr, value) atomic_exchange_explicit (addr, value, memory_order_relaxed)
#define opal_atomic_swap_ptr(addr, value) atomic_exchange_explicit (addr, value, memory_order_relaxed)
#else
#define opal_atomic_swap_32(addr, value) atomic_exchange_explicit ((_Atomic unsigned int *)addr, value, memory_order_relaxed)
#define opal_atomic_swap_64(addr, value) atomic_exchange_explicit ((_Atomic unsigned long *)addr, value, memory_order_relaxed)
#define opal_atomic_swap_ptr(addr, value) atomic_exchange_explicit ((_Atomic unsigned long *)addr, value, memory_order_relaxed)
#endif

#if defined(__PGI) || defined(__ibmxl__)
#define OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(op, bits, type, operator) \
static inline type opal_atomic_fetch_ ## op ##_## bits (opal_atomic_ ## type *addr, type value) \
{ \
return atomic_fetch_ ## op ## _explicit ((type *)addr, value, memory_order_relaxed); \
} \
\
static inline type opal_atomic_## op ## _fetch_ ## bits (opal_atomic_ ## type *addr, type value) \
{ \
return atomic_fetch_ ## op ## _explicit ((type *)addr, value, memory_order_relaxed) operator value; \
}
#else
#define OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(op, bits, type, operator) \
static inline type opal_atomic_fetch_ ## op ##_## bits (opal_atomic_ ## type *addr, type value) \
{ \
Expand All @@ -111,6 +129,7 @@ static inline void opal_atomic_rmb (void)
{ \
return atomic_fetch_ ## op ## _explicit (addr, value, memory_order_relaxed) operator value; \
}
#endif

OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(add, 32, int32_t, +)
OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(add, 64, int64_t, +)
Expand Down Expand Up @@ -206,22 +225,39 @@ static inline int64_t opal_atomic_max_fetch_64 (opal_atomic_int64_t *addr, int64
#define OPAL_ATOMIC_LOCK_UNLOCKED false
#define OPAL_ATOMIC_LOCK_LOCKED true

#define OPAL_ATOMIC_LOCK_INIT ATOMIC_FLAG_INIT
#define OPAL_USE_C11_ATOMIC_LOCK 1

#define OPAL_USE_ATOMIC_FLAG_OPAL_LOCK 1
#if defined(__ibmxl__) || defined(__PGI)
#define OPAL_ATOMIC_LOCK_INIT 0
typedef _Atomic bool opal_atomic_lock_t;
#else
#define OPAL_ATOMIC_LOCK_INIT ATOMIC_FLAG_INIT
typedef atomic_flag opal_atomic_lock_t;
#endif

/*
* Lock initialization function. It set the lock to UNLOCKED.
*/
static inline void opal_atomic_lock_init (opal_atomic_lock_t *lock, bool value)
{
#if defined(__PGI)
atomic_flag_clear ((volatile void *) lock);
#else
atomic_flag_clear (lock);
#endif
}


static inline int opal_atomic_trylock (opal_atomic_lock_t *lock)
{

#if defined(__PGI)
return (int) atomic_flag_test_and_set ((volatile void *) lock);
#else
return (int) atomic_flag_test_and_set (lock);
#endif

}


Expand All @@ -234,7 +270,11 @@ static inline void opal_atomic_lock(opal_atomic_lock_t *lock)

static inline void opal_atomic_unlock (opal_atomic_lock_t *lock)
{
#if defined(__PGI)
atomic_flag_clear ((volatile void *) lock);
#else
atomic_flag_clear (lock);
#endif
}


Expand Down
1 change: 0 additions & 1 deletion opal/include/opal/sys/powerpc/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,4 @@
# This makefile.am does not stand on its own - it is included from opal/include/Makefile.am

headers += \
opal/sys/powerpc/atomic.h \
opal/sys/powerpc/timer.h
Loading