diff --git a/config/opal_config_argobots.m4 b/config/opal_config_argobots.m4 new file mode 100644 index 00000000000..c158adf0a50 --- /dev/null +++ b/config/opal_config_argobots.m4 @@ -0,0 +1,37 @@ +dnl +dnl Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana +dnl University Research and Technology +dnl Corporation. All rights reserved. +dnl Copyright (c) 2004-2005 The University of Tennessee and The University +dnl of Tennessee Research Foundation. All rights +dnl reserved. +dnl Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, +dnl University of Stuttgart. All rights reserved. +dnl Copyright (c) 2004-2005 The Regents of the University of California. +dnl All rights reserved. +dnl Copyright (c) 2012 Cisco Systems, Inc. All rights reserved. +dnl Copyright (c) 2014 Intel, Inc. All rights reserved. +dnl Copyright (c) 2014-2016 Research Organization for Information Science +dnl and Technology (RIST). All rights reserved. +dnl $COPYRIGHT$ +dnl +dnl Additional copyrights may follow +dnl +dnl $HEADER$ +dnl +dnl OPAL_CONFIG_ARGOBOTS_THREADS() +dnl +dnl Configure Argobots threads, setting the following variables (but +dnl not calling AC_SUBST on them). + +AC_DEFUN([OPAL_CONFIG_ARGOBOTS_THREADS],[ + AC_CHECK_HEADERS([abt.h], + [AC_CHECK_LIB([abt],[ABT_init], + [threads_argobots_happy="yes"], + [threads_argobots_happy="no"])], + [threads_argobots_happy="no"]) + + AS_IF([test "$threads_argobots_happy" = "yes"], + [$1], + [$2]) +])dnl diff --git a/config/opal_config_pthreads.m4 b/config/opal_config_pthreads.m4 index b2d9c7aaece..de040436a9d 100644 --- a/config/opal_config_pthreads.m4 +++ b/config/opal_config_pthreads.m4 @@ -281,11 +281,11 @@ if test "$opal_pthread_c_success" = "0"; then opal_pthread_c_success=0) AC_LANG_POP(C) if test "$opal_pthread_c_success" = "1"; then - PTHREAD_CFLAGS="$pf" + TPKG_CFLAGS="$pf" AC_MSG_RESULT([yes]) break else - PTHREAD_CFLAGS= + TPKG_CFLAGS= CFLAGS="$orig_CFLAGS" AC_MSG_RESULT([no]) fi @@ -307,11 +307,11 @@ if test "$opal_pthread_cxx_success" = "0"; then opal_pthread_cxx_success=0) AC_LANG_POP(C++) if test "$opal_pthread_cxx_success" = "1"; then - PTHREAD_CXXFLAGS="$pf" + TPKG_CXXFLAGS="$pf" AC_MSG_RESULT([yes]) break else - PTHREAD_CXXFLAGS= + TPKG_CXXFLAGS= CXXFLAGS="$orig_CXXFLAGS" AC_MSG_RESULT([no]) fi @@ -335,11 +335,11 @@ if test "$opal_pthread_fortran_success" = "0" && \ opal_pthread_fortran_success=0) AC_LANG_POP(C) if test "$opal_pthread_fortran_success" = "1"; then - PTHREAD_FCFLAGS="$pf" + TPKG_FCFLAGS="$pf" AC_MSG_RESULT([yes]) break else - PTHREAD_FCFLAGS= + TPKG_FCFLAGS= FCFLAGS="$orig_FCFLAGS" AC_MSG_RESULT([no]) fi @@ -406,14 +406,14 @@ if test "$opal_pthread_c_success" = "0"; then case "${host_cpu}-${host-_os}" in *-aix* | *-freebsd*) if test "`echo $CPPFLAGS | $GREP 'D_THREAD_SAFE'`" = ""; then - PTHREAD_CPPFLAGS="-D_THREAD_SAFE" - CPPFLAGS="$CPPFLAGS $PTHREAD_CPPFLAGS" + TPKG_CPPFLAGS="-D_THREAD_SAFE" + CPPFLAGS="$CPPFLAGS $TPKG_CPPFLAGS" fi ;; *) if test "`echo $CPPFLAGS | $GREP 'D_REENTRANT'`" = ""; then - PTHREAD_CPPFLAGS="-D_REENTRANT" - CPPFLAGS="$CPPFLAGS $PTHREAD_CPPFLAGS" + TPKG_CPPFLAGS="-D_REENTRANT" + CPPFLAGS="$CPPFLAGS $TPKG_CPPFLAGS" fi ;; esac @@ -423,10 +423,10 @@ if test "$opal_pthread_c_success" = "0"; then opal_pthread_c_success=0) AC_LANG_POP(C) if test "$opal_pthread_c_success" = "1"; then - PTHREAD_LIBS="$pl" + TPKG_LIBS="$pl" AC_MSG_RESULT([yes]) else - PTHREAD_CPPFLAGS= + TPKG_CPPFLAGS= CPPFLAGS="$orig_CPPFLAGS" LIBS="$orig_LIBS" AC_MSG_RESULT([no]) @@ -441,23 +441,23 @@ AC_DEFUN([OPAL_INTL_POSIX_THREADS_LIBS_CXX],[ # C++ compiler # if test "$opal_pthread_cxx_success" = "0"; then - if test ! "$opal_pthread_c_success" = "0" && test ! "$PTHREAD_LIBS" = "" ; then - AC_MSG_CHECKING([if C++ compiler and POSIX threads work with $PTHREAD_LIBS]) + if test ! "$opal_pthread_c_success" = "0" && test ! "$TPKG_LIBS" = "" ; then + AC_MSG_CHECKING([if C++ compiler and POSIX threads work with $TPKG_LIBS]) case "${host_cpu}-${host-_os}" in *-aix* | *-freebsd*) if test "`echo $CXXCPPFLAGS | $GREP 'D_THREAD_SAFE'`" = ""; then - PTHREAD_CXXCPPFLAGS="-D_THREAD_SAFE" - CXXCPPFLAGS="$CXXCPPFLAGS $PTHREAD_CXXCPPFLAGS" + TPKG_CXXCPPFLAGS="-D_THREAD_SAFE" + CXXCPPFLAGS="$CXXCPPFLAGS $TPKG_CXXCPPFLAGS" fi ;; *) if test "`echo $CXXCPPFLAGS | $GREP 'D_REENTRANT'`" = ""; then - PTHREAD_CXXCPPFLAGS="-D_REENTRANT" - CXXCPPFLAGS="$CXXCPPFLAGS $PTHREAD_CXXCPPFLAGS" + TPKG_CXXCPPFLAGS="-D_REENTRANT" + CXXCPPFLAGS="$CXXCPPFLAGS $TPKG_CXXCPPFLAGS" fi ;; esac - LIBS="$orig_LIBS $PTHREAD_LIBS" + LIBS="$orig_LIBS $TPKG_LIBS" AC_LANG_PUSH(C++) OPAL_INTL_PTHREAD_TRY_LINK(opal_pthread_cxx_success=1, opal_pthread_cxx_success=0) @@ -476,14 +476,14 @@ if test "$opal_pthread_cxx_success" = "0"; then case "${host_cpu}-${host-_os}" in *-aix* | *-freebsd*) if test "`echo $CXXCPPFLAGS | $GREP 'D_THREAD_SAFE'`" = ""; then - PTHREAD_CXXCPPFLAGS="-D_THREAD_SAFE" - CXXCPPFLAGS="$CXXCPPFLAGS $PTHREAD_CXXCPPFLAGS" + TPKG_CXXCPPFLAGS="-D_THREAD_SAFE" + CXXCPPFLAGS="$CXXCPPFLAGS $TPKG_CXXCPPFLAGS" fi ;; *) if test "`echo $CXXCPPFLAGS | $GREP 'D_REENTRANT'`" = ""; then - PTHREAD_CXXCPPFLAGS="-D_REENTRANT" - CXXCPPFLAGS="$CXXCPPFLAGS $PTHREAD_CXXCPPFLAGS" + TPKG_CXXCPPFLAGS="-D_REENTRANT" + CXXCPPFLAGS="$CXXCPPFLAGS $TPKG_CXXCPPFLAGS" fi ;; esac @@ -493,10 +493,10 @@ if test "$opal_pthread_cxx_success" = "0"; then opal_pthread_cxx_success=0) AC_LANG_POP(C++) if test "$opal_pthread_cxx_success" = "1"; then - PTHREAD_LIBS="$pl" + TPKG_LIBS="$pl" AC_MSG_RESULT([yes]) else - PTHREAD_CXXCPPFLAGS= + TPKG_CXXCPPFLAGS= CXXCPPFLAGS="$orig_CXXCPPFLAGS" LIBS="$orig_LIBS" AC_MSG_RESULT([no]) @@ -514,9 +514,9 @@ AC_DEFUN([OPAL_INTL_POSIX_THREADS_LIBS_FC],[ if test "$opal_pthread_fortran_success" = "0" && \ test "$OMPI_TRY_FORTRAN_BINDINGS" -gt "$OMPI_FORTRAN_NO_BINDINGS" && \ test $ompi_fortran_happy -eq 1; then - if test ! "$opal_pthread_c_success" = "0" && test ! "$PTHREAD_LIBS" = "" ; then - AC_MSG_CHECKING([if Fortran compiler and POSIX threads work with $PTHREAD_LIBS]) - LIBS="$orig_LIBS $PTHREAD_LIBS" + if test ! "$opal_pthread_c_success" = "0" && test ! "$TPKG_LIBS" = "" ; then + AC_MSG_CHECKING([if Fortran compiler and POSIX threads work with $TPKG_LIBS]) + LIBS="$orig_LIBS $TPKG_LIBS" AC_LANG_PUSH(C) OPAL_INTL_PTHREAD_TRY_LINK_FORTRAN(opal_pthread_fortran_success=1, opal_pthread_fortran_success=0) @@ -537,7 +537,7 @@ if test "$opal_pthread_fortran_success" = "0" && \ opal_pthread_fortran_success=0) AC_LANG_POP(C) if test "$opal_pthread_fortran_success" = "1"; then - PTHREAD_LIBS="$pl" + TPKG_LIBS="$pl" AC_MSG_RESULT([yes]) break else @@ -600,13 +600,13 @@ orig_CXXCPPFLAGS="$CXXCPPFLAGS" orig_LDFLAGS="$LDFLAGS" orig_LIBS="$LIBS" -PTHREAD_CFLAGS= -PTHREAD_FCFLAGS= -PTHREAD_CXXFLAGS= -PTHREAD_CPPFLAGS= -PTHREAD_CXXCPPFLAGS= -PTHREAD_LDFLAGS= -PTHREAD_LIBS= +TPKG_CFLAGS= +TPKG_FCFLAGS= +TPKG_CXXFLAGS= +TPKG_CPPFLAGS= +TPKG_CXXCPPFLAGS= +TPKG_LDFLAGS= +TPKG_LIBS= # Try with the basics, mam. OPAL_INTL_POSIX_THREADS_PLAIN diff --git a/config/opal_config_qthreads.m4 b/config/opal_config_qthreads.m4 new file mode 100644 index 00000000000..08c0fd729a9 --- /dev/null +++ b/config/opal_config_qthreads.m4 @@ -0,0 +1,45 @@ +dnl +dnl Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana +dnl University Research and Technology +dnl Corporation. All rights reserved. +dnl Copyright (c) 2004-2005 The University of Tennessee and The University +dnl of Tennessee Research Foundation. All rights +dnl reserved. +dnl Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, +dnl University of Stuttgart. All rights reserved. +dnl Copyright (c) 2004-2005 The Regents of the University of California. +dnl All rights reserved. +dnl Copyright (c) 2012 Cisco Systems, Inc. All rights reserved. +dnl Copyright (c) 2014 Intel, Inc. All rights reserved. +dnl Copyright (c) 2014-2016 Research Organization for Information Science +dnl and Technology (RIST). All rights reserved. +dnl Copyright (c) 2019 Sandia National Laboratories. All rights reserved. +dnl Copyright (c) 2019 Triad National Security, LLC. All rights. +dnl $COPYRIGHT$ +dnl +dnl Additional copyrights may follow +dnl +dnl $HEADER$ +dnl +dnl OPAL_CONFIG_QTHREADS() +dnl +dnl Configure argobot threads, setting the following variables (but +dnl not calling AC_SUBST on them). + +#******************************************************************** +# +# TODO: undoubtedly need some better check than this +# +#******************************************************************** +AC_DEFUN([OPAL_CONFIG_QTHREADS],[ + + AC_CHECK_HEADERS([mach/mach_time.h], + [AC_CHECK_FUNC([mach_absolute_time], + [threads_qthreads_happy="yes"], + [threads_qthreads_happy="no"])], + [threads_qthreads_happy="no"]) + + AS_IF([test "$threads_qthreads_happy" = "yes"], + [$1], + [$2]) +])dnl diff --git a/config/opal_config_threads.m4 b/config/opal_config_threads.m4 index d136cccf86b..9aead21cbd5 100644 --- a/config/opal_config_threads.m4 +++ b/config/opal_config_threads.m4 @@ -14,6 +14,7 @@ dnl Copyright (c) 2009-2011 Oak Ridge National Labs. All rights reserved. dnl Copyright (c) 2014 Intel, Inc. All rights reserved dnl Copyright (c) 2015 Research Organization for Information Science dnl and Technology (RIST). All rights reserved. +dnl Copyright (c) 2019 Triad National Security, LLC. All rights. dnl $COPYRIGHT$ dnl dnl Additional copyrights may follow @@ -34,36 +35,74 @@ AC_DEFUN([OPAL_CONFIG_THREADS],[ # # -# Check we have POSIX threads +# First see what kind of threads we are going to use # -OPAL_CONFIG_POSIX_THREADS(HAVE_POSIX_THREADS=1, HAVE_POSIX_THREADS=0) -AC_MSG_CHECKING([for working POSIX threads package]) -if test "$HAVE_POSIX_THREADS" = "1" ; then - AC_MSG_RESULT([yes]) -else - AC_MSG_RESULT([no]) -fi -export HAVE_POSIX_THREADS + +AC_ARG_WITH([threads], + [AC_HELP_STRING([--with-threads=TYPE], + [Specify thread TYPE to use. default:pthreads. Other options are qthreads and argobots.])]) + +# +# Check we for the thread package requested, or posix +# + +thread_type_found= + +# +# check for posix threads +# +AS_IF([test -z "$with_threads" || test "$with_threads" = "pthreads" || test "$with_threads" = "yes"], + [OPAL_CONFIG_POSIX_THREADS(HAVE_THREAD_PKG=1, HAVE_THREAD_PKG=0) + AC_MSG_CHECKING([for working POSIX threads package]) + AS_IF([test "$HAVE_THREAD_PKG" = "1"], + [AC_MSG_RESULT([yes]) + thread_type_found="pthreads"], + [AC_MSG_RESULT([no])])], + []) + +# +# see if argobots is called for +# +AS_IF([test -z "$thread_type_found" && test "$with_threads" = "argobots"], + [OPAL_CONFIG_ARGOBOTS_THREADS(HAVE_THREAD_PKG=1, HAVE_THREAD_PKG=0) + AC_MSG_CHECKING([for working ARGOBOTS threads package]) + AS_IF([test "$HAVE_THREAD_PKG" = "1"], + [AC_MSG_RESULT([yes]) + thread_type_found="argobots"], + [AC_MSG_RESULT([no])])], + []) + +AS_IF([test -z "$thread_type_found" && test "$with_threads" = "qthreads"], + [OPAL_CONFIG_QTHREADS(HAVE_THREAD_PKG=1, HAVE_THREAD_PKG=0) + AC_MSG_CHECKING([for working Qthreads package]) + AS_IF([test "$HAVE_THREAD_PKG" = "1"], + [AC_MSG_RESULT([yes]) + thread_type_found="qthreads"], + [AC_MSG_RESULT([no])])], + []) # -# Ask what threading we want (allow posix right now) +# Bail if we didn't find any thread package # -if test "$HAVE_POSIX_THREADS" = "0"; then - AC_MSG_WARN(["*** POSIX threads are not"]) - AC_MSG_WARN(["*** available on your system "]) - AC_MSG_ERROR(["*** Can not continue"]) -fi +AS_IF([test -z "$thread_type_found"], + [AC_MSG_WARN([*** no thread package $with_threads]) + AC_MSG_WARN([*** available on your system]) + AC_MSG_ERROR([*** Can not continue])]) -THREAD_CFLAGS="$PTHREAD_CFLAGS" -THREAD_FCFLAGS="$PTHREAD_FCFLAGS" -THREAD_CXXFLAGS="$PTHREAD_CXXFLAGS" -THREAD_CPPFLAGS="$PTHREAD_CPPFLAGS" -THREAD_CXXCPPFLAGS="$PTHREAD_CXXCPPFLAGS" -THREAD_LDFLAGS="$PTHREAD_LDFLAGS" -THREAD_LIBS="$PTHREAD_LIBS" +THREAD_CFLAGS="$TPKG_CFLAGS" +THREAD_FCFLAGS="$TPKG_FCFLAGS" +THREAD_CXXFLAGS="$TPKG_CXXFLAGS" +THREAD_CPPFLAGS="$TPKG_CPPFLAGS" +THREAD_CXXCPPFLAGS="$TPKG_CXXCPPFLAGS" +THREAD_LDFLAGS="$TPKG_LDFLAGS" +THREAD_LIBS="$TPKG_LIBS" +HAVE_THREAD_PKG_TYPE="$thread_type_found" +export HAVE_THREAD_PKG_TYPE -OPAL_CHECK_PTHREAD_PIDS +AS_IF([test "$thread_type_found" = "pthreads"], + [OPAL_CHECK_PTHREAD_PIDS],[]) +OPAL_SUMMARY_ADD([[Miscellaneous]],[[Threading Package]],[opal_threads], [$thread_type_found]) ])dnl diff --git a/opal/Makefile.am b/opal/Makefile.am index b657794eabc..de2588716ed 100644 --- a/opal/Makefile.am +++ b/opal/Makefile.am @@ -71,7 +71,6 @@ endif include class/Makefile.am include memoryhooks/Makefile.am include runtime/Makefile.am -include threads/Makefile.am include mca/Makefile.am include tools/Makefile.am include dss/Makefile.am diff --git a/opal/mca/event/event.h b/opal/mca/event/event.h index b0958b64e09..65f8f69e054 100644 --- a/opal/mca/event/event.h +++ b/opal/mca/event/event.h @@ -48,6 +48,8 @@ BEGIN_C_DECLS #define OPAL_TIMEOUT_DEFAULT {1, 0} +OPAL_DECLSPEC void opal_event_use_threads(void); + /** * Structure for event components. */ diff --git a/opal/mca/event/external/external.h b/opal/mca/event/external/external.h index 00378f684fe..6fe67feeeab 100644 --- a/opal/mca/event/external/external.h +++ b/opal/mca/event/external/external.h @@ -71,9 +71,6 @@ OPAL_DECLSPEC int opal_event_finalize(void); #define opal_event_set_priority(x, n) event_priority_set((x), (n)) -/* thread support APIs */ -#define opal_event_use_threads() evthread_use_pthreads() - /* Basic event APIs */ #define opal_event_enable_debug_mode() event_enable_debug_mode() diff --git a/opal/mca/event/libevent2022/libevent/poll.c b/opal/mca/event/libevent2022/libevent/poll.c index 04d311bb676..47beb50e081 100644 --- a/opal/mca/event/libevent2022/libevent/poll.c +++ b/opal/mca/event/libevent2022/libevent/poll.c @@ -162,6 +162,9 @@ poll_dispatch(struct event_base *base, struct timeval *tv) EVBASE_RELEASE_LOCK(base, th_base_lock); + if (msec > 0) { + msec = 0; + } res = poll(event_set, nfds, msec); EVBASE_ACQUIRE_LOCK(base, th_base_lock); diff --git a/opal/mca/event/libevent2022/libevent2022.h b/opal/mca/event/libevent2022/libevent2022.h index de3443539f0..73961785475 100644 --- a/opal/mca/event/libevent2022/libevent2022.h +++ b/opal/mca/event/libevent2022/libevent2022.h @@ -102,9 +102,6 @@ OPAL_DECLSPEC int opal_event_finalize(void); #define opal_event_set_priority(x, n) event_priority_set((x), (n)) -/* thread support APIs */ -#define opal_event_use_threads() evthread_use_pthreads() - /* Basic event APIs */ #define opal_event_enable_debug_mode() event_enable_debug_mode() diff --git a/opal/mca/pmix/base/base.h b/opal/mca/pmix/base/base.h index 83365891070..277e598cf30 100644 --- a/opal/mca/pmix/base/base.h +++ b/opal/mca/pmix/base/base.h @@ -55,11 +55,11 @@ OPAL_DECLSPEC int opal_pmix_base_exchange(opal_value_t *info, OPAL_DECLSPEC void opal_pmix_base_set_evbase(opal_event_base_t *evbase); -#define opal_pmix_condition_wait(a,b) pthread_cond_wait(a, &(b)->m_lock_pthread) -typedef pthread_cond_t opal_pmix_condition_t; -#define opal_pmix_condition_broadcast(a) pthread_cond_broadcast(a) -#define opal_pmix_condition_signal(a) pthread_cond_signal(a) -#define OPAL_PMIX_CONDITION_STATIC_INIT PTHREAD_COND_INITIALIZER +#define opal_pmix_condition_wait(a,b) opal_cond_wait(a, b) +typedef opal_cond_t opal_pmix_condition_t; +#define opal_pmix_condition_broadcast(a) opal_cond_broadcast(a) +#define opal_pmix_condition_signal(a) opal_cond_signal(a) +#define OPAL_PMIX_CONDITION_STATIC_INIT OPAL_CONDITION_STATIC_INIT typedef struct { opal_mutex_t mutex; @@ -81,7 +81,7 @@ extern opal_pmix_base_t opal_pmix_base; #define OPAL_PMIX_CONSTRUCT_LOCK(l) \ do { \ OBJ_CONSTRUCT(&(l)->mutex, opal_mutex_t); \ - pthread_cond_init(&(l)->cond, NULL); \ + opal_cond_init(&(l)->cond); \ (l)->active = true; \ OPAL_POST_OBJECT((l)); \ } while(0) @@ -90,7 +90,7 @@ extern opal_pmix_base_t opal_pmix_base; do { \ OPAL_ACQUIRE_OBJECT((l)); \ OBJ_DESTRUCT(&(l)->mutex); \ - pthread_cond_destroy(&(l)->cond); \ + opal_cond_destroy(&(l)->cond); \ } while(0) diff --git a/opal/mca/threads/Makefile.am b/opal/mca/threads/Makefile.am new file mode 100644 index 00000000000..7e7e65173b5 --- /dev/null +++ b/opal/mca/threads/Makefile.am @@ -0,0 +1,40 @@ +# +# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana +# University Research and Technology +# Corporation. All rights reserved. +# Copyright (c) 2004-2005 The University of Tennessee and The University +# of Tennessee Research Foundation. All rights +# reserved. +# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, +# University of Stuttgart. All rights reserved. +# Copyright (c) 2004-2005 The Regents of the University of California. +# All rights reserved. +# Copyright (c) 2010 Cisco Systems, Inc. All rights reserved. +# Copyright (c) 2019 Sandia National Laboratories. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +# main library setup +noinst_LTLIBRARIES = libmca_threads.la +libmca_threads_la_SOURCES = + +# local files +headers = threads.h +nodist_headers = +libmca_threads_la_SOURCES += $(headers) + +# Conditionally install the header files +if WANT_INSTALL_HEADERS +opaldir = $(opalincludedir)/$(subdir) +nobase_opal_HEADERS = $(headers) +nobase_nodist_opal_HEADERS = $(nodist_headers) +endif + +include base/Makefile.am + +distclean-local: + rm -f base/static-components.h diff --git a/opal/mca/threads/argobots/Makefile.am b/opal/mca/threads/argobots/Makefile.am new file mode 100644 index 00000000000..ffec87a40d3 --- /dev/null +++ b/opal/mca/threads/argobots/Makefile.am @@ -0,0 +1,34 @@ +# +# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana +# University Research and Technology +# Corporation. All rights reserved. +# Copyright (c) 2004-2005 The University of Tennessee and The University +# of Tennessee Research Foundation. All rights +# reserved. +# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, +# University of Stuttgart. All rights reserved. +# Copyright (c) 2004-2005 The Regents of the University of California. +# All rights reserved. +# Copyright (c) 2008 Cisco Systems, Inc. All rights reserved. +# Copyright (c) 2019 Sandia National Laboratories. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +noinst_LTLIBRARIES = libmca_threads_argobots.la + +libmca_threads_argobots_la_SOURCES = \ + threads_argobots.h \ + threads_argobots_component.c \ + threads_argobots_condition.c \ + threads_argobots_event.c \ + threads_argobots_module.c \ + threads_argobots_mutex.c \ + threads_argobots_mutex.h \ + threads_argobots_threads.h \ + threads_argobots_tsd.h \ + threads_argobots_wait_sync.c \ + threads_argobots_wait_sync.h diff --git a/opal/mca/threads/argobots/configure.m4 b/opal/mca/threads/argobots/configure.m4 new file mode 100644 index 00000000000..26d327ac143 --- /dev/null +++ b/opal/mca/threads/argobots/configure.m4 @@ -0,0 +1,62 @@ +# -*- shell-script -*- +# +# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana +# University Research and Technology +# Corporation. All rights reserved. +# Copyright (c) 2004-2005 The University of Tennessee and The University +# of Tennessee Research Foundation. All rights +# reserved. +# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, +# University of Stuttgart. All rights reserved. +# Copyright (c) 2004-2005 The Regents of the University of California. +# All rights reserved. +# Copyright (c) 2010 Cisco Systems, Inc. All rights reserved. +# Copyright (c) 2015 Research Organization for Information Science +# and Technology (RIST). All rights reserved. +# Copyright (c) 2019 Sandia National Laboratories. All rights reserved. +# Copyright (c) 2019 Triad National Security, LLC. All rights +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# +AC_DEFUN([MCA_opal_threads_argobots_PRIORITY], [30]) + +AC_DEFUN([MCA_opal_threads_argobots_COMPILE_MODE], [ + AC_MSG_CHECKING([for MCA component $2:$3 compile mode]) + $4="static" + AC_MSG_RESULT([$$4]) +]) + +AC_DEFUN([MCA_opal_threads_argobots_POST_CONFIG],[ + AS_IF([test "$1" = "1"], [threads_base_include="argobots/threads_argobots_threads.h"]) +])dnl + +AC_DEFUN([MCA_opal_mutex_argobots_POST_CONFIG],[ + AS_IF([test "$1" = "1"], [mutex_base_include="argobots/threads_argobots_mutex.h"]) + AC_MSG_CHECKING([mutex_base_include = $mutex_base_include]) +])dnl + +AC_DEFUN([MCA_opal_tsd_argobots_POST_CONFIG],[ + AS_IF([test "$1" = "1"], [threads_base_include="argobots/threads_argobots_tsd.h"]) + AC_MSG_CHECKING([threads_base_include = $threads_base_include]) +])dnl + +AC_DEFUN([MCA_opal_wait_sync_argobots_POST_CONFIG],[ + AS_IF([test "$1" = "1"], [wait_sync_base_include="argobots/threads_argobots_wait_sync.h"]) + AC_MSG_CHECKING([wait_sync_base_include = $wait_sync_base_include]) +])dnl + +# MCA_threads_argobots_CONFIG(action-if-can-compile, +# [action-if-cant-compile]) +# ------------------------------------------------ +AC_DEFUN([MCA_opal_threads_argobots_CONFIG],[ + AC_CONFIG_FILES([opal/mca/threads/argobots/Makefile]) + + AC_MSG_CHECKING([HAVE_THREAD_PKG_TYPE = $HAVE_THREAD_PKG_TYPE]) + + AS_IF([test "$HAVE_THREAD_PKG_TYPE" = "argobots"], + [$1], + [$2]) +]) diff --git a/opal/mca/threads/argobots/owner.txt b/opal/mca/threads/argobots/owner.txt new file mode 100644 index 00000000000..199577ac8cf --- /dev/null +++ b/opal/mca/threads/argobots/owner.txt @@ -0,0 +1,7 @@ +# +# owner/status file +# owner: institution that is responsible for this package +# status: e.g. active, maintenance, unmaintained +# +owner: SNL +status: unmaintained diff --git a/opal/mca/threads/argobots/threads_argobots.h b/opal/mca/threads/argobots/threads_argobots.h new file mode 100644 index 00000000000..133fa81582a --- /dev/null +++ b/opal/mca/threads/argobots/threads_argobots.h @@ -0,0 +1,12 @@ + +#ifndef OPAL_MCA_THREADS_ARGOBOTS_THREADS_ARGOBOTS_H +#define OPAL_MCA_THREADS_ARGOBOTS_THREADS_ARGOBOTS_H 1 + +#include + +static inline void ensure_init_argobots(void) { + if (ABT_initialized() != 0) + ABT_init(0, 0); +} + +#endif /* OPAL_MCA_THREADS_ARGOBOTS_THREADS_ARGOBOTS_H */ diff --git a/opal/mca/threads/argobots/threads_argobots_component.c b/opal/mca/threads/argobots/threads_argobots_component.c new file mode 100644 index 00000000000..248473a2e27 --- /dev/null +++ b/opal/mca/threads/argobots/threads_argobots_component.c @@ -0,0 +1,57 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ +/* + * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2014 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2007-2015 Los Alamos National Security, LLC. All rights + * reserved. + * Copyright (c) 2019 Sandia National Laboratories. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "opal_config.h" + +#include "opal/mca/threads/argobots/threads_argobots.h" +#include "opal/mca/threads/thread.h" +#include "opal/mca/threads/threads.h" +#include "opal/constants.h" +#include + +static int opal_threads_argobots_open(void); + +const opal_threads_base_component_2_0_0_t mca_threads_argobots_component = { + /* First, the mca_component_t struct containing meta information + about the component itself */ + .threadsc_version = { + OPAL_THREADS_BASE_VERSION_2_0_0, + + /* Component name and version */ + .mca_component_name = "argobots", + MCA_BASE_MAKE_VERSION(component, OPAL_MAJOR_VERSION, OPAL_MINOR_VERSION, + OPAL_RELEASE_VERSION), + + .mca_open_component = opal_threads_argobots_open, + }, + .threadsc_data = { + /* The component is checkpoint ready */ + MCA_BASE_METADATA_PARAM_CHECKPOINT + }, +}; + +int opal_threads_argobots_open(void) +{ + ensure_init_argobots(); + return OPAL_SUCCESS; +} diff --git a/opal/mca/threads/argobots/threads_argobots_condition.c b/opal/mca/threads/argobots/threads_argobots_condition.c new file mode 100644 index 00000000000..6e7c2868569 --- /dev/null +++ b/opal/mca/threads/argobots/threads_argobots_condition.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2005 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2019 Sandia National Laboratories. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "opal_config.h" + +#include "opal/mca/threads/condition.h" + + +static void opal_condition_construct(opal_condition_t *c) +{ + c->c_waiting = 0; + c->c_signaled = 0; +} + + +static void opal_condition_destruct(opal_condition_t *c) +{ +} + +OBJ_CLASS_INSTANCE(opal_condition_t, + opal_object_t, + opal_condition_construct, + opal_condition_destruct); diff --git a/opal/mca/threads/argobots/threads_argobots_event.c b/opal/mca/threads/argobots/threads_argobots_event.c new file mode 100644 index 00000000000..98830d27891 --- /dev/null +++ b/opal/mca/threads/argobots/threads_argobots_event.c @@ -0,0 +1,136 @@ + +#include "opal/mca/threads/threads.h" +#include "opal/mca/threads/argobots/threads_argobots.h" +#include "opal/mca/event/libevent2022/libevent/include/event2/thread.h" +#include "opal/mca/event/libevent2022/libevent/include/event2/event-config.h" +#include "opal/mca/event/libevent2022/libevent/include/event2/util.h" + +#include + +static void * +evthread_argobots_lock_alloc(unsigned locktype) +{ + ABT_mutex lock; + if (locktype & EVTHREAD_LOCKTYPE_RECURSIVE) { + ABT_mutex_attr abt_mutex_attr; + ABT_mutex_attr_create(&abt_mutex_attr); + ABT_mutex_attr_set_recursive(abt_mutex_attr, ABT_TRUE); + ABT_mutex_create_with_attr(abt_mutex_attr, &lock); + ABT_mutex_attr_free(&abt_mutex_attr); + } else { + ABT_mutex_create(&lock); + } + return lock; +} + +static void +evthread_argobots_lock_free(void *_lock, unsigned locktype) +{ + ABT_mutex lock = _lock; + ABT_mutex_free(&lock); +} + +static int +evthread_argobots_lock(unsigned mode, void *_lock) +{ + int ret; + ABT_mutex lock = _lock; + if (mode & EVTHREAD_TRY) { + ret = ABT_mutex_trylock(lock); + } else { + ret = ABT_mutex_lock(lock); + } + return ret; +} + +static int +evthread_argobots_unlock(unsigned mode, void *_lock) +{ + ABT_mutex lock = _lock; + int ret = ABT_mutex_unlock(lock); + /* This yield is necessary to avoid taking a lock consecutively. */ + ABT_thread_yield(); + return ret; +} + +static unsigned long +evthread_argobots_get_id(void) +{ + ABT_thread thr; + ABT_thread_self(&thr); + return (unsigned long)((intptr_t)thr); +} + +static void * +evthread_argobots_cond_alloc(unsigned condflags) +{ + ABT_cond cond; + ABT_cond_create(&cond); + return cond; +} + +static void +evthread_argobots_cond_free(void *_cond) +{ + ABT_cond cond = _cond; + ABT_cond_free(&cond); +} + +static int +evthread_argobots_cond_signal(void *_cond, int broadcast) +{ + ABT_cond cond = _cond; + int r; + if (broadcast) + r = ABT_cond_broadcast(cond); + else + r = ABT_cond_signal(cond); + return r ? -1 : 0; +} + +static int +evthread_argobots_cond_wait(void *_cond, void *_lock, const struct timeval *tv) +{ + int r; + ABT_cond cond = _cond; + ABT_mutex lock = _lock; + + if (tv) { + struct timeval now, abstime; + struct timespec ts; + evutil_gettimeofday(&now, NULL); + evutil_timeradd(&now, tv, &abstime); + ts.tv_sec = abstime.tv_sec; + ts.tv_nsec = abstime.tv_usec*1000; + r = ABT_cond_timedwait(cond, lock, &ts); + if (r != 0) + return 1; + else + return 0; + } else { + r = ABT_cond_wait(cond, lock); + return r ? -1 : 0; + } +} + +void opal_event_use_threads(void) { + struct evthread_lock_callbacks cbs = { + EVTHREAD_LOCK_API_VERSION, + EVTHREAD_LOCKTYPE_RECURSIVE, + evthread_argobots_lock_alloc, + evthread_argobots_lock_free, + evthread_argobots_lock, + evthread_argobots_unlock + }; + struct evthread_condition_callbacks cond_cbs = { + EVTHREAD_CONDITION_API_VERSION, + evthread_argobots_cond_alloc, + evthread_argobots_cond_free, + evthread_argobots_cond_signal, + evthread_argobots_cond_wait + }; + ensure_init_argobots(); + evthread_set_lock_callbacks(&cbs); + evthread_set_condition_callbacks(&cond_cbs); + evthread_set_id_callback(evthread_argobots_get_id); +} diff --git a/opal/mca/threads/argobots/threads_argobots_module.c b/opal/mca/threads/argobots/threads_argobots_module.c new file mode 100644 index 00000000000..8587ab0e3e1 --- /dev/null +++ b/opal/mca/threads/argobots/threads_argobots_module.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2005 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ +#include + +#include "opal/mca/threads/argobots/threads_argobots.h" +#include "opal/constants.h" +#include "opal/util/sys_limits.h" +#include "opal/util/output.h" +#include "opal/prefetch.h" +#include "opal/mca/threads/threads.h" +#include "opal/mca/threads/tsd.h" + +#include + +struct opal_tsd_key_value { + opal_tsd_key_t key; + opal_tsd_destructor_t destructor; +}; + +static ABT_thread opal_main_thread; +struct opal_tsd_key_value *opal_tsd_key_values = NULL; +static int opal_tsd_key_values_count = 0; + +/* + * Constructor + */ +static void opal_thread_construct(opal_thread_t *t) +{ + t->t_run = 0; + t->t_handle = ABT_THREAD_NULL; +} + +OBJ_CLASS_INSTANCE(opal_thread_t, + opal_object_t, + opal_thread_construct, NULL); + +static inline ABT_thread opal_thread_get_argobots_self(void) { + ABT_thread self; + ABT_thread_self(&self); + return self; +} + +static void opal_thread_argobots_wrapper(void *arg) { + opal_thread_t *t = (opal_thread_t *) arg; + t->t_ret = ((void*(*)(void*)) t->t_run)(t); +} + +opal_thread_t *opal_thread_get_self(void) +{ + ensure_init_argobots(); + opal_thread_t *t = OBJ_NEW(opal_thread_t); + t->t_handle = opal_thread_get_argobots_self(); + return t; +} + +bool opal_thread_self_compare(opal_thread_t *t) +{ + ensure_init_argobots(); + return t->t_handle == opal_thread_get_argobots_self(); +} + +int opal_thread_join(opal_thread_t *t, void **thr_return) { + ensure_init_argobots(); + int rc = ABT_thread_free(&t->t_handle); + if (thr_return) + *thr_return = t->t_ret; + t->t_handle = ABT_THREAD_NULL; + return (rc == 0) ? OPAL_SUCCESS : OPAL_ERROR; +} + +void opal_thread_set_main() { + ensure_init_argobots(); + opal_main_thread = opal_thread_get_argobots_self(); +} + +int opal_thread_start(opal_thread_t *t) { + ensure_init_argobots(); + int rc; + if (OPAL_ENABLE_DEBUG) { + if (NULL == t->t_run || t->t_handle != ABT_THREAD_NULL) { + return OPAL_ERR_BAD_PARAM; + } + } + + ABT_xstream self_xstream; + ABT_xstream_self(&self_xstream); + rc = ABT_thread_create_on_xstream(self_xstream, + opal_thread_argobots_wrapper, t, + ABT_THREAD_ATTR_NULL, &t->t_handle); + + return (rc == 0) ? OPAL_SUCCESS : OPAL_ERROR; +} + +opal_class_t opal_thread_t_class; + +int opal_tsd_key_create(opal_tsd_key_t *key, opal_tsd_destructor_t destructor) +{ + ensure_init_argobots(); + int rc; + rc = ABT_key_create(destructor, key); + if ((0 == rc) && (opal_thread_get_argobots_self() == opal_main_thread)) { + opal_tsd_key_values = (struct opal_tsd_key_value *)realloc(opal_tsd_key_values, (opal_tsd_key_values_count+1) * sizeof(struct opal_tsd_key_value)); + opal_tsd_key_values[opal_tsd_key_values_count].key = *key; + opal_tsd_key_values[opal_tsd_key_values_count].destructor = destructor; + opal_tsd_key_values_count ++; + } + return rc; +} + +int opal_tsd_keys_destruct() +{ + ensure_init_argobots(); + int i; + void * ptr; + for (i=0; i +#include + +#include "opal/mca/threads/mutex.h" +#include "opal/mca/threads/argobots/threads_argobots_mutex.h" + +/* + * Wait and see if some upper layer wants to use threads, if support + * exists. + */ +bool opal_uses_threads = false; + +static void mca_threads_argobots_mutex_constructor(opal_mutex_t *p_mutex) { + ensure_init_argobots(); + p_mutex->m_lock_argobots = OPAL_ABT_MUTEX_NULL; + p_mutex->m_recursive = 0; +#if OPAL_ENABLE_DEBUG + p_mutex->m_lock_debug = 0; + p_mutex->m_lock_file = NULL; + p_mutex->m_lock_line = 0; +#endif + opal_atomic_lock_init(&p_mutex->m_lock_atomic, 0); +} + +static void mca_threads_argobots_mutex_desctructor(opal_mutex_t *p_mutex) { + ensure_init_argobots(); + if (p_mutex->m_lock_argobots != OPAL_ABT_MUTEX_NULL) + ABT_mutex_free(&p_mutex->m_lock_argobots); +} + +static void mca_threads_argobots_recursive_mutex_constructor + (opal_recursive_mutex_t *p_mutex) { + ensure_init_argobots(); + p_mutex->m_lock_argobots = OPAL_ABT_MUTEX_NULL; + p_mutex->m_recursive = 1; +#if OPAL_ENABLE_DEBUG + p_mutex->m_lock_debug = 0; + p_mutex->m_lock_file = NULL; + p_mutex->m_lock_line = 0; +#endif + opal_atomic_lock_init(&p_mutex->m_lock_atomic, 0); +} + +static void mca_threads_argobots_recursive_mutex_desctructor + (opal_recursive_mutex_t *p_mutex) { + ensure_init_argobots(); + if (p_mutex->m_lock_argobots != OPAL_ABT_MUTEX_NULL) + ABT_mutex_free(&p_mutex->m_lock_argobots); +} + +OBJ_CLASS_INSTANCE(opal_mutex_t, + opal_object_t, + mca_threads_argobots_mutex_constructor, + mca_threads_argobots_mutex_desctructor); +OBJ_CLASS_INSTANCE(opal_recursive_mutex_t, + opal_object_t, + mca_threads_argobots_recursive_mutex_constructor, + mca_threads_argobots_recursive_mutex_desctructor); diff --git a/opal/mca/threads/argobots/threads_argobots_mutex.h b/opal/mca/threads/argobots/threads_argobots_mutex.h new file mode 100644 index 00000000000..72da868f0a6 --- /dev/null +++ b/opal/mca/threads/argobots/threads_argobots_mutex.h @@ -0,0 +1,311 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2006 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2007-2018 Los Alamos National Security, LLC. All rights + * reserved. + * Copyright (c) 2015-2016 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2019 Sandia National Laboratories. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#ifndef OPAL_MCA_THREADS_ARGOBOTS_THREADS_ARGOBOTS_MUTEX_H +#define OPAL_MCA_THREADS_ARGOBOTS_THREADS_ARGOBOTS_MUTEX_H 1 + +/** + * @file: + * + * Mutual exclusion functions: Unix implementation. + * + * Functions for locking of critical sections. + * + * On unix, use Argobots or our own atomic operations as + * available. + */ + +#include "opal/mca/threads/argobots/threads_argobots.h" +#include "opal_config.h" + +#include +#include + +#include "opal/class/opal_object.h" +#include "opal/sys/atomic.h" + +#include + +BEGIN_C_DECLS + +/* Don't use ABT_MUTEX_NULL, since it might be not NULL. */ +#define OPAL_ABT_MUTEX_NULL 0 + +struct opal_mutex_t { + opal_object_t super; + + ABT_mutex m_lock_argobots; + int m_recursive; + +#if OPAL_ENABLE_DEBUG + int m_lock_debug; + const char *m_lock_file; + int m_lock_line; +#endif + + opal_atomic_lock_t m_lock_atomic; +}; + +typedef struct opal_argobots_mutex_t opal_pthread_mutex_t; +typedef struct opal_argobots_mutex_t opal_pthread_recursive_mutex_t; + +OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_mutex_t); +OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_recursive_mutex_t); + +#if OPAL_ENABLE_DEBUG +#define OPAL_MUTEX_STATIC_INIT \ + { \ + .super = OPAL_OBJ_STATIC_INIT(opal_mutex_t), \ + .m_lock_argobots = OPAL_ABT_MUTEX_NULL, \ + .m_recursive = 0, \ + .m_lock_debug = 0, \ + .m_lock_file = NULL, \ + .m_lock_line = 0, \ + .m_lock_atomic = OPAL_ATOMIC_LOCK_INIT, \ + } +#else +#define OPAL_MUTEX_STATIC_INIT \ + { \ + .super = OPAL_OBJ_STATIC_INIT(opal_mutex_t), \ + .m_lock_argobots = OPAL_ABT_MUTEX_NULL, \ + .m_recursive = 0, \ + .m_lock_atomic = OPAL_ATOMIC_LOCK_INIT, \ + } +#endif + +#if defined(OPAL_PTHREAD_RECURSIVE_MUTEX_INITIALIZER) + +#if OPAL_ENABLE_DEBUG +#define OPAL_RECURSIVE_MUTEX_STATIC_INIT \ + { \ + .super = OPAL_OBJ_STATIC_INIT(opal_mutex_t), \ + .m_lock_argobots = OPAL_ABT_MUTEX_NULL, \ + .m_recursive = 1, \ + .m_lock_debug = 0, \ + .m_lock_file = NULL, \ + .m_lock_line = 0, \ + .m_lock_atomic = OPAL_ATOMIC_LOCK_INIT, \ + } +#else +#define OPAL_RECURSIVE_MUTEX_STATIC_INIT \ + { \ + .super = OPAL_OBJ_STATIC_INIT(opal_mutex_t), \ + .m_lock_argobots = OPAL_ABT_MUTEX_NULL, \ + .m_recursive = 1, \ + .m_lock_atomic = OPAL_ATOMIC_LOCK_INIT, \ + } +#endif + +#endif + +/************************************************************************ + * + * mutex operations (non-atomic versions) + * + ************************************************************************/ + +static inline void opal_mutex_create(struct opal_mutex_t *m) { + while (m->m_lock_argobots == OPAL_ABT_MUTEX_NULL) { + ABT_mutex abt_mutex; + if (m->m_recursive) { + ABT_mutex_attr abt_mutex_attr; + ABT_mutex_attr_create(&abt_mutex_attr); + ABT_mutex_attr_set_recursive(abt_mutex_attr, ABT_TRUE); + ABT_mutex_create_with_attr(abt_mutex_attr, &abt_mutex); + ABT_mutex_attr_free(&abt_mutex_attr); + } else { + ABT_mutex_create(&abt_mutex); + } + void *null_ptr = OPAL_ABT_MUTEX_NULL; + if (opal_atomic_compare_exchange_strong_ptr( + (intptr_t *)&m->m_lock_argobots, (intptr_t *)&null_ptr, + (intptr_t)abt_mutex)) { + /* mutex is successfully created and substituted. */ + return; + } + ABT_mutex_free(&abt_mutex); + } +} + +static inline int opal_mutex_trylock(opal_mutex_t *m) +{ + ensure_init_argobots(); + if (m->m_lock_argobots == OPAL_ABT_MUTEX_NULL) + opal_mutex_create(m); +#if OPAL_ENABLE_DEBUG + int ret = ABT_mutex_trylock(m->m_lock_argobots); + if (ret != 0) { + errno = ret; + perror("opal_mutex_trylock()"); + abort(); + } + return ret; +#else + return ABT_mutex_trylock(m->m_lock_argobots); +#endif +} + +static inline void opal_mutex_lock(opal_mutex_t *m) +{ + ensure_init_argobots(); + if (m->m_lock_argobots == OPAL_ABT_MUTEX_NULL) + opal_mutex_create(m); +#if OPAL_ENABLE_DEBUG + int ret = ABT_mutex_lock(m->m_lock_argobots); + if (ret != 0) { + errno = ret; + perror("opal_mutex_lock()"); + abort(); + } +#else + ABT_mutex_lock(m->m_lock_argobots); +#endif +} + +static inline void opal_mutex_unlock(opal_mutex_t *m) +{ + ensure_init_argobots(); + if (m->m_lock_argobots == OPAL_ABT_MUTEX_NULL) + opal_mutex_create(m); +#if OPAL_ENABLE_DEBUG + int ret = ABT_mutex_unlock(m->m_lock_argobots); + if (ret != 0) { + errno = ret; + perror("opal_mutex_unlock"); + abort(); + } +#else + ABT_mutex_unlock(m->m_lock_argobots); +#endif + /* For fairness of locking. */ + ABT_thread_yield(); +} + +/************************************************************************ + * + * mutex operations (atomic versions) + * + ************************************************************************/ + +#if OPAL_HAVE_ATOMIC_SPINLOCKS + +/************************************************************************ + * Spin Locks + ************************************************************************/ + +static inline int opal_mutex_atomic_trylock(opal_mutex_t *m) +{ + return opal_atomic_trylock(&m->m_lock_atomic); +} + +static inline void opal_mutex_atomic_lock(opal_mutex_t *m) +{ + opal_atomic_lock(&m->m_lock_atomic); +} + +static inline void opal_mutex_atomic_unlock(opal_mutex_t *m) +{ + opal_atomic_unlock(&m->m_lock_atomic); +} + +#else + +/************************************************************************ + * Standard locking + ************************************************************************/ + +static inline int opal_mutex_atomic_trylock(opal_mutex_t *m) +{ + return opal_mutex_trylock(m); +} + +static inline void opal_mutex_atomic_lock(opal_mutex_t *m) +{ + opal_mutex_lock(m); +} + +static inline void opal_mutex_atomic_unlock(opal_mutex_t *m) +{ + opal_mutex_unlock(m); +} + +#endif + +#define OPAL_ABT_COND_NULL NULL +typedef ABT_cond opal_cond_t; +#define OPAL_CONDITION_STATIC_INIT OPAL_ABT_COND_NULL + +static inline void opal_cond_create(opal_cond_t *cond) { + ensure_init_argobots(); + while (*cond == OPAL_ABT_COND_NULL) { + ABT_cond new_cond; + ABT_cond_create(&new_cond); + void *null_ptr = OPAL_ABT_COND_NULL; + if (opal_atomic_compare_exchange_strong_ptr((intptr_t *)cond, + (intptr_t *)&null_ptr, + (intptr_t)new_cond)) { + /* cond is successfully created and substituted. */ + return; + } + ABT_cond_free(&new_cond); + } +} + +static inline int opal_cond_init(opal_cond_t *cond) { + *cond = OPAL_ABT_COND_NULL; + return 0; +} + +static inline int opal_cond_wait(opal_cond_t *cond, opal_mutex_t *lock) { + ensure_init_argobots(); + if (*cond == OPAL_ABT_COND_NULL) + opal_cond_create(cond); + return ABT_cond_wait(*cond, lock->m_lock_argobots); +} + +static inline int opal_cond_broadcast(opal_cond_t *cond) { + ensure_init_argobots(); + if (*cond == OPAL_ABT_COND_NULL) + opal_cond_create(cond); + return ABT_cond_broadcast(*cond); +} + +static inline int opal_cond_signal(opal_cond_t *cond) { + ensure_init_argobots(); + if (*cond == OPAL_ABT_COND_NULL) + opal_cond_create(cond); + return ABT_cond_signal(*cond); +} + +static inline int opal_cond_destroy(opal_cond_t *cond) { + ensure_init_argobots(); + if (*cond != OPAL_ABT_COND_NULL) + ABT_cond_free(cond); + return 0; +} + +END_C_DECLS + +#endif /* OPAL_MCA_THREADS_ARGOBOTS_THREADS_ARGOBOTS_MUTEX_H */ diff --git a/opal/mca/threads/argobots/threads_argobots_threads.h b/opal/mca/threads/argobots/threads_argobots_threads.h new file mode 100644 index 00000000000..5a7d7a772c7 --- /dev/null +++ b/opal/mca/threads/argobots/threads_argobots_threads.h @@ -0,0 +1,16 @@ + +#ifndef OPAL_MCA_THREADS_ARGOBOTS_THREADS_ARGOBOTS_THREADS_H +#define OPAL_MCA_THREADS_ARGOBOTS_THREADS_ARGOBOTS_THREADS_H 1 + +#include +#include + +struct opal_thread_t { + opal_object_t super; + opal_thread_fn_t t_run; + void* t_arg; + ABT_thread t_handle; + void* t_ret; +}; + +#endif /* OPAL_MCA_THREADS_ARGOBOTS_THREADS_ARGOBOTS_THREADS_H */ diff --git a/opal/mca/threads/argobots/threads_argobots_tsd.h b/opal/mca/threads/argobots/threads_argobots_tsd.h new file mode 100644 index 00000000000..290adadfde3 --- /dev/null +++ b/opal/mca/threads/argobots/threads_argobots_tsd.h @@ -0,0 +1,32 @@ + +#ifndef OPAL_MCA_THREADS_ARGOBOTS_THREADS_ARGOBOTS_TSD_H +#define OPAL_MCA_THREADS_ARGOBOTS_THREADS_ARGOBOTS_TSD_H 1 + +#include "opal/mca/threads/argobots/threads_argobots.h" +#include + +typedef ABT_key opal_tsd_key_t; + +static inline int +opal_tsd_key_delete(opal_tsd_key_t key) +{ + ensure_init_argobots(); + return ABT_key_free(&key); +} + +static inline int +opal_tsd_setspecific(opal_tsd_key_t key, void *value) +{ + ensure_init_argobots(); + return ABT_key_set(key, value); +} + +static inline int +opal_tsd_getspecific(opal_tsd_key_t key, void **valuep) +{ + ensure_init_argobots(); + ABT_key_get(key, valuep); + return OPAL_SUCCESS; +} + +#endif /* OPAL_MCA_THREADS_ARGOBOTS_THREADS_ARGOBOTS_TSD_H */ diff --git a/opal/mca/threads/argobots/threads_argobots_wait_sync.c b/opal/mca/threads/argobots/threads_argobots_wait_sync.c new file mode 100644 index 00000000000..dddb7eafbf7 --- /dev/null +++ b/opal/mca/threads/argobots/threads_argobots_wait_sync.c @@ -0,0 +1,112 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ +/* + * Copyright (c) 2014-2016 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2016 Los Alamos National Security, LLC. All rights + * reserved. + * Copyright (c) 2017 IBM Corporation. All rights reserved. + * Copyright (c) 2019 Sandia National Laboratories. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ +#include "opal/mca/threads/argobots/threads_argobots.h" +#include "opal/mca/threads/wait_sync.h" + +static opal_mutex_t wait_sync_lock = OPAL_MUTEX_STATIC_INIT; +static ompi_wait_sync_t* wait_sync_list = NULL; + +static opal_atomic_int32_t num_thread_in_progress = 0; + +#define WAIT_SYNC_PASS_OWNERSHIP(who) \ + do { \ + ensure_init_argobots(); \ + ABT_mutex_lock((who)->lock); \ + ABT_cond_signal((who)->condition ); \ + ABT_mutex_unlock((who)->lock); \ + } while(0) + +int ompi_sync_wait_mt(ompi_wait_sync_t *sync) +{ + ensure_init_argobots(); + /* Don't stop if the waiting synchronization is completed. We avoid the + * race condition around the release of the synchronization using the + * signaling field. + */ + if(sync->count <= 0) + return (0 == sync->status) ? OPAL_SUCCESS : OPAL_ERROR; + + /* lock so nobody can signal us during the list updating */ + ABT_mutex_lock(sync->lock); + + /* Now that we hold the lock make sure another thread has not already + * call cond_signal. + */ + if(sync->count <= 0) { + ABT_mutex_unlock(sync->lock); + return (0 == sync->status) ? OPAL_SUCCESS : OPAL_ERROR; + } + + /* Insert sync on the list of pending synchronization constructs */ + OPAL_THREAD_LOCK(&wait_sync_lock); + if( NULL == wait_sync_list ) { + sync->next = sync->prev = sync; + wait_sync_list = sync; + } else { + sync->prev = wait_sync_list->prev; + sync->prev->next = sync; + sync->next = wait_sync_list; + wait_sync_list->prev = sync; + } + OPAL_THREAD_UNLOCK(&wait_sync_lock); + + /** + * If we are not responsible for progresing, go silent until something worth noticing happen: + * - this thread has been promoted to take care of the progress + * - our sync has been triggered. + */ + check_status: + if( sync != wait_sync_list && num_thread_in_progress >= opal_max_thread_in_progress) { + ABT_cond_wait(sync->condition, sync->lock); + + /** + * At this point either the sync was completed in which case + * we should remove it from the wait list, or/and I was + * promoted as the progress manager. + */ + + if( sync->count <= 0 ) { /* Completed? */ + ABT_mutex_unlock(sync->lock); + goto i_am_done; + } + /* either promoted, or spurious wakeup ! */ + goto check_status; + } + ABT_mutex_unlock(sync->lock); + + OPAL_THREAD_ADD_FETCH32(&num_thread_in_progress, 1); + while(sync->count > 0) { /* progress till completion */ + opal_progress(); /* don't progress with the sync lock locked or you'll deadlock */ + ABT_thread_yield(); + } + OPAL_THREAD_ADD_FETCH32(&num_thread_in_progress, -1); + + i_am_done: + /* My sync is now complete. Trim the list: remove self, wake next */ + OPAL_THREAD_LOCK(&wait_sync_lock); + sync->prev->next = sync->next; + sync->next->prev = sync->prev; + /* In case I am the progress manager, pass the duties on */ + if( sync == wait_sync_list ) { + wait_sync_list = (sync == sync->next) ? NULL : sync->next; + if( NULL != wait_sync_list ) + WAIT_SYNC_PASS_OWNERSHIP(wait_sync_list); + } + OPAL_THREAD_UNLOCK(&wait_sync_lock); + + return (0 == sync->status) ? OPAL_SUCCESS : OPAL_ERROR; +} diff --git a/opal/mca/threads/argobots/threads_argobots_wait_sync.h b/opal/mca/threads/argobots/threads_argobots_wait_sync.h new file mode 100644 index 00000000000..dbe443db550 --- /dev/null +++ b/opal/mca/threads/argobots/threads_argobots_wait_sync.h @@ -0,0 +1,87 @@ + +#ifndef OPAL_MCA_THREADS_ARGOBOTS_THREADS_ARGOBOTS_WAIT_SYNC_H +#define OPAL_MCA_THREADS_ARGOBOTS_THREADS_ARGOBOTS_WAIT_SYNC_H 1 + +#include "opal/mca/threads/argobots/threads_argobots.h" +#include + +typedef struct ompi_wait_sync_t { + opal_atomic_int32_t count; + int32_t status; + ABT_cond condition; + ABT_mutex lock; + struct ompi_wait_sync_t *next; + struct ompi_wait_sync_t *prev; + volatile bool signaling; +} ompi_wait_sync_t; + +#define SYNC_WAIT(sync) (opal_using_threads() ? ompi_sync_wait_mt (sync) : sync_wait_st (sync)) + +/* The loop in release handles a race condition between the signaling + * thread and the destruction of the condition variable. The signaling + * member will be set to false after the final signaling thread has + * finished operating on the sync object. This is done to avoid + * extra atomics in the signalling function and keep it as fast + * as possible. Note that the race window is small so spinning here + * is more optimal than sleeping since this macro is called in + * the critical path. */ +#define WAIT_SYNC_RELEASE(sync) \ + if (opal_using_threads()) { \ + ensure_init_argobots(); \ + while ((sync)->signaling) { \ + ABT_thread_yield(); \ + continue; \ + } \ + ABT_cond_free(&(sync)->condition); \ + ABT_mutex_free(&(sync)->lock); \ + } + +#define WAIT_SYNC_RELEASE_NOWAIT(sync) \ + if (opal_using_threads()) { \ + ensure_init_argobots(); \ + ABT_cond_free(&(sync)->condition); \ + ABT_mutex_free(&(sync)->lock); \ + } + + +#define WAIT_SYNC_SIGNAL(sync) \ + if (opal_using_threads()) { \ + ensure_init_argobots(); \ + ABT_mutex_lock(sync->lock); \ + ABT_cond_signal(sync->condition); \ + ABT_mutex_unlock(sync->lock); \ + sync->signaling = false; \ + } + +#define WAIT_SYNC_SIGNALLED(sync){ \ + (sync)->signaling = false; \ +} + +OPAL_DECLSPEC int ompi_sync_wait_mt(ompi_wait_sync_t *sync); +static inline int sync_wait_st (ompi_wait_sync_t *sync) +{ + ensure_init_argobots(); + while (sync->count > 0) { + opal_progress(); + ABT_thread_yield(); + } + + return sync->status; +} + + +#define WAIT_SYNC_INIT(sync,c) \ + do { \ + (sync)->count = (c); \ + (sync)->next = NULL; \ + (sync)->prev = NULL; \ + (sync)->status = 0; \ + (sync)->signaling = (0 != (c)); \ + if (opal_using_threads()) { \ + ensure_init_argobots(); \ + ABT_cond_create (&(sync)->condition); \ + ABT_mutex_create (&(sync)->lock); \ + } \ + } while(0) + +#endif /* OPAL_MCA_THREADS_ARGOBOTS_THREADS_ARGOBOTS_WAIT_SYNC_H */ diff --git a/opal/mca/threads/base/Makefile.am b/opal/mca/threads/base/Makefile.am new file mode 100644 index 00000000000..d0e6710ce01 --- /dev/null +++ b/opal/mca/threads/base/Makefile.am @@ -0,0 +1,25 @@ +# +# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana +# University Research and Technology +# Corporation. All rights reserved. +# Copyright (c) 2004-2005 The University of Tennessee and The University +# of Tennessee Research Foundation. All rights +# reserved. +# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, +# University of Stuttgart. All rights reserved. +# Copyright (c) 2004-2005 The Regents of the University of California. +# All rights reserved. +# Copyright (c) 2019 Sandia National Laboratories. All rights reserved. +# +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +headers += \ + base/base.h + +libmca_threads_la_SOURCES += \ + base/threads_base_open.c diff --git a/opal/mca/threads/base/base.h b/opal/mca/threads/base/base.h new file mode 100644 index 00000000000..3af4d834a71 --- /dev/null +++ b/opal/mca/threads/base/base.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2014 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2014 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2019 Sandia National Laboratories. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + * + */ + +#ifndef OPAL_THREADS_BASE_H +#define OPAL_THREADS_BASE_H + +#include "opal_config.h" +#include "opal/mca/base/mca_base_framework.h" +#include "opal/mca/threads/threads.h" + + +/* + * Global functions for MCA overall threads open and close + */ + +BEGIN_C_DECLS + +/** + * Framework structure declaration + */ +OPAL_DECLSPEC extern mca_base_framework_t opal_threads_base_framework; + +END_C_DECLS + +/* include implementation to call */ +#include MCA_threads_IMPLEMENTATION_HEADER + +#endif /* OPAL_BASE_THREADS_H */ diff --git a/opal/mca/threads/base/owner.txt b/opal/mca/threads/base/owner.txt new file mode 100644 index 00000000000..340dd610b4f --- /dev/null +++ b/opal/mca/threads/base/owner.txt @@ -0,0 +1,7 @@ +# +# owner/status file +# owner: institution that is responsible for this package +# status: e.g. active, maintenance, unmaintained +# +owner: SNL +status: maintenance diff --git a/opal/mca/threads/base/threads_base_open.c b/opal/mca/threads/base/threads_base_open.c new file mode 100644 index 00000000000..1e15851cec5 --- /dev/null +++ b/opal/mca/threads/base/threads_base_open.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2014 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2014 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2019 Sandia National Laboratories. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + + +#include "opal_config.h" + +#include "opal/constants.h" +#include "opal/mca/threads/base/base.h" + + +/* + * The following file was created by configure. It contains extern + * statements and the definition of an array of pointers to each + * component's public mca_base_component_t struct. + */ +#include "opal/mca/threads/base/static-components.h" + +static int mca_threads_base_register(mca_base_register_flag_t flags) +{ + // Do I need to register anything here? + return OPAL_SUCCESS; +} + +/* + * Globals + */ +/* Use default register/open/close functions */ +MCA_BASE_FRAMEWORK_DECLARE(opal, threads, "OPAL OS threads", mca_threads_base_register, NULL, NULL, + mca_threads_base_static_components, 0); diff --git a/opal/mca/threads/condition.h b/opal/mca/threads/condition.h new file mode 100644 index 00000000000..3456bde692a --- /dev/null +++ b/opal/mca/threads/condition.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2005 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2007 Los Alamos National Security, LLC. All rights + * reserved. + * Copyright (c) 2015 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2019 Sandia National Laboratories. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ +#ifndef OPAL_MCA_CONDITION_SPINLOCK_H +#define OPAL_MCA_CONDITION_SPINLOCK_H + +#include "opal_config.h" +#ifdef HAVE_SYS_TIME_H +#include +#endif +#include +#include + +#include "opal/threads/mutex.h" +#include "opal/runtime/opal_progress.h" + +#include "opal/runtime/opal_cr.h" + +BEGIN_C_DECLS + +/* + * Combine pthread support w/ polled progress to allow run-time selection + * of threading vs. non-threading progress. + */ + +struct opal_condition_t { + opal_object_t super; + volatile int c_waiting; + volatile int c_signaled; +}; +typedef struct opal_condition_t opal_condition_t; + +OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_condition_t); + + +static inline int opal_condition_wait(opal_condition_t *c, opal_mutex_t *m) +{ + int rc = 0; + c->c_waiting++; + + if (opal_using_threads()) { + if (c->c_signaled) { + c->c_waiting--; + opal_mutex_unlock(m); + opal_progress(); + OPAL_CR_TEST_CHECKPOINT_READY_STALL(); + opal_mutex_lock(m); + return 0; + } + while (c->c_signaled == 0) { + opal_mutex_unlock(m); + opal_progress(); + OPAL_CR_TEST_CHECKPOINT_READY_STALL(); + opal_mutex_lock(m); + } + } else { + while (c->c_signaled == 0) { + opal_progress(); + OPAL_CR_TEST_CHECKPOINT_READY_STALL(); + } + } + + c->c_signaled--; + c->c_waiting--; + return rc; +} + +static inline int opal_condition_timedwait(opal_condition_t *c, + opal_mutex_t *m, + const struct timespec *abstime) +{ + struct timeval tv; + struct timeval absolute; + int rc = 0; + + c->c_waiting++; + if (opal_using_threads()) { + absolute.tv_sec = abstime->tv_sec; + absolute.tv_usec = abstime->tv_nsec / 1000; + gettimeofday(&tv,NULL); + if (c->c_signaled == 0) { + do { + opal_mutex_unlock(m); + opal_progress(); + gettimeofday(&tv,NULL); + opal_mutex_lock(m); + } while (c->c_signaled == 0 && + (tv.tv_sec <= absolute.tv_sec || + (tv.tv_sec == absolute.tv_sec && tv.tv_usec < absolute.tv_usec))); + } + } else { + absolute.tv_sec = abstime->tv_sec; + absolute.tv_usec = abstime->tv_nsec / 1000; + gettimeofday(&tv,NULL); + if (c->c_signaled == 0) { + do { + opal_progress(); + gettimeofday(&tv,NULL); + } while (c->c_signaled == 0 && + (tv.tv_sec <= absolute.tv_sec || + (tv.tv_sec == absolute.tv_sec && tv.tv_usec < absolute.tv_usec))); + } + } + + if (c->c_signaled != 0) c->c_signaled--; + c->c_waiting--; + return rc; +} + +static inline int opal_condition_signal(opal_condition_t *c) +{ + if (c->c_waiting) { + c->c_signaled++; + } + return 0; +} + +static inline int opal_condition_broadcast(opal_condition_t *c) +{ + c->c_signaled = c->c_waiting; + return 0; +} + +END_C_DECLS + +#endif // OPAL_MCA_CONDITION_SPINLOCK_H + diff --git a/opal/mca/threads/configure.m4 b/opal/mca/threads/configure.m4 new file mode 100644 index 00000000000..b35ce36a3b2 --- /dev/null +++ b/opal/mca/threads/configure.m4 @@ -0,0 +1,55 @@ +dnl -*- shell-script -*- +dnl +dnl Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana +dnl University Research and Technology +dnl Corporation. All rights reserved. +dnl Copyright (c) 2004-2005 The University of Tennessee and The University +dnl of Tennessee Research Foundation. All rights +dnl reserved. +dnl Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, +dnl University of Stuttgart. All rights reserved. +dnl Copyright (c) 2004-2005 The Regents of the University of California. +dnl All rights reserved. +dnl Copyright (c) 2010 Cisco Systems, Inc. All rights reserved. +dnl Copyright (c) 2019 Sandia National Laboratories. All rights reserved. +dnl $COPYRIGHT$ +dnl +dnl Additional copyrights may follow +dnl +dnl $HEADER$ +dnl + +dnl we only want one :) +m4_define(MCA_opal_threads_CONFIGURE_MODE, STOP_AT_FIRST) + +AC_DEFINE_UNQUOTED([OPAL_ENABLE_MULTI_THREADS], [1], + [Whether we should enable thread support within the OPAL code base]) +AC_DEFUN([MCA_opal_threads_CONFIG],[ + thread_type=$HAVE_THREAD_PKG_TYPE + threads_base_include= + mutex_base_include= + + # first, compile all the components + MCA_CONFIGURE_FRAMEWORK($1, $2, 1) + + threads_base_include="${thread_type}/threads_${thread_type}_threads.h" + mutex_base_include="${thread_type}/threads_${thread_type}_mutex.h" + tsd_base_include="${thread_type}/threads_${thread_type}_tsd.h" + wait_sync_base_include="${thread_type}/threads_${thread_type}_wait_sync.h" + + AC_DEFINE_UNQUOTED([MCA_threads_IMPLEMENTATION_HEADER], + ["opal/mca/threads/$threads_base_include"], + [Header to include for threads implementation]) + + AC_DEFINE_UNQUOTED([MCA_mutex_IMPLEMENTATION_HEADER], + ["opal/mca/threads/$mutex_base_include"], + [Header to include for mutex implementation]) + + AC_DEFINE_UNQUOTED([MCA_tsd_IMPLEMENTATION_HEADER], + ["opal/mca/threads/$tsd_base_include"], + [Header to include for tsd implementation]) + + AC_DEFINE_UNQUOTED([MCA_wait_sync_IMPLEMENTATION_HEADER], + ["opal/mca/threads/$wait_sync_base_include"], + [Header to include for wait_sync implementation]) +]) diff --git a/opal/mca/threads/mutex.h b/opal/mca/threads/mutex.h new file mode 100644 index 00000000000..d0228c98dfb --- /dev/null +++ b/opal/mca/threads/mutex.h @@ -0,0 +1,193 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2016 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2007-2016 Los Alamos National Security, LLC. All rights + * reserved. + * Copyright (c) 2007 Voltaire. All rights reserved. + * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019 Sandia National Laboratories. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#ifndef OPAL_MCA_MUTEX_H +#define OPAL_MCA_MUTEX_H 1 + +#include "opal_config.h" + +BEGIN_C_DECLS + +/** +* @file: + * + * Mutual exclusion functions. + * + * Functions for locking of critical sections. + */ + +/** + * Opaque mutex object + */ + +typedef struct opal_mutex_t opal_mutex_t; +typedef struct opal_mutex_t opal_recursive_mutex_t; + +#include MCA_mutex_IMPLEMENTATION_HEADER + +OBJ_CLASS_DECLARATION(opal_mutex_t); +OBJ_CLASS_DECLARATION(opal_recursive_mutex_t); + + +/** + * Try to acquire a mutex. + * + * @param mutex Address of the mutex. + * @return 0 if the mutex was acquired, 1 otherwise. + */ +static inline int opal_mutex_trylock(opal_mutex_t *mutex); + + +/** + * Acquire a mutex. + * + * @param mutex Address of the mutex. + */ +static inline void opal_mutex_lock(opal_mutex_t *mutex); + + +/** + * Release a mutex. + * + * @param mutex Address of the mutex. + */ +static inline void opal_mutex_unlock(opal_mutex_t *mutex); + + +/** + * Try to acquire a mutex using atomic operations. + * + * @param mutex Address of the mutex. + * @return 0 if the mutex was acquired, 1 otherwise. + */ +static inline int opal_mutex_atomic_trylock(opal_mutex_t *mutex); + + +/** + * Acquire a mutex using atomic operations. + * + * @param mutex Address of the mutex. + */ +static inline void opal_mutex_atomic_lock(opal_mutex_t *mutex); + + +/** + * Release a mutex using atomic operations. + * + * @param mutex Address of the mutex. + */ +static inline void opal_mutex_atomic_unlock(opal_mutex_t *mutex); + + +/** + * Lock a mutex if opal_using_threads() says that multiple threads may + * be active in the process. + * + * @param mutex Pointer to a opal_mutex_t to lock. + * + * If there is a possibility that multiple threads are running in the + * process (as determined by opal_using_threads()), this function will + * block waiting to lock the mutex. + * + * If there is no possibility that multiple threads are running in the + * process, return immediately. + */ +#define OPAL_THREAD_LOCK(mutex) \ + do { \ + if (OPAL_UNLIKELY(opal_using_threads())) { \ + opal_mutex_lock(mutex); \ + } \ + } while (0) + + +/** + * Try to lock a mutex if opal_using_threads() says that multiple + * threads may be active in the process. + * + * @param mutex Pointer to a opal_mutex_t to trylock + * + * If there is a possibility that multiple threads are running in the + * process (as determined by opal_using_threads()), this function will + * trylock the mutex. + * + * If there is no possibility that multiple threads are running in the + * process, return immediately without modifying the mutex. + * + * Returns 0 if mutex was locked, non-zero otherwise. + */ +#define OPAL_THREAD_TRYLOCK(mutex) \ + (OPAL_UNLIKELY(opal_using_threads()) ? opal_mutex_trylock(mutex) : 0) + +/** + * Unlock a mutex if opal_using_threads() says that multiple threads + * may be active in the process. + * + * @param mutex Pointer to a opal_mutex_t to unlock. + * + * If there is a possibility that multiple threads are running in the + * process (as determined by opal_using_threads()), this function will + * unlock the mutex. + * + * If there is no possibility that multiple threads are running in the + * process, return immediately without modifying the mutex. + */ +#define OPAL_THREAD_UNLOCK(mutex) \ + do { \ + if (OPAL_UNLIKELY(opal_using_threads())) { \ + opal_mutex_unlock(mutex); \ + } \ + } while (0) + + +/** + * Lock a mutex if opal_using_threads() says that multiple threads may + * be active in the process for the duration of the specified action. + * + * @param mutex Pointer to a opal_mutex_t to lock. + * @param action A scope over which the lock is held. + * + * If there is a possibility that multiple threads are running in the + * process (as determined by opal_using_threads()), this function will + * acquire the lock before invoking the specified action and release + * it on return. + * + * If there is no possibility that multiple threads are running in the + * process, invoke the action without acquiring the lock. + */ +#define OPAL_THREAD_SCOPED_LOCK(mutex, action) \ + do { \ + if(OPAL_UNLIKELY(opal_using_threads())) { \ + opal_mutex_lock(mutex); \ + action; \ + opal_mutex_unlock(mutex); \ + } else { \ + action; \ + } \ + } while (0) + +END_C_DECLS + +#endif /* OPAL_MCA_MUTEX_H */ diff --git a/opal/mca/threads/pthreads/Makefile.am b/opal/mca/threads/pthreads/Makefile.am new file mode 100644 index 00000000000..833950d5e17 --- /dev/null +++ b/opal/mca/threads/pthreads/Makefile.am @@ -0,0 +1,32 @@ +# +# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana +# University Research and Technology +# Corporation. All rights reserved. +# Copyright (c) 2004-2005 The University of Tennessee and The University +# of Tennessee Research Foundation. All rights +# reserved. +# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, +# University of Stuttgart. All rights reserved. +# Copyright (c) 2004-2005 The Regents of the University of California. +# All rights reserved. +# Copyright (c) 2008 Cisco Systems, Inc. All rights reserved. +# Copyright (c) 2019 Sandia National Laboratories. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +noinst_LTLIBRARIES = libmca_threads_pthreads.la + +libmca_threads_pthreads_la_SOURCES = \ + threads_pthreads_component.c \ + threads_pthreads_condition.c \ + threads_pthreads_module.c \ + threads_pthreads_mutex.c \ + threads_pthreads_mutex.h \ + threads_pthreads_threads.h \ + threads_pthreads_tsd.h \ + threads_pthreads_wait_sync.c \ + threads_pthreads_wait_sync.h diff --git a/opal/mca/threads/pthreads/configure.m4 b/opal/mca/threads/pthreads/configure.m4 new file mode 100644 index 00000000000..f0ca42683ce --- /dev/null +++ b/opal/mca/threads/pthreads/configure.m4 @@ -0,0 +1,62 @@ +# -*- shell-script -*- +# +# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana +# University Research and Technology +# Corporation. All rights reserved. +# Copyright (c) 2004-2005 The University of Tennessee and The University +# of Tennessee Research Foundation. All rights +# reserved. +# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, +# University of Stuttgart. All rights reserved. +# Copyright (c) 2004-2005 The Regents of the University of California. +# All rights reserved. +# Copyright (c) 2010 Cisco Systems, Inc. All rights reserved. +# Copyright (c) 2015 Research Organization for Information Science +# and Technology (RIST). All rights reserved. +# Copyright (c) 2019 Sandia National Laboratories. All rights reserved. +# Copyright (c) 2019 Triad National Security, LLC. All rights +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# +AC_DEFUN([MCA_opal_threads_pthreads_PRIORITY], [30]) + +AC_DEFUN([MCA_opal_threads_pthreads_COMPILE_MODE], [ + AC_MSG_CHECKING([for MCA component $2:$3 compile mode]) + $4="static" + AC_MSG_RESULT([$$4]) +]) + +AC_DEFUN([MCA_opal_threads_pthreads_POST_CONFIG],[ + AS_IF([test "$1" = "1"], [threads_base_include="pthreads/threads_pthreads_threads.h"]) +])dnl + +AC_DEFUN([MCA_opal_mutex_pthreads_POST_CONFIG],[ + AS_IF([test "$1" = "1"], [mutex_base_include="pthreads/threads_pthreads_mutex.h"]) + AC_MSG_CHECKING([mutex_base_include = $mutex_base_include]) +])dnl + +AC_DEFUN([MCA_opal_tsd_pthreads_POST_CONFIG],[ + AS_IF([test "$1" = "1"], [threads_base_include="pthreads/threads_pthreads_tsd.h"]) + AC_MSG_CHECKING([threads_base_include = $threads_base_include]) +])dnl + +AC_DEFUN([MCA_opal_wait_sync_pthreads_POST_CONFIG],[ + AS_IF([test "$1" = "1"], [wait_sync_base_include="pthreads/threads_pthreads_wait_sync.h"]) + AC_MSG_CHECKING([wait_sync_includenclude = $wait_sync_base_include]) +])dnl + +# MCA_threads_pthreads_CONFIG(action-if-can-compile, +# [action-if-cant-compile]) +# ------------------------------------------------ +AC_DEFUN([MCA_opal_threads_pthreads_CONFIG],[ + AC_CONFIG_FILES([opal/mca/threads/pthreads/Makefile]) + + AC_MSG_CHECKING([HAVE_THREAD_PKG_TYPE = $HAVE_THREAD_PKG_TYPE]) + + AS_IF([test "$HAVE_THREAD_PKG_TYPE" = "pthreads"], + [$1], + [$2]) +]) diff --git a/opal/mca/threads/pthreads/owner.txt b/opal/mca/threads/pthreads/owner.txt new file mode 100644 index 00000000000..199577ac8cf --- /dev/null +++ b/opal/mca/threads/pthreads/owner.txt @@ -0,0 +1,7 @@ +# +# owner/status file +# owner: institution that is responsible for this package +# status: e.g. active, maintenance, unmaintained +# +owner: SNL +status: unmaintained diff --git a/opal/mca/threads/pthreads/threads_pthreads_component.c b/opal/mca/threads/pthreads/threads_pthreads_component.c new file mode 100644 index 00000000000..938497c02d1 --- /dev/null +++ b/opal/mca/threads/pthreads/threads_pthreads_component.c @@ -0,0 +1,54 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ +/* + * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2014 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2007-2015 Los Alamos National Security, LLC. All rights + * reserved. + * Copyright (c) 2019 Sandia National Laboratories. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "opal_config.h" + +#include "opal/mca/threads/thread.h" +#include "opal/mca/threads/threads.h" +#include "opal/constants.h" + +static int opal_threads_pthreads_open(void); + +const opal_threads_base_component_2_0_0_t mca_threads_pthreads_component = { + /* First, the mca_component_t struct containing meta information + about the component itself */ + .threadsc_version = { + OPAL_THREADS_BASE_VERSION_2_0_0, + + /* Component name and version */ + .mca_component_name = "pthreads", + MCA_BASE_MAKE_VERSION(component, OPAL_MAJOR_VERSION, OPAL_MINOR_VERSION, + OPAL_RELEASE_VERSION), + + .mca_open_component = opal_threads_pthreads_open, + }, + .threadsc_data = { + /* The component is checkpoint ready */ + MCA_BASE_METADATA_PARAM_CHECKPOINT + }, +}; + +int opal_threads_pthreads_open(void) +{ + return OPAL_SUCCESS; +} diff --git a/opal/mca/threads/pthreads/threads_pthreads_condition.c b/opal/mca/threads/pthreads/threads_pthreads_condition.c new file mode 100644 index 00000000000..6e7c2868569 --- /dev/null +++ b/opal/mca/threads/pthreads/threads_pthreads_condition.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2005 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2019 Sandia National Laboratories. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "opal_config.h" + +#include "opal/mca/threads/condition.h" + + +static void opal_condition_construct(opal_condition_t *c) +{ + c->c_waiting = 0; + c->c_signaled = 0; +} + + +static void opal_condition_destruct(opal_condition_t *c) +{ +} + +OBJ_CLASS_INSTANCE(opal_condition_t, + opal_object_t, + opal_condition_construct, + opal_condition_destruct); diff --git a/opal/threads/thread.c b/opal/mca/threads/pthreads/threads_pthreads_module.c similarity index 79% rename from opal/threads/thread.c rename to opal/mca/threads/pthreads/threads_pthreads_module.c index 2d67fa2d693..7d2ae55965a 100644 --- a/opal/threads/thread.c +++ b/opal/mca/threads/pthreads/threads_pthreads_module.c @@ -9,41 +9,30 @@ * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. - * Copyright (c) 2010 Cisco Systems, Inc. All rights reserved. - * Copyright (c) 2015-2017 Research Organization for Information Science - * and Technology (RIST). All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ */ +#include -#include "opal_config.h" - -#include "opal/threads/threads.h" -#include "opal/threads/tsd.h" #include "opal/constants.h" - -bool opal_debug_threads = false; - -static void opal_thread_construct(opal_thread_t *t); - -static pthread_t opal_main_thread; +#include "opal/util/sys_limits.h" +#include "opal/util/output.h" +#include "opal/prefetch.h" +#include "opal/mca/threads/threads.h" +#include "opal/mca/threads/tsd.h" struct opal_tsd_key_value { opal_tsd_key_t key; opal_tsd_destructor_t destructor; }; -static struct opal_tsd_key_value *opal_tsd_key_values = NULL; +static pthread_t opal_main_thread; +struct opal_tsd_key_value *opal_tsd_key_values = NULL; static int opal_tsd_key_values_count = 0; -OBJ_CLASS_INSTANCE(opal_thread_t, - opal_object_t, - opal_thread_construct, NULL); - - /* * Constructor */ @@ -53,50 +42,51 @@ static void opal_thread_construct(opal_thread_t *t) t->t_handle = (pthread_t) -1; } -int opal_thread_start(opal_thread_t *t) -{ - int rc; - - if (OPAL_ENABLE_DEBUG) { - if (NULL == t->t_run || t->t_handle != (pthread_t) -1) { - return OPAL_ERR_BAD_PARAM; - } - } +OBJ_CLASS_INSTANCE(opal_thread_t, + opal_object_t, + opal_thread_construct, NULL); + - rc = pthread_create(&t->t_handle, NULL, (void*(*)(void*)) t->t_run, t); - return (rc == 0) ? OPAL_SUCCESS : OPAL_ERROR; +opal_thread_t *opal_thread_get_self(void) +{ + opal_thread_t *t = OBJ_NEW(opal_thread_t); + t->t_handle = pthread_self(); + return t; } - -int opal_thread_join(opal_thread_t *t, void **thr_return) +bool opal_thread_self_compare(opal_thread_t *t) { + return t->t_handle == pthread_self(); +} + +int opal_thread_join(opal_thread_t *t, void **thr_return) { int rc = pthread_join(t->t_handle, thr_return); t->t_handle = (pthread_t) -1; return (rc == 0) ? OPAL_SUCCESS : OPAL_ERROR; } - -bool opal_thread_self_compare(opal_thread_t *t) -{ - return t->t_handle == pthread_self(); +void opal_thread_set_main() { + opal_main_thread = pthread_self(); } +int opal_thread_start(opal_thread_t *t) { + int rc; -opal_thread_t *opal_thread_get_self(void) -{ - opal_thread_t *t = OBJ_NEW(opal_thread_t); - t->t_handle = pthread_self(); - return t; -} + if (OPAL_ENABLE_DEBUG) { + if (NULL == t->t_run || t->t_handle != (pthread_t) -1) { + return OPAL_ERR_BAD_PARAM; + } + } -void opal_thread_kill(opal_thread_t *t, int sig) -{ - pthread_kill(t->t_handle, sig); + rc = pthread_create(&t->t_handle, NULL, (void*(*)(void*)) t->t_run, t); + + return (rc == 0) ? OPAL_SUCCESS : OPAL_ERROR; } -int opal_tsd_key_create(opal_tsd_key_t *key, - opal_tsd_destructor_t destructor) +opal_class_t opal_thread_t_class; + +int opal_tsd_key_create(opal_tsd_key_t *key, opal_tsd_destructor_t destructor) { int rc; rc = pthread_key_create(key, destructor); @@ -128,6 +118,6 @@ int opal_tsd_keys_destruct() return OPAL_SUCCESS; } -void opal_thread_set_main() { - opal_main_thread = pthread_self(); +void opal_event_use_threads(void) { + evthread_use_pthreads(); } diff --git a/opal/mca/threads/pthreads/threads_pthreads_mutex.c b/opal/mca/threads/pthreads/threads_pthreads_mutex.c new file mode 100644 index 00000000000..35ca43a2494 --- /dev/null +++ b/opal/mca/threads/pthreads/threads_pthreads_mutex.c @@ -0,0 +1,98 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2005 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2007-2016 Los Alamos National Security, LLC. All rights + * reserved. + * Copyright (c) 2015 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2019 Sandia National Laboratories. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "opal_config.h" + +#include +#include + +#include "opal/mca/threads/mutex.h" +//#include "opal/mca/threads/pthreads/mutex_unix.h" + +/* + * Wait and see if some upper layer wants to use threads, if support + * exists. + */ +bool opal_uses_threads = false; + +struct opal_pthread_mutex_t { + opal_object_t super; + + pthread_mutex_t m_lock_pthread; + +#if OPAL_ENABLE_DEBUG + int m_lock_debug; + const char *m_lock_file; + int m_lock_line; +#endif + + opal_atomic_lock_t m_lock_atomic; +}; +typedef struct opal_pthread_mutex_t opal_pthread_mutex_t; +typedef struct opal_pthread_mutex_t opal_pthread_recursive_mutex_t; + +static void mca_threads_pthreads_mutex_constructor(opal_mutex_t *p_mutex) { + pthread_mutex_init(&p_mutex->m_lock_pthread, NULL); +#if OPAL_ENABLE_DEBUG + p_mutex->m_lock_debug = 0; + p_mutex->m_lock_file = NULL; + p_mutex->m_lock_line = 0; +#endif + opal_atomic_lock_init(&p_mutex->m_lock_atomic, 0); +} + +static void mca_threads_pthreads_mutex_desctructor(opal_mutex_t *p_mutex) { + pthread_mutex_destroy(&p_mutex->m_lock_pthread); +} + +static void mca_threads_pthreads_recursive_mutex_constructor + (opal_recursive_mutex_t *p_mutex) { + pthread_mutexattr_t mutex_attr; + pthread_mutexattr_init(&mutex_attr); + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&p_mutex->m_lock_pthread, &mutex_attr); + pthread_mutexattr_destroy(&mutex_attr); +#if OPAL_ENABLE_DEBUG + p_mutex->m_lock_debug = 0; + p_mutex->m_lock_file = NULL; + p_mutex->m_lock_line = 0; +#endif + opal_atomic_lock_init(&p_mutex->m_lock_atomic, 0); +} + +static void mca_threads_pthreads_recursive_mutex_desctructor + (opal_recursive_mutex_t *p_mutex) { + pthread_mutex_destroy(&p_mutex->m_lock_pthread); +} + +OBJ_CLASS_INSTANCE(opal_mutex_t, + opal_object_t, + mca_threads_pthreads_mutex_constructor, + mca_threads_pthreads_mutex_desctructor); + +OBJ_CLASS_INSTANCE(opal_recursive_mutex_t, + opal_object_t, + mca_threads_pthreads_recursive_mutex_constructor, + mca_threads_pthreads_recursive_mutex_desctructor); diff --git a/opal/threads/mutex_unix.h b/opal/mca/threads/pthreads/threads_pthreads_mutex.h similarity index 90% rename from opal/threads/mutex_unix.h rename to opal/mca/threads/pthreads/threads_pthreads_mutex.h index 1cafdedd4e1..3f8d082c4b4 100644 --- a/opal/threads/mutex_unix.h +++ b/opal/mca/threads/pthreads/threads_pthreads_mutex.h @@ -14,6 +14,8 @@ * reserved. * Copyright (c) 2015-2016 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2019 Sandia National Laboratories. All rights reserved. + * * $COPYRIGHT$ * * Additional copyrights may follow @@ -21,8 +23,8 @@ * $HEADER$ */ -#ifndef OPAL_MUTEX_UNIX_H -#define OPAL_MUTEX_UNIX_H 1 +#ifndef OPAL_MCA_THREADS_PTHREADS_THREADS_PTHREADS_MUTEX_H +#define OPAL_MCA_THREADS_PTHREADS_THREADS_PTHREADS_MUTEX_H 1 /** * @file: @@ -209,6 +211,14 @@ static inline void opal_mutex_atomic_unlock(opal_mutex_t *m) #endif +typedef pthread_cond_t opal_cond_t; +#define OPAL_CONDITION_STATIC_INIT PTHREAD_COND_INITIALIZER +#define opal_cond_init(a) pthread_cond_init(a, NULL) +#define opal_cond_wait(a,b) pthread_cond_wait(a, &(b)->m_lock_pthread) +#define opal_cond_broadcast(a) pthread_cond_broadcast(a) +#define opal_cond_signal(a) pthread_cond_signal(a) +#define opal_cond_destroy(a) pthread_cond_destroy(a) + END_C_DECLS -#endif /* OPAL_MUTEX_UNIX_H */ +#endif /* OPAL_MCA_THREADS_PTHREADS_THREADS_PTHREADS_MUTEX_H */ diff --git a/opal/mca/threads/pthreads/threads_pthreads_threads.h b/opal/mca/threads/pthreads/threads_pthreads_threads.h new file mode 100644 index 00000000000..ed0166e4dab --- /dev/null +++ b/opal/mca/threads/pthreads/threads_pthreads_threads.h @@ -0,0 +1,15 @@ + +#ifndef OPAL_MCA_THREADS_PTHREADS_THREADS_PTHREADS_THREADS_H +#define OPAL_MCA_THREADS_PTHREADS_THREADS_PTHREADS_THREADS_H 1 + +#include +#include + +struct opal_thread_t { + opal_object_t super; + opal_thread_fn_t t_run; + void* t_arg; + pthread_t t_handle; +}; + +#endif /* OPAL_MCA_THREADS_PTHREADS_THREADS_PTHREADS_THREADS_H */ diff --git a/opal/mca/threads/pthreads/threads_pthreads_tsd.h b/opal/mca/threads/pthreads/threads_pthreads_tsd.h new file mode 100644 index 00000000000..f3696f7df3d --- /dev/null +++ b/opal/mca/threads/pthreads/threads_pthreads_tsd.h @@ -0,0 +1,29 @@ + +#ifndef OPAL_MCA_THREADS_PTHREADS_THREADS_PTHREADS_TSD_H +#define OPAL_MCA_THREADS_PTHREADS_THREADS_PTHREADS_TSD_H 1 + +#include +#include + +typedef pthread_key_t opal_tsd_key_t; + +static inline int +opal_tsd_key_delete(opal_tsd_key_t key) +{ + return pthread_key_delete(key); +} + +static inline int +opal_tsd_setspecific(opal_tsd_key_t key, void *value) +{ + return pthread_setspecific(key, value); +} + +static inline int +opal_tsd_getspecific(opal_tsd_key_t key, void **valuep) +{ + *valuep = pthread_getspecific(key); + return OPAL_SUCCESS; +} + +#endif /* OPAL_MCA_THREADS_PTHREADS_THREADS_PTHREADS_TSD_H */ diff --git a/opal/threads/wait_sync.c b/opal/mca/threads/pthreads/threads_pthreads_wait_sync.c similarity index 96% rename from opal/threads/wait_sync.c rename to opal/mca/threads/pthreads/threads_pthreads_wait_sync.c index 1f73f7c8ad4..21a8943c5d7 100644 --- a/opal/threads/wait_sync.c +++ b/opal/mca/threads/pthreads/threads_pthreads_wait_sync.c @@ -6,13 +6,15 @@ * Copyright (c) 2016 Los Alamos National Security, LLC. All rights * reserved. * Copyright (c) 2017 IBM Corporation. All rights reserved. + * Copyright (c) 2019 Sandia National Laboratories. All rights reserved. + * * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ */ -#include "wait_sync.h" +#include "opal/mca/threads/wait_sync.h" static opal_mutex_t wait_sync_lock = OPAL_MUTEX_STATIC_INIT; static ompi_wait_sync_t* wait_sync_list = NULL; diff --git a/opal/mca/threads/pthreads/threads_pthreads_wait_sync.h b/opal/mca/threads/pthreads/threads_pthreads_wait_sync.h new file mode 100644 index 00000000000..0b43a51fd62 --- /dev/null +++ b/opal/mca/threads/pthreads/threads_pthreads_wait_sync.h @@ -0,0 +1,77 @@ + +#ifndef OPAL_MCA_THREADS_PTHREADS_THREADS_PTHREADS_WAIT_SYNC_H +#define OPAL_MCA_THREADS_PTHREADS_THREADS_PTHREADS_WAIT_SYNC_H 1 + +typedef struct ompi_wait_sync_t { + opal_atomic_int32_t count; + int32_t status; + pthread_cond_t condition; + pthread_mutex_t lock; + struct ompi_wait_sync_t *next; + struct ompi_wait_sync_t *prev; + volatile bool signaling; +} ompi_wait_sync_t; + +#define SYNC_WAIT(sync) (opal_using_threads() ? ompi_sync_wait_mt (sync) : sync_wait_st (sync)) + +/* The loop in release handles a race condition between the signaling + * thread and the destruction of the condition variable. The signaling + * member will be set to false after the final signaling thread has + * finished operating on the sync object. This is done to avoid + * extra atomics in the signalling function and keep it as fast + * as possible. Note that the race window is small so spinning here + * is more optimal than sleeping since this macro is called in + * the critical path. */ +#define WAIT_SYNC_RELEASE(sync) \ + if (opal_using_threads()) { \ + while ((sync)->signaling) { \ + continue; \ + } \ + pthread_cond_destroy(&(sync)->condition); \ + pthread_mutex_destroy(&(sync)->lock); \ + } + +#define WAIT_SYNC_RELEASE_NOWAIT(sync) \ + if (opal_using_threads()) { \ + pthread_cond_destroy(&(sync)->condition); \ + pthread_mutex_destroy(&(sync)->lock); \ + } + + +#define WAIT_SYNC_SIGNAL(sync) \ + if (opal_using_threads()) { \ + pthread_mutex_lock(&(sync->lock)); \ + pthread_cond_signal(&sync->condition); \ + pthread_mutex_unlock(&(sync->lock)); \ + sync->signaling = false; \ + } + +#define WAIT_SYNC_SIGNALLED(sync){ \ + (sync)->signaling = false; \ +} + +OPAL_DECLSPEC int ompi_sync_wait_mt(ompi_wait_sync_t *sync); +static inline int sync_wait_st (ompi_wait_sync_t *sync) +{ + while (sync->count > 0) { + opal_progress(); + } + + return sync->status; +} + + +#define WAIT_SYNC_INIT(sync,c) \ + do { \ + (sync)->count = (c); \ + (sync)->next = NULL; \ + (sync)->prev = NULL; \ + (sync)->status = 0; \ + (sync)->signaling = (0 != (c)); \ + if (opal_using_threads()) { \ + pthread_cond_init (&(sync)->condition, NULL); \ + pthread_mutex_init (&(sync)->lock, NULL); \ + } \ + } while(0) + +#endif /* OPAL_MCA_THREADS_PTHREADS_THREADS_PTHREADS_WAIT_SYNC_H */ diff --git a/opal/mca/threads/qthreads/Makefile.am b/opal/mca/threads/qthreads/Makefile.am new file mode 100644 index 00000000000..d9a893a880f --- /dev/null +++ b/opal/mca/threads/qthreads/Makefile.am @@ -0,0 +1,27 @@ +# +# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana +# University Research and Technology +# Corporation. All rights reserved. +# Copyright (c) 2004-2005 The University of Tennessee and The University +# of Tennessee Research Foundation. All rights +# reserved. +# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, +# University of Stuttgart. All rights reserved. +# Copyright (c) 2004-2005 The Regents of the University of California. +# All rights reserved. +# Copyright (c) 2008 Cisco Systems, Inc. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +noinst_LTLIBRARIES = libmca_threads_qthreads.la + +libmca_threads_qthreads_la_SOURCES = \ + threads_qthreads.h \ + threads_qthreads_component.c \ + threads_qthreads_mutex.c \ + threads_qthreads_condition.c \ + threads_qthreads_module.c diff --git a/opal/mca/threads/qthreads/configure.m4 b/opal/mca/threads/qthreads/configure.m4 new file mode 100644 index 00000000000..be32cf87911 --- /dev/null +++ b/opal/mca/threads/qthreads/configure.m4 @@ -0,0 +1,43 @@ +# -*- shell-script -*- +# +# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana +# University Research and Technology +# Corporation. All rights reserved. +# Copyright (c) 2004-2005 The University of Tennessee and The University +# of Tennessee Research Foundation. All rights +# reserved. +# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, +# University of Stuttgart. All rights reserved. +# Copyright (c) 2004-2005 The Regents of the University of California. +# All rights reserved. +# Copyright (c) 2010 Cisco Systems, Inc. All rights reserved. +# Copyright (c) 2015 Research Organization for Information Science +# and Technology (RIST). All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# +AC_DEFUN([MCA_opal_threads_qthreads_PRIORITY], [30]) + +AC_DEFUN([MCA_opal_threads_qthreads_COMPILE_MODE], [ + AC_MSG_CHECKING([for MCA component $2:$3 compile mode]) + $4="static" + AC_MSG_RESULT([$$4]) +]) + +AC_DEFUN([MCA_opal_threads_qthreads_POST_CONFIG],[ + AS_IF([test "$1" = "1"], [threads_base_include="qthreads/threads_qthreads.h"]) +])dnl + +# MCA_threads_qthreads_CONFIG(action-if-can-compile, +# [action-if-cant-compile]) +# ------------------------------------------------ +AC_DEFUN([MCA_opal_threads_qthreads_CONFIG],[ + AC_CONFIG_FILES([opal/mca/threads/qthreads/Makefile]) + + AS_IF([test "$HAVE_THREAD_PKG_TYPE" = "qthreads"], + [$1], + [$2]) +]) diff --git a/opal/mca/threads/qthreads/owner.txt b/opal/mca/threads/qthreads/owner.txt new file mode 100644 index 00000000000..199577ac8cf --- /dev/null +++ b/opal/mca/threads/qthreads/owner.txt @@ -0,0 +1,7 @@ +# +# owner/status file +# owner: institution that is responsible for this package +# status: e.g. active, maintenance, unmaintained +# +owner: SNL +status: unmaintained diff --git a/opal/mca/threads/qthreads/threads_qthreads.h b/opal/mca/threads/qthreads/threads_qthreads.h new file mode 100644 index 00000000000..f1ab4c81c0f --- /dev/null +++ b/opal/mca/threads/qthreads/threads_qthreads.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2014 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#ifndef OPAL_MCA_TIMER_DARWIN_TIMER_DARWIN_H +#define OPAL_MCA_TIMER_DARWIN_TIMER_DARWIN_H + +#include "opal_config.h" +#include + +typedef uint64_t opal_threadss_t; + +/* frequency in mhz */ +OPAL_DECLSPEC extern opal_threadss_t opal_threadss_darwin_freq; +OPAL_DECLSPEC extern mach_timebase_info_data_t opal_threadss_darwin_info; +OPAL_DECLSPEC extern opal_threadss_t opal_threadss_darwin_bias; + +/** + * Use the pragmatic solution proposed at + * http://stackoverflow.com/questions/23378063/how-can-i-use-mach-absolute-time-without-overflowing/23378064#23378064 + */ +static inline opal_threadss_t +opal_threadss_base_get_cycles(void) +{ + uint64_t now = mach_absolute_time(); + + if( opal_threadss_darwin_info.denom == 0 ) { + (void)mach_timebase_info(&opal_threadss_darwin_info); + if( opal_threadss_darwin_info.denom > 1024 ) { + double frac = (double)opal_threadss_darwin_info.numer/opal_threadss_darwin_info.denom; + opal_threadss_darwin_info.denom = 1024; + opal_threadss_darwin_info.numer = opal_threadss_darwin_info.denom * frac + 0.5; + } + opal_threadss_darwin_bias = now; + } + /* this is basically a wrapper around the "right" assembly to convert + the tick counter off the PowerPC Time Base into nanos. */ + return (now - opal_threadss_darwin_bias) * opal_threadss_darwin_info.numer / opal_threadss_darwin_info.denom; +} + + +static inline opal_threadss_t +opal_threadss_base_get_usec(void) +{ + /* freq is in Hz, so this gives usec */ + return opal_threadss_base_get_cycles() / 1000; +} + + +static inline opal_threadss_t +opal_threadss_base_get_freq(void) +{ + return opal_threadss_darwin_freq; +} + +typedef pthread_key_t opal_tsd_key_t; + +static inline int +opal_tsd_key_delete(opal_tsd_key_t key) +{ + return pthread_key_delete(key); +} + +static inline int +opal_tsd_setspecific(opal_tsd_key_t key, void *value) +{ + return pthread_setspecific(key, value); +} + +static inline int +opal_tsd_getspecific(opal_tsd_key_t key, void **valuep) +{ + *valuep = pthread_getspecific(key); + return OPAL_SUCCESS; +} + +#define OPAL_TIMER_CYCLE_NATIVE 0 +#define OPAL_TIMER_CYCLE_SUPPORTED 1 +#define OPAL_TIMER_USEC_NATIVE 1 +#define OPAL_TIMER_USEC_SUPPORTED 1 + +#endif diff --git a/opal/mca/threads/qthreads/threads_qthreads_component.c b/opal/mca/threads/qthreads/threads_qthreads_component.c new file mode 100644 index 00000000000..aef0a009d1f --- /dev/null +++ b/opal/mca/threads/qthreads/threads_qthreads_component.c @@ -0,0 +1,53 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ +/* + * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2014 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2007-2015 Los Alamos National Security, LLC. All rights + * reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "opal_config.h" + +#include "opal/mca/threads/thread.h" +#include "opal/mca/threads/threads.h" +#include "opal/mca/threads/qthreads/threads_qthreads.h" +#include "opal/constants.h" + +static int opal_threads_qthreads_open(void); + +const opal_threads_base_component_2_0_0_t mca_threads_qthreads_component = { + /* First, the mca_component_t struct containing meta information + about the component itself */ + .threadsc_version = { + OPAL_THREADS_BASE_VERSION_2_0_0, + + /* Component name and version */ + .mca_component_name = "qthreads", + MCA_BASE_MAKE_VERSION(component, OPAL_MAJOR_VERSION, OPAL_MINOR_VERSION, + OPAL_RELEASE_VERSION), + + .mca_open_component = opal_threads_qthreads_open, + }, + .threadsc_data = { + /* The component is checkpoint ready */ + MCA_BASE_METADATA_PARAM_CHECKPOINT + }, +}; + +int opal_threads_qthreads_open(void) +{ + return OPAL_SUCCESS; +} diff --git a/opal/threads/condition.c b/opal/mca/threads/qthreads/threads_qthreads_condition.c similarity index 96% rename from opal/threads/condition.c rename to opal/mca/threads/qthreads/threads_qthreads_condition.c index 7745d316544..bdc8a67f214 100644 --- a/opal/threads/condition.c +++ b/opal/mca/threads/qthreads/threads_qthreads_condition.c @@ -18,7 +18,7 @@ #include "opal_config.h" -#include "opal/threads/condition.h" +#include "opal/mca/threads/condition.h" static void opal_condition_construct(opal_condition_t *c) diff --git a/opal/mca/threads/qthreads/threads_qthreads_module.c b/opal/mca/threads/qthreads/threads_qthreads_module.c new file mode 100644 index 00000000000..554ef07a1b8 --- /dev/null +++ b/opal/mca/threads/qthreads/threads_qthreads_module.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2005 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ +#include + +#include "opal/constants.h" +#include "opal/util/sys_limits.h" +#include "opal/util/output.h" +#include "opal/prefetch.h" +#include "opal/mca/threads/threads.h" +#include "opal/mca/threads/tsd.h" + +struct opal_tsd_key_value { + opal_tsd_key_t key; + opal_tsd_destructor_t destructor; +}; + +static pthread_t opal_main_thread; +struct opal_tsd_key_value *opal_tsd_key_values = NULL; +static int opal_tsd_key_values_count = 0; + +/* + * Constructor + */ +static void opal_thread_construct(opal_thread_t *t) +{ + t->t_run = 0; + t->t_handle = (pthread_t) -1; +} + +OBJ_CLASS_INSTANCE(opal_thread_t, + opal_object_t, + opal_thread_construct, NULL); + + + +opal_thread_t *opal_thread_get_self(void) +{ + opal_thread_t *t = OBJ_NEW(opal_thread_t); + t->t_handle = pthread_self(); + return t; +} + +bool opal_thread_self_compare(opal_thread_t *t) +{ + return t->t_handle == pthread_self(); +} + +int sync_wait_mt(void *p) { + return 0; +} + +int opal_thread_join(opal_thread_t *t, void **thr_return) { + int rc = pthread_join(t->t_handle, thr_return); + t->t_handle = (pthread_t) -1; + return (rc == 0) ? OPAL_SUCCESS : OPAL_ERROR; +} + +void opal_thread_set_main() { + opal_main_thread = pthread_self(); +} + +int opal_thread_start(opal_thread_t *t) { + int rc; + + if (OPAL_ENABLE_DEBUG) { + if (NULL == t->t_run || t->t_handle != (pthread_t) -1) { + return OPAL_ERR_BAD_PARAM; + } + } + + rc = pthread_create(&t->t_handle, NULL, (void*(*)(void*)) t->t_run, t); + + return (rc == 0) ? OPAL_SUCCESS : OPAL_ERROR; +} + +opal_class_t opal_thread_t_class; + +int opal_tsd_key_create(opal_tsd_key_t *key, opal_tsd_destructor_t destructor) +{ + int rc; + rc = pthread_key_create(key, destructor); + if ((0 == rc) && (pthread_self() == opal_main_thread)) { + opal_tsd_key_values = (struct opal_tsd_key_value *)realloc(opal_tsd_key_values, (opal_tsd_key_values_count+1) * sizeof(struct opal_tsd_key_value)); + opal_tsd_key_values[opal_tsd_key_values_count].key = *key; + opal_tsd_key_values[opal_tsd_key_values_count].destructor = destructor; + opal_tsd_key_values_count ++; + } + return rc; +} + +int opal_tsd_keys_destruct() +{ + int i; + void * ptr; + for (i=0; i + *
  • OPAL_THREADS_CYCLE_NATIVE
    Whether + * opal_threads_base_get_cycle() is implemented directly or computed + * from some other data (such as a high res threads)
  • + *
  • OPAL_THREADS_CYCLE_SUPPORTED
    Whether + * opal_threads_base_get_cycle() is supported on the current + * platform.
  • + *
  • OPAL_THREADS_USEC_SUPPORTED
    Whether + * opal_threads_base_get_usec() is supported on the current + * platform or implemented on top of gettimeofday(), which + * may be unsuitable for some uses. + * + * + * The cycle count may not be the cycle count of the CPU itself, if + * there is another sufficiently close counter with better behavior + * characteristics (like the Time Base counter on many Power/PowerPC + * platforms). The function opal_threads_base_get_freq() returns the + * frequency of the cycle counter in use, *NOT* the frequency of the + * main CPU. + * + * Unless otherwise noted, no attempt is made to cope with the the + * differences in counters on SMP machines. If your process switches + * CPUs, your threads results may change. + * + * Build time priorities are allocated as follows: + * + * - 0 gettimeofday() wrapper + * - 10 Assembly threadss with bad frequency search (Linux) + * - 20 NIC software stack (QSNet, Myrinet?) + * - 30 Operating systems with native interfaces + */ + +#ifndef OPAL_MCA_THREADS_THREADS_H +#define OPAL_MCA_THREADS_THREADS_H + +#include "opal_config.h" + +#include "opal/mca/mca.h" +#include "opal/mca/base/base.h" + + +/** + * Structure for threads components. + */ +struct opal_threads_base_component_2_0_0_t { + /** MCA base component */ + mca_base_component_t threadsc_version; + /** MCA base data */ + mca_base_component_data_t threadsc_data; +}; +/** + * Convenience typedef + */ +typedef struct opal_threads_base_component_2_0_0_t opal_threads_base_component_2_0_0_t; + +/* + * Macro for use in components that are of type threads + */ +#define OPAL_THREADS_BASE_VERSION_2_0_0 \ + OPAL_MCA_BASE_VERSION_2_1_0("threads", 2, 0, 0) + +#endif /* OPAL_MCA_THREADS_THREADS_H */ diff --git a/opal/mca/threads/thread_usage.h b/opal/mca/threads/thread_usage.h new file mode 100644 index 00000000000..92e0031a751 --- /dev/null +++ b/opal/mca/threads/thread_usage.h @@ -0,0 +1,267 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2007 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2006 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2007-2014 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2014-2016 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2015-2018 Los Alamos National Security, LLC. All rights + * reserved. + * Copyright (c) 2019 Sandia National Laboratories. All rights reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#if !defined(OPAL_MCA_THREAD_USAGE_H) +#define OPAL_MCA_THREAD_USAGE_H + +#include "opal_config.h" + +#include "opal/sys/atomic.h" +#include "opal/prefetch.h" + +OPAL_DECLSPEC extern bool opal_uses_threads; + +/** + * Check and see if the process is using multiple threads. + * + * @retval true If the process may have more than one thread. + * @retval false If the process only has a single thread. + * + * The value that this function returns is influenced by: + * + * - how MPI_INIT or MPI_INIT_THREAD was invoked, + * - what the final MPI thread level was determined to be, + * - whether the OMPI or MPI libraries are multi-threaded + * + * MPI_INIT and MPI_INIT_THREAD (specifically, back-end OMPI startup + * functions) invoke opal_set_using_threads() to influence the value of + * this function, depending on their situation. Some examples: + * + * - if MPI_INIT is invoked, and the ompi components in use are + * single-threaded, this value will be false. + * + * - if MPI_INIT_THREAD is invoked with MPI_THREAD_MULTIPLE, we have + * thread support, and the final thread level is determined to be + * MPI_THREAD_MULTIPLE, this value will be true. + * + * - if the process is a single-threaded OMPI executable (e.g., mpicc), + * this value will be false. + * + * Hence, this function will return false if there is guaranteed to + * only be one thread in the process. If there is even the + * possibility that we may have multiple threads, true will be + * returned. + */ +#define opal_using_threads() opal_uses_threads + +/** + * Set whether the process is using multiple threads or not. + * + * @param have Boolean indicating whether the process is using + * multiple threads or not. + * + * @retval opal_using_threads The new return value from + * opal_using_threads(). + * + * This function is used to influence the return value of + * opal_using_threads(). If configure detected that we have thread + * support, the return value of future invocations of + * opal_using_threads() will be the parameter's value. If configure + * detected that we have no thread support, then the retuen from + * opal_using_threads() will always be false. + */ +static inline bool opal_set_using_threads(bool have) +{ + opal_uses_threads = have; + return opal_using_threads(); +} + + +/** + * Use an atomic operation for increment/decrement if opal_using_threads() + * indicates that threads are in use by the application or library. + */ + +#define OPAL_THREAD_DEFINE_ATOMIC_OP(type, name, operator, suffix) \ +static inline type opal_thread_ ## name ## _fetch_ ## suffix (opal_atomic_ ## type *addr, type delta) \ +{ \ + if (OPAL_UNLIKELY(opal_using_threads())) { \ + return opal_atomic_ ## name ## _fetch_ ## suffix (addr, delta); \ + } \ + \ + *addr = *addr operator delta; \ + return *addr; \ +} \ + \ +static inline type opal_thread_fetch_ ## name ## _ ## suffix (opal_atomic_ ## type *addr, type delta) \ +{ \ + if (OPAL_UNLIKELY(opal_using_threads())) { \ + return opal_atomic_fetch_ ## name ## _ ## suffix (addr, delta); \ + } \ + \ + type old = *addr; \ + *addr = old operator delta; \ + return old; \ +} + +#define OPAL_THREAD_DEFINE_ATOMIC_COMPARE_EXCHANGE(type, addr_type, suffix) \ +static inline bool opal_thread_compare_exchange_strong_ ## suffix (opal_atomic_ ## addr_type *addr, type *compare, type value) \ +{ \ + if (OPAL_UNLIKELY(opal_using_threads())) { \ + return opal_atomic_compare_exchange_strong_ ## suffix (addr, (addr_type *) compare, (addr_type) value); \ + } \ + \ + if ((type) *addr == *compare) { \ + ((type *) addr)[0] = value; \ + return true; \ + } \ + \ + *compare = ((type *) addr)[0]; \ + \ + return false; \ +} + +#define OPAL_THREAD_DEFINE_ATOMIC_SWAP(type, addr_type, suffix) \ +static inline type opal_thread_swap_ ## suffix (opal_atomic_ ## addr_type *ptr, type newvalue) \ +{ \ + if (opal_using_threads ()) { \ + return (type) opal_atomic_swap_ ## suffix (ptr, (addr_type) newvalue); \ + } \ + \ + type old = ((type *) ptr)[0]; \ + ((type *) ptr)[0] = newvalue; \ + \ + return old; \ +} + +OPAL_THREAD_DEFINE_ATOMIC_OP(int32_t, add, +, 32) +OPAL_THREAD_DEFINE_ATOMIC_OP(size_t, add, +, size_t) +OPAL_THREAD_DEFINE_ATOMIC_OP(int32_t, and, &, 32) +OPAL_THREAD_DEFINE_ATOMIC_OP(int32_t, or, |, 32) +OPAL_THREAD_DEFINE_ATOMIC_OP(int32_t, xor, ^, 32) +OPAL_THREAD_DEFINE_ATOMIC_OP(int32_t, sub, -, 32) +OPAL_THREAD_DEFINE_ATOMIC_OP(size_t, sub, -, size_t) + +OPAL_THREAD_DEFINE_ATOMIC_COMPARE_EXCHANGE(int32_t, int32_t, 32) +OPAL_THREAD_DEFINE_ATOMIC_COMPARE_EXCHANGE(intptr_t, intptr_t, ptr) +OPAL_THREAD_DEFINE_ATOMIC_SWAP(int32_t, int32_t, 32) +OPAL_THREAD_DEFINE_ATOMIC_SWAP(intptr_t, intptr_t, ptr) + +#define OPAL_THREAD_ADD_FETCH32 opal_thread_add_fetch_32 +#define OPAL_ATOMIC_ADD_FETCH32 opal_thread_add_fetch_32 + +#define OPAL_THREAD_AND_FETCH32 opal_thread_and_fetch_32 +#define OPAL_ATOMIC_AND_FETCH32 opal_thread_and_fetch_32 + +#define OPAL_THREAD_OR_FETCH32 opal_thread_or_fetch_32 +#define OPAL_ATOMIC_OR_FETCH32 opal_thread_or_fetch_32 + +#define OPAL_THREAD_XOR_FETCH32 opal_thread_xor_fetch_32 +#define OPAL_ATOMIC_XOR_FETCH32 opal_thread_xor_fetch_32 + +#define OPAL_THREAD_ADD_FETCH_SIZE_T opal_thread_add_fetch_size_t +#define OPAL_ATOMIC_ADD_FETCH_SIZE_T opal_thread_add_fetch_size_t + +#define OPAL_THREAD_SUB_FETCH_SIZE_T opal_thread_sub_fetch_size_t +#define OPAL_ATOMIC_SUB_FETCH_SIZE_T opal_thread_sub_fetch_size_t + +#define OPAL_THREAD_FETCH_ADD32 opal_thread_fetch_add_32 +#define OPAL_ATOMIC_FETCH_ADD32 opal_thread_fetch_add_32 + +#define OPAL_THREAD_FETCH_AND32 opal_thread_fetch_and_32 +#define OPAL_ATOMIC_FETCH_AND32 opal_thread_fetch_and_32 + +#define OPAL_THREAD_FETCH_OR32 opal_thread_fetch_or_32 +#define OPAL_ATOMIC_FETCH_OR32 opal_thread_fetch_or_32 + +#define OPAL_THREAD_FETCH_XOR32 opal_thread_fetch_xor_32 +#define OPAL_ATOMIC_FETCH_XOR32 opal_thread_fetch_xor_32 + +#define OPAL_THREAD_FETCH_ADD_SIZE_T opal_thread_fetch_add_size_t +#define OPAL_ATOMIC_FETCH_ADD_SIZE_T opal_thread_fetch_add_size_t + +#define OPAL_THREAD_FETCH_SUB_SIZE_T opal_thread_fetch_sub_size_t +#define OPAL_ATOMIC_FETCH_SUB_SIZE_T opal_thread_fetch_sub_size_t + +#define OPAL_THREAD_COMPARE_EXCHANGE_STRONG_32 opal_thread_compare_exchange_strong_32 +#define OPAL_ATOMIC_COMPARE_EXCHANGE_STRONG_32 opal_thread_compare_exchange_strong_32 + +#define OPAL_THREAD_COMPARE_EXCHANGE_STRONG_PTR(x, y, z) opal_thread_compare_exchange_strong_ptr ((opal_atomic_intptr_t *) x, (intptr_t *) y, (intptr_t) z) +#define OPAL_ATOMIC_COMPARE_EXCHANGE_STRONG_PTR OPAL_THREAD_COMPARE_EXCHANGE_STRONG_PTR + +#define OPAL_THREAD_SWAP_32 opal_thread_swap_32 +#define OPAL_ATOMIC_SWAP_32 opal_thread_swap_32 + +#define OPAL_THREAD_SWAP_PTR(x, y) opal_thread_swap_ptr ((opal_atomic_intptr_t *) x, (intptr_t) y) +#define OPAL_ATOMIC_SWAP_PTR OPAL_THREAD_SWAP_PTR + +/* define 64-bit macros is 64-bit atomic math is available */ +#if OPAL_HAVE_ATOMIC_MATH_64 + +OPAL_THREAD_DEFINE_ATOMIC_OP(int64_t, add, +, 64) +OPAL_THREAD_DEFINE_ATOMIC_OP(int64_t, and, &, 64) +OPAL_THREAD_DEFINE_ATOMIC_OP(int64_t, or, |, 64) +OPAL_THREAD_DEFINE_ATOMIC_OP(int64_t, xor, ^, 64) +OPAL_THREAD_DEFINE_ATOMIC_OP(int64_t, sub, -, 64) +OPAL_THREAD_DEFINE_ATOMIC_COMPARE_EXCHANGE(int64_t, int64_t, 64) +OPAL_THREAD_DEFINE_ATOMIC_SWAP(int64_t, int64_t, 64) + +#define OPAL_THREAD_ADD_FETCH64 opal_thread_add_fetch_64 +#define OPAL_ATOMIC_ADD_FETCH64 opal_thread_add_fetch_64 + +#define OPAL_THREAD_AND_FETCH64 opal_thread_and_fetch_64 +#define OPAL_ATOMIC_AND_FETCH64 opal_thread_and_fetch_64 + +#define OPAL_THREAD_OR_FETCH64 opal_thread_or_fetch_64 +#define OPAL_ATOMIC_OR_FETCH64 opal_thread_or_fetch_64 + +#define OPAL_THREAD_XOR_FETCH64 opal_thread_xor_fetch_64 +#define OPAL_ATOMIC_XOR_FETCH64 opal_thread_xor_fetch_64 + +#define OPAL_THREAD_FETCH_ADD64 opal_thread_fetch_add_64 +#define OPAL_ATOMIC_FETCH_ADD64 opal_thread_fetch_add_64 + +#define OPAL_THREAD_FETCH_AND64 opal_thread_fetch_and_64 +#define OPAL_ATOMIC_FETCH_AND64 opal_thread_fetch_and_64 + +#define OPAL_THREAD_FETCH_OR64 opal_thread_fetch_or_64 +#define OPAL_ATOMIC_FETCH_OR64 opal_thread_fetch_or_64 + +#define OPAL_THREAD_FETCH_XOR64 opal_thread_fetch_xor_64 +#define OPAL_ATOMIC_FETCH_XOR64 opal_thread_fetch_xor_64 + +#define OPAL_THREAD_COMPARE_EXCHANGE_STRONG_64 opal_thread_compare_exchange_strong_64 +#define OPAL_ATOMIC_COMPARE_EXCHANGE_STRONG_64 opal_thread_compare_exchange_strong_64 + +#define OPAL_THREAD_SWAP_64 opal_thread_swap_64 +#define OPAL_ATOMIC_SWAP_64 opal_thread_swap_64 + +#endif + +/* thread local storage */ +#if OPAL_C_HAVE__THREAD_LOCAL +#define opal_thread_local _Thread_local +#define OPAL_HAVE_THREAD_LOCAL 1 + +#elif OPAL_C_HAVE___THREAD /* OPAL_C_HAVE__THREAD_LOCAL */ +#define opal_thread_local __thread +#define OPAL_HAVE_THREAD_LOCAL 1 +#endif /* OPAL_C_HAVE___THREAD */ + +#if !defined(OPAL_HAVE_THREAD_LOCAL) +#define OPAL_HAVE_THREAD_LOCAL 0 +#endif /* !defined(OPAL_HAVE_THREAD_LOCAL) */ + +#endif /* !defined(OPAL_MCA_THREAD_USAGE_H) */ diff --git a/opal/mca/threads/threads.h b/opal/mca/threads/threads.h new file mode 100644 index 00000000000..c69de3f774d --- /dev/null +++ b/opal/mca/threads/threads.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2006 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2010 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015-2017 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2017 Intel, Inc. All rights reserved. + * Copyright (c) 2019 Sandia National Laboratories. All rights reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#ifndef OPAL_MCA_THREAD_H +#define OPAL_MCA_THREAD_H 1 + +#include "opal_config.h" + +#include "opal/class/opal_object.h" +#if OPAL_ENABLE_DEBUG +#include "opal/util/output.h" +#endif + +#include "mutex.h" +#include "condition.h" + +BEGIN_C_DECLS + +typedef void *(*opal_thread_fn_t) (opal_object_t *); + +#define OPAL_THREAD_CANCELLED ((void*)1); + +#include MCA_threads_IMPLEMENTATION_HEADER + +typedef struct opal_thread_t opal_thread_t; + +OBJ_CLASS_DECLARATION(opal_thread_t); + +#if OPAL_ENABLE_DEBUG +OPAL_DECLSPEC extern bool opal_debug_threads; +#endif + + +OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_thread_t); + +#if OPAL_ENABLE_DEBUG +#define OPAL_ACQUIRE_THREAD(lck, cnd, act) \ + do { \ + OPAL_THREAD_LOCK((lck)); \ + if (opal_debug_threads) { \ + opal_output(0, "Waiting for thread %s:%d", \ + __FILE__, __LINE__); \ + } \ + while (*(act)) { \ + opal_condition_wait((cnd), (lck)); \ + } \ + if (opal_debug_threads) { \ + opal_output(0, "Thread obtained %s:%d", \ + __FILE__, __LINE__); \ + } \ + *(act) = true; \ + } while(0); +#else +#define OPAL_ACQUIRE_THREAD(lck, cnd, act) \ + do { \ + OPAL_THREAD_LOCK((lck)); \ + while (*(act)) { \ + opal_condition_wait((cnd), (lck)); \ + } \ + *(act) = true; \ + } while(0); +#endif + + +#if OPAL_ENABLE_DEBUG +#define OPAL_RELEASE_THREAD(lck, cnd, act) \ + do { \ + if (opal_debug_threads) { \ + opal_output(0, "Releasing thread %s:%d", \ + __FILE__, __LINE__); \ + } \ + *(act) = false; \ + opal_condition_broadcast((cnd)); \ + OPAL_THREAD_UNLOCK((lck)); \ + } while(0); +#else +#define OPAL_RELEASE_THREAD(lck, cnd, act) \ + do { \ + *(act) = false; \ + opal_condition_broadcast((cnd)); \ + OPAL_THREAD_UNLOCK((lck)); \ + } while(0); +#endif + + +#define OPAL_WAKEUP_THREAD(cnd, act) \ + do { \ + *(act) = false; \ + opal_condition_broadcast((cnd)); \ + } while(0); + +/* provide a macro for forward-proofing the shifting + * of objects between libevent threads - at some point, we + * may revamp that threading model */ + +/* post an object to another thread - for now, we + * only have a memory barrier */ +#define OPAL_POST_OBJECT(o) opal_atomic_wmb() + +/* acquire an object from another thread - for now, + * we only have a memory barrier */ +#define OPAL_ACQUIRE_OBJECT(o) opal_atomic_rmb() + + + +OPAL_DECLSPEC int opal_thread_start(opal_thread_t *); +OPAL_DECLSPEC int opal_thread_join(opal_thread_t *, void **thread_return); +OPAL_DECLSPEC bool opal_thread_self_compare(opal_thread_t*); +OPAL_DECLSPEC opal_thread_t *opal_thread_get_self(void); +OPAL_DECLSPEC void opal_thread_kill(opal_thread_t *, int sig); +OPAL_DECLSPEC void opal_thread_set_main(void); +OPAL_DECLSPEC void opal_event_use_threads(void); + +END_C_DECLS + +#endif /* OPAL_MCA_THREAD_H */ diff --git a/opal/mca/threads/tsd.h b/opal/mca/threads/tsd.h new file mode 100644 index 00000000000..5f5a7ffd625 --- /dev/null +++ b/opal/mca/threads/tsd.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2007-2013 Los Alamos National Security, LLC. All rights + * reserved. + * Copyright (c) 2008 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2015-2017 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2019 Sandia National Laboratories. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + + +#ifndef OPAL_MCA_THREADS_TSD_H +#define OPAL_MCA_THREADS_TSD_H + +#include "opal_config.h" + +#include + +#include "opal/constants.h" + +BEGIN_C_DECLS + +/** + * @file + * + * Thread Specific Datastore Interface + * + * Functions for providing thread-specific datastore capabilities. + */ + + +/** + * Prototype for callback when tsd data is being destroyed + */ +typedef void (*opal_tsd_destructor_t)(void *value); + +#if defined(DOXYGEN) + +/** + * Typedef for thread-specific data key + */ +typedef void* opal_tsd_key_t; + + +/** + * Delete a thread-specific data key + * + * Delete a thread-specific data key previously returned by + * opal_tsd_key_create(). The destructor associated with the key is + * not fired in any thread and memory cleanup is the responsibility of + * the caller. + * + * @note Unlike pthread_key_delete, this function should not be called + * from within a destructor. It can not be universally supported at + * this time. + * + * @param key[in] The key for accessing thread-specific data + * + * @retval OPAL_SUCCESS Success + * @retval EINVAL Invalid key + */ +OPAL_DECLSPEC int opal_tsd_key_delete(opal_tsd_key_t key); + + +/** + * Set a thread-specific data value + * + * Associates value with key in the current thread. The value for the + * key in other threads is not changed. Different threads may assign + * different values to the same key. + * + * @note This function should not be called within + * opal_tsd_key_delete(). + * + * @param key[in] Thread specific data key to modify + * @param value[in] Value to associate with key + * + * @retval OPAL_SUCCESS Success + * @retval ENOMEM Insufficient memory exists to associate the + * value with the key + * @retval EINVAL Invalid key + */ +OPAL_DECLSPEC int opal_tsd_setspecific(opal_tsd_key_t key, void *value); + + +/** + * Get a thread-specific data value + * + * Get the data associated with the given key, as set by + * opal_tsd_setspecific(). If opal_tsd_setspecific() hasn't been + * called in the current thread with the given key, NULL is returned + * in valuep. + * + * @param key[in] Thread specific data key to modify + * @param value[out] Value to associate with key + * + * @retval OPAL_SUCCESS Success + * @retval ENOMEM Insufficient memory exists to associate the + * value with the key + * @retval EINVAL Invalid key + */ +OPAL_DECLSPEC int opal_tsd_getspecific(opal_tsd_key_t key, void **valuep); + +#else + +#include MCA_tsd_IMPLEMENTATION_HEADER + +#endif + +/** + * Create thread-specific data key + * + * Create a thread-specific data key visible to all threads in the + * current process. The returned key is valid in all threads, + * although the values bound to the key by opal_tsd_setspecific() are + * allocated on a per-thread basis and persist for the life of the + * calling thread. + * + * Upon key creation, the value NULL is associated with the new key in + * all active threads. When a new thread is created, the value NULL + * is associated with all defined keys in the new thread. + * + * The destructor parameter may be NULL. At thread exit, if + * destructor is non-NULL AND the thread has a non-NULL value + * associated with the key, the function is called with the current + * value as its argument. + * + * @param key[out] The key for accessing thread-specific data + * @param destructor[in] Cleanup function to call when a thread exits + * + * @retval OPAL_SUCCESS Success + * @retval EAGAIN The system lacked the necessary resource to + * create another thread specific data key + * @retval ENOMEM Insufficient memory exists to create the key + */ +OPAL_DECLSPEC int opal_tsd_key_create(opal_tsd_key_t *key, + opal_tsd_destructor_t destructor); + + +/** + * Destruct all thread-specific data keys + * + * Destruct all thread-specific data keys and invoke the destructor + * + * This should only be invoked in the main thread. + * This is made necessary since destructors are not invoked on the + * keys of the main thread, since there is no such thing as + * pthread_join(main_thread) + * + * @retval OPAL_SUCCESS Success + */ +OPAL_DECLSPEC int opal_tsd_keys_destruct(void); + +END_C_DECLS + +#endif /* OPAL_MCA_THREADS_TSD_H */ diff --git a/opal/mca/threads/wait_sync.h b/opal/mca/threads/wait_sync.h new file mode 100644 index 00000000000..4dc9f9ecb07 --- /dev/null +++ b/opal/mca/threads/wait_sync.h @@ -0,0 +1,58 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ +/* + * Copyright (c) 2014-2016 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2016 Los Alamos National Security, LLC. All rights + * reserved. + * Copyright (c) 2016 Mellanox Technologies. All rights reserved. + * Copyright (c) 2016 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2017 IBM Corporation. All rights reserved. + * Copyright (c) 2019 Sandia National Laboratories. All rights reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#if !defined(OPAL_MCA_THREADS_WAIT_SYNC_H) +#define OPAL_MCA_THREADS_WAIT_SYNC_H + +#include "opal/sys/atomic.h" +#include "opal/threads/condition.h" + +BEGIN_C_DECLS + +extern int opal_max_thread_in_progress; + +#include MCA_wait_sync_IMPLEMENTATION_HEADER + +#define REQUEST_PENDING (void*)0L +#define REQUEST_COMPLETED (void*)1L + +/** + * Update the status of the synchronization primitive. If an error is + * reported the synchronization is completed and the signal + * triggered. The status of the synchronization will be reported to + * the waiting threads. + */ +static inline void wait_sync_update(ompi_wait_sync_t *sync, int updates, int status) +{ + if( OPAL_LIKELY(OPAL_SUCCESS == status) ) { + if( 0 != (OPAL_THREAD_ADD_FETCH32(&sync->count, -updates)) ) { + return; + } + } else { + /* this is an error path so just use the atomic */ + sync->status = OPAL_ERROR; + opal_atomic_wmb (); + opal_atomic_swap_32 (&sync->count, 0); + } + WAIT_SYNC_SIGNAL(sync); +} + +END_C_DECLS + +#endif /* defined(OPAL_MCA_THREADS_WAIT_SYNC_H) */ diff --git a/opal/mca/timer/linux/timer_linux_component.c b/opal/mca/timer/linux/timer_linux_component.c index c5b664afbeb..0eb03baac04 100644 --- a/opal/mca/timer/linux/timer_linux_component.c +++ b/opal/mca/timer/linux/timer_linux_component.c @@ -26,6 +26,7 @@ #include "opal_config.h" #include +#include #include "opal/mca/timer/timer.h" #include "opal/mca/timer/base/base.h" diff --git a/opal/runtime/opal_init.c b/opal/runtime/opal_init.c index 2db5b441165..7673a4137f5 100644 --- a/opal/runtime/opal_init.c +++ b/opal/runtime/opal_init.c @@ -70,6 +70,7 @@ #include "opal/runtime/opal_progress.h" #include "opal/mca/event/base/base.h" +#include "opal/mca/threads/base/base.h" #include "opal/mca/backtrace/base/base.h" #include "opal/constants.h" @@ -520,7 +521,7 @@ opal_init_util(int* pargc, char*** pargv) * versions of memcpy correctly configured. */ static mca_base_framework_t *opal_init_frameworks[] = { - &opal_hwloc_base_framework, &opal_memcpy_base_framework, &opal_memchecker_base_framework, + &opal_hwloc_base_framework, &opal_memcpy_base_framework, &opal_threads_base_framework, &opal_memchecker_base_framework, &opal_backtrace_base_framework, &opal_timer_base_framework, &opal_event_base_framework, &opal_shmem_base_framework, &opal_reachable_base_framework, &opal_compress_base_framework, NULL, diff --git a/opal/runtime/opal_params.c b/opal/runtime/opal_params.c index 2897b64737f..485a8ce325b 100644 --- a/opal/runtime/opal_params.c +++ b/opal/runtime/opal_params.c @@ -61,6 +61,10 @@ char *opal_timing_output = NULL; bool opal_timing_overhead = true; #endif +#if OPAL_ENABLE_DEBUG +bool opal_debug_threads; +#endif + bool opal_built_with_cuda_support = OPAL_INT_TO_BOOL(OPAL_CUDA_SUPPORT); bool opal_cuda_support = false; bool opal_warn_on_missing_libcuda = true; diff --git a/opal/threads/Makefile.am b/opal/threads/Makefile.am deleted file mode 100644 index a4a084038ca..00000000000 --- a/opal/threads/Makefile.am +++ /dev/null @@ -1,39 +0,0 @@ -# -*- makefile -*- -# -# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana -# University Research and Technology -# Corporation. All rights reserved. -# Copyright (c) 2004-2016 The University of Tennessee and The University -# of Tennessee Research Foundation. All rights -# reserved. -# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, -# University of Stuttgart. All rights reserved. -# Copyright (c) 2004-2005 The Regents of the University of California. -# All rights reserved. -# Copyright (c) 2014 Cisco Systems, Inc. All rights reserved. -# Copyright (c) 2015 Research Organization for Information Science -# and Technology (RIST). All rights reserved. -# $COPYRIGHT$ -# -# Additional copyrights may follow -# -# $HEADER$ -# - -# This makefile.am does not stand on its own - it is included from opal/Makefile.am - -# Source code files -headers += \ - threads/condition.h \ - threads/mutex.h \ - threads/mutex_unix.h \ - threads/threads.h \ - threads/tsd.h \ - threads/wait_sync.h \ - threads/thread_usage.h - -lib@OPAL_LIB_PREFIX@open_pal_la_SOURCES += \ - threads/condition.c \ - threads/mutex.c \ - threads/thread.c \ - threads/wait_sync.c diff --git a/opal/threads/condition.h b/opal/threads/condition.h index 4c61fd64ac9..47eef598f8e 100644 --- a/opal/threads/condition.h +++ b/opal/threads/condition.h @@ -22,124 +22,7 @@ #ifndef OPAL_CONDITION_SPINLOCK_H #define OPAL_CONDITION_SPINLOCK_H -#include "opal_config.h" -#ifdef HAVE_SYS_TIME_H -#include -#endif -#include -#include - -#include "opal/threads/mutex.h" -#include "opal/runtime/opal_progress.h" - -#include "opal/runtime/opal_cr.h" - -BEGIN_C_DECLS - -/* - * Combine pthread support w/ polled progress to allow run-time selection - * of threading vs. non-threading progress. - */ - -struct opal_condition_t { - opal_object_t super; - volatile int c_waiting; - volatile int c_signaled; -}; -typedef struct opal_condition_t opal_condition_t; - -OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_condition_t); - - -static inline int opal_condition_wait(opal_condition_t *c, opal_mutex_t *m) -{ - int rc = 0; - c->c_waiting++; - - if (opal_using_threads()) { - if (c->c_signaled) { - c->c_waiting--; - opal_mutex_unlock(m); - opal_progress(); - OPAL_CR_TEST_CHECKPOINT_READY_STALL(); - opal_mutex_lock(m); - return 0; - } - while (c->c_signaled == 0) { - opal_mutex_unlock(m); - opal_progress(); - OPAL_CR_TEST_CHECKPOINT_READY_STALL(); - opal_mutex_lock(m); - } - } else { - while (c->c_signaled == 0) { - opal_progress(); - OPAL_CR_TEST_CHECKPOINT_READY_STALL(); - } - } - - c->c_signaled--; - c->c_waiting--; - return rc; -} - -static inline int opal_condition_timedwait(opal_condition_t *c, - opal_mutex_t *m, - const struct timespec *abstime) -{ - struct timeval tv; - struct timeval absolute; - int rc = 0; - - c->c_waiting++; - if (opal_using_threads()) { - absolute.tv_sec = abstime->tv_sec; - absolute.tv_usec = abstime->tv_nsec / 1000; - gettimeofday(&tv,NULL); - if (c->c_signaled == 0) { - do { - opal_mutex_unlock(m); - opal_progress(); - gettimeofday(&tv,NULL); - opal_mutex_lock(m); - } while (c->c_signaled == 0 && - (tv.tv_sec <= absolute.tv_sec || - (tv.tv_sec == absolute.tv_sec && tv.tv_usec < absolute.tv_usec))); - } - } else { - absolute.tv_sec = abstime->tv_sec; - absolute.tv_usec = abstime->tv_nsec / 1000; - gettimeofday(&tv,NULL); - if (c->c_signaled == 0) { - do { - opal_progress(); - gettimeofday(&tv,NULL); - } while (c->c_signaled == 0 && - (tv.tv_sec <= absolute.tv_sec || - (tv.tv_sec == absolute.tv_sec && tv.tv_usec < absolute.tv_usec))); - } - } - - if (c->c_signaled != 0) c->c_signaled--; - c->c_waiting--; - return rc; -} - -static inline int opal_condition_signal(opal_condition_t *c) -{ - if (c->c_waiting) { - c->c_signaled++; - } - return 0; -} - -static inline int opal_condition_broadcast(opal_condition_t *c) -{ - c->c_signaled = c->c_waiting; - return 0; -} - -END_C_DECLS +#include "opal/mca/threads/condition.h" #endif diff --git a/opal/threads/mutex.h b/opal/threads/mutex.h index 694c23d988a..79067829ca1 100644 --- a/opal/threads/mutex.h +++ b/opal/threads/mutex.h @@ -26,167 +26,6 @@ #ifndef OPAL_MUTEX_H #define OPAL_MUTEX_H 1 -#include "opal_config.h" - -#include "opal/threads/thread_usage.h" - -BEGIN_C_DECLS - -/** - * @file: - * - * Mutual exclusion functions. - * - * Functions for locking of critical sections. - */ - -/** - * Opaque mutex object - */ -typedef struct opal_mutex_t opal_mutex_t; -typedef struct opal_mutex_t opal_recursive_mutex_t; - -/** - * Try to acquire a mutex. - * - * @param mutex Address of the mutex. - * @return 0 if the mutex was acquired, 1 otherwise. - */ -static inline int opal_mutex_trylock(opal_mutex_t *mutex); - - -/** - * Acquire a mutex. - * - * @param mutex Address of the mutex. - */ -static inline void opal_mutex_lock(opal_mutex_t *mutex); - - -/** - * Release a mutex. - * - * @param mutex Address of the mutex. - */ -static inline void opal_mutex_unlock(opal_mutex_t *mutex); - - -/** - * Try to acquire a mutex using atomic operations. - * - * @param mutex Address of the mutex. - * @return 0 if the mutex was acquired, 1 otherwise. - */ -static inline int opal_mutex_atomic_trylock(opal_mutex_t *mutex); - - -/** - * Acquire a mutex using atomic operations. - * - * @param mutex Address of the mutex. - */ -static inline void opal_mutex_atomic_lock(opal_mutex_t *mutex); - - -/** - * Release a mutex using atomic operations. - * - * @param mutex Address of the mutex. - */ -static inline void opal_mutex_atomic_unlock(opal_mutex_t *mutex); - -END_C_DECLS - -#include "mutex_unix.h" - -BEGIN_C_DECLS - -/** - * Lock a mutex if opal_using_threads() says that multiple threads may - * be active in the process. - * - * @param mutex Pointer to a opal_mutex_t to lock. - * - * If there is a possibility that multiple threads are running in the - * process (as determined by opal_using_threads()), this function will - * block waiting to lock the mutex. - * - * If there is no possibility that multiple threads are running in the - * process, return immediately. - */ -#define OPAL_THREAD_LOCK(mutex) \ - do { \ - if (OPAL_UNLIKELY(opal_using_threads())) { \ - opal_mutex_lock(mutex); \ - } \ - } while (0) - - -/** - * Try to lock a mutex if opal_using_threads() says that multiple - * threads may be active in the process. - * - * @param mutex Pointer to a opal_mutex_t to trylock - * - * If there is a possibility that multiple threads are running in the - * process (as determined by opal_using_threads()), this function will - * trylock the mutex. - * - * If there is no possibility that multiple threads are running in the - * process, return immediately without modifying the mutex. - * - * Returns 0 if mutex was locked, non-zero otherwise. - */ -#define OPAL_THREAD_TRYLOCK(mutex) \ - (OPAL_UNLIKELY(opal_using_threads()) ? opal_mutex_trylock(mutex) : 0) - -/** - * Unlock a mutex if opal_using_threads() says that multiple threads - * may be active in the process. - * - * @param mutex Pointer to a opal_mutex_t to unlock. - * - * If there is a possibility that multiple threads are running in the - * process (as determined by opal_using_threads()), this function will - * unlock the mutex. - * - * If there is no possibility that multiple threads are running in the - * process, return immediately without modifying the mutex. - */ -#define OPAL_THREAD_UNLOCK(mutex) \ - do { \ - if (OPAL_UNLIKELY(opal_using_threads())) { \ - opal_mutex_unlock(mutex); \ - } \ - } while (0) - - -/** - * Lock a mutex if opal_using_threads() says that multiple threads may - * be active in the process for the duration of the specified action. - * - * @param mutex Pointer to a opal_mutex_t to lock. - * @param action A scope over which the lock is held. - * - * If there is a possibility that multiple threads are running in the - * process (as determined by opal_using_threads()), this function will - * acquire the lock before invoking the specified action and release - * it on return. - * - * If there is no possibility that multiple threads are running in the - * process, invoke the action without acquiring the lock. - */ -#define OPAL_THREAD_SCOPED_LOCK(mutex, action) \ - do { \ - if(OPAL_UNLIKELY(opal_using_threads())) { \ - opal_mutex_lock(mutex); \ - action; \ - opal_mutex_unlock(mutex); \ - } else { \ - action; \ - } \ - } while (0) - -END_C_DECLS +#include "opal/mca/threads/mutex.h" #endif /* OPAL_MUTEX_H */ diff --git a/opal/threads/thread_usage.h b/opal/threads/thread_usage.h index 8ce65362c1c..7d71bcb6d04 100644 --- a/opal/threads/thread_usage.h +++ b/opal/threads/thread_usage.h @@ -1,266 +1,29 @@ -/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. - * Copyright (c) 2004-2007 The University of Tennessee and The University + * Copyright (c) 2004-2006 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. - * Copyright (c) 2004-2006 High Performance Computing Center Stuttgart, + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. - * Copyright (c) 2007-2014 Cisco Systems, Inc. All rights reserved. - * Copyright (c) 2014-2016 Research Organization for Information Science + * Copyright (c) 2010 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015-2017 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2015-2018 Los Alamos National Security, LLC. All rights - * reserved. + * Copyright (c) 2017 Intel, Inc. All rights reserved. * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -#if !defined(OPAL_THREAD_USAGE_H) -#define OPAL_THREAD_USAGE_H - -#include "opal_config.h" - -#include "opal/sys/atomic.h" -#include "opal/prefetch.h" - -OPAL_DECLSPEC extern bool opal_uses_threads; - -/** - * Check and see if the process is using multiple threads. - * - * @retval true If the process may have more than one thread. - * @retval false If the process only has a single thread. - * - * The value that this function returns is influenced by: - * - * - how MPI_INIT or MPI_INIT_THREAD was invoked, - * - what the final MPI thread level was determined to be, - * - whether the OMPI or MPI libraries are multi-threaded - * - * MPI_INIT and MPI_INIT_THREAD (specifically, back-end OMPI startup - * functions) invoke opal_set_using_threads() to influence the value of - * this function, depending on their situation. Some examples: - * - * - if MPI_INIT is invoked, and the ompi components in use are - * single-threaded, this value will be false. - * - * - if MPI_INIT_THREAD is invoked with MPI_THREAD_MULTIPLE, we have - * thread support, and the final thread level is determined to be - * MPI_THREAD_MULTIPLE, this value will be true. * - * - if the process is a single-threaded OMPI executable (e.g., mpicc), - * this value will be false. - * - * Hence, this function will return false if there is guaranteed to - * only be one thread in the process. If there is even the - * possibility that we may have multiple threads, true will be - * returned. - */ -#define opal_using_threads() opal_uses_threads - -/** - * Set whether the process is using multiple threads or not. - * - * @param have Boolean indicating whether the process is using - * multiple threads or not. - * - * @retval opal_using_threads The new return value from - * opal_using_threads(). + * Additional copyrights may follow * - * This function is used to influence the return value of - * opal_using_threads(). If configure detected that we have thread - * support, the return value of future invocations of - * opal_using_threads() will be the parameter's value. If configure - * detected that we have no thread support, then the retuen from - * opal_using_threads() will always be false. - */ -static inline bool opal_set_using_threads(bool have) -{ - opal_uses_threads = have; - return opal_using_threads(); -} - - -/** - * Use an atomic operation for increment/decrement if opal_using_threads() - * indicates that threads are in use by the application or library. + * $HEADER$ */ -#define OPAL_THREAD_DEFINE_ATOMIC_OP(type, name, operator, suffix) \ -static inline type opal_thread_ ## name ## _fetch_ ## suffix (opal_atomic_ ## type *addr, type delta) \ -{ \ - if (OPAL_UNLIKELY(opal_using_threads())) { \ - return opal_atomic_ ## name ## _fetch_ ## suffix (addr, delta); \ - } \ - \ - *addr = *addr operator delta; \ - return *addr; \ -} \ - \ -static inline type opal_thread_fetch_ ## name ## _ ## suffix (opal_atomic_ ## type *addr, type delta) \ -{ \ - if (OPAL_UNLIKELY(opal_using_threads())) { \ - return opal_atomic_fetch_ ## name ## _ ## suffix (addr, delta); \ - } \ - \ - type old = *addr; \ - *addr = old operator delta; \ - return old; \ -} - -#define OPAL_THREAD_DEFINE_ATOMIC_COMPARE_EXCHANGE(type, addr_type, suffix) \ -static inline bool opal_thread_compare_exchange_strong_ ## suffix (opal_atomic_ ## addr_type *addr, type *compare, type value) \ -{ \ - if (OPAL_UNLIKELY(opal_using_threads())) { \ - return opal_atomic_compare_exchange_strong_ ## suffix (addr, (addr_type *) compare, (addr_type) value); \ - } \ - \ - if ((type) *addr == *compare) { \ - ((type *) addr)[0] = value; \ - return true; \ - } \ - \ - *compare = ((type *) addr)[0]; \ - \ - return false; \ -} - -#define OPAL_THREAD_DEFINE_ATOMIC_SWAP(type, addr_type, suffix) \ -static inline type opal_thread_swap_ ## suffix (opal_atomic_ ## addr_type *ptr, type newvalue) \ -{ \ - if (opal_using_threads ()) { \ - return (type) opal_atomic_swap_ ## suffix (ptr, (addr_type) newvalue); \ - } \ - \ - type old = ((type *) ptr)[0]; \ - ((type *) ptr)[0] = newvalue; \ - \ - return old; \ -} - -OPAL_THREAD_DEFINE_ATOMIC_OP(int32_t, add, +, 32) -OPAL_THREAD_DEFINE_ATOMIC_OP(size_t, add, +, size_t) -OPAL_THREAD_DEFINE_ATOMIC_OP(int32_t, and, &, 32) -OPAL_THREAD_DEFINE_ATOMIC_OP(int32_t, or, |, 32) -OPAL_THREAD_DEFINE_ATOMIC_OP(int32_t, xor, ^, 32) -OPAL_THREAD_DEFINE_ATOMIC_OP(int32_t, sub, -, 32) -OPAL_THREAD_DEFINE_ATOMIC_OP(size_t, sub, -, size_t) - -OPAL_THREAD_DEFINE_ATOMIC_COMPARE_EXCHANGE(int32_t, int32_t, 32) -OPAL_THREAD_DEFINE_ATOMIC_COMPARE_EXCHANGE(intptr_t, intptr_t, ptr) -OPAL_THREAD_DEFINE_ATOMIC_SWAP(int32_t, int32_t, 32) -OPAL_THREAD_DEFINE_ATOMIC_SWAP(intptr_t, intptr_t, ptr) - -#define OPAL_THREAD_ADD_FETCH32 opal_thread_add_fetch_32 -#define OPAL_ATOMIC_ADD_FETCH32 opal_thread_add_fetch_32 - -#define OPAL_THREAD_AND_FETCH32 opal_thread_and_fetch_32 -#define OPAL_ATOMIC_AND_FETCH32 opal_thread_and_fetch_32 - -#define OPAL_THREAD_OR_FETCH32 opal_thread_or_fetch_32 -#define OPAL_ATOMIC_OR_FETCH32 opal_thread_or_fetch_32 - -#define OPAL_THREAD_XOR_FETCH32 opal_thread_xor_fetch_32 -#define OPAL_ATOMIC_XOR_FETCH32 opal_thread_xor_fetch_32 - -#define OPAL_THREAD_ADD_FETCH_SIZE_T opal_thread_add_fetch_size_t -#define OPAL_ATOMIC_ADD_FETCH_SIZE_T opal_thread_add_fetch_size_t - -#define OPAL_THREAD_SUB_FETCH_SIZE_T opal_thread_sub_fetch_size_t -#define OPAL_ATOMIC_SUB_FETCH_SIZE_T opal_thread_sub_fetch_size_t - -#define OPAL_THREAD_FETCH_ADD32 opal_thread_fetch_add_32 -#define OPAL_ATOMIC_FETCH_ADD32 opal_thread_fetch_add_32 - -#define OPAL_THREAD_FETCH_AND32 opal_thread_fetch_and_32 -#define OPAL_ATOMIC_FETCH_AND32 opal_thread_fetch_and_32 - -#define OPAL_THREAD_FETCH_OR32 opal_thread_fetch_or_32 -#define OPAL_ATOMIC_FETCH_OR32 opal_thread_fetch_or_32 - -#define OPAL_THREAD_FETCH_XOR32 opal_thread_fetch_xor_32 -#define OPAL_ATOMIC_FETCH_XOR32 opal_thread_fetch_xor_32 - -#define OPAL_THREAD_FETCH_ADD_SIZE_T opal_thread_fetch_add_size_t -#define OPAL_ATOMIC_FETCH_ADD_SIZE_T opal_thread_fetch_add_size_t - -#define OPAL_THREAD_FETCH_SUB_SIZE_T opal_thread_fetch_sub_size_t -#define OPAL_ATOMIC_FETCH_SUB_SIZE_T opal_thread_fetch_sub_size_t - -#define OPAL_THREAD_COMPARE_EXCHANGE_STRONG_32 opal_thread_compare_exchange_strong_32 -#define OPAL_ATOMIC_COMPARE_EXCHANGE_STRONG_32 opal_thread_compare_exchange_strong_32 - -#define OPAL_THREAD_COMPARE_EXCHANGE_STRONG_PTR(x, y, z) opal_thread_compare_exchange_strong_ptr ((opal_atomic_intptr_t *) x, (intptr_t *) y, (intptr_t) z) -#define OPAL_ATOMIC_COMPARE_EXCHANGE_STRONG_PTR OPAL_THREAD_COMPARE_EXCHANGE_STRONG_PTR - -#define OPAL_THREAD_SWAP_32 opal_thread_swap_32 -#define OPAL_ATOMIC_SWAP_32 opal_thread_swap_32 - -#define OPAL_THREAD_SWAP_PTR(x, y) opal_thread_swap_ptr ((opal_atomic_intptr_t *) x, (intptr_t) y) -#define OPAL_ATOMIC_SWAP_PTR OPAL_THREAD_SWAP_PTR - -/* define 64-bit macros is 64-bit atomic math is available */ -#if OPAL_HAVE_ATOMIC_MATH_64 - -OPAL_THREAD_DEFINE_ATOMIC_OP(int64_t, add, +, 64) -OPAL_THREAD_DEFINE_ATOMIC_OP(int64_t, and, &, 64) -OPAL_THREAD_DEFINE_ATOMIC_OP(int64_t, or, |, 64) -OPAL_THREAD_DEFINE_ATOMIC_OP(int64_t, xor, ^, 64) -OPAL_THREAD_DEFINE_ATOMIC_OP(int64_t, sub, -, 64) -OPAL_THREAD_DEFINE_ATOMIC_COMPARE_EXCHANGE(int64_t, int64_t, 64) -OPAL_THREAD_DEFINE_ATOMIC_SWAP(int64_t, int64_t, 64) - -#define OPAL_THREAD_ADD_FETCH64 opal_thread_add_fetch_64 -#define OPAL_ATOMIC_ADD_FETCH64 opal_thread_add_fetch_64 - -#define OPAL_THREAD_AND_FETCH64 opal_thread_and_fetch_64 -#define OPAL_ATOMIC_AND_FETCH64 opal_thread_and_fetch_64 - -#define OPAL_THREAD_OR_FETCH64 opal_thread_or_fetch_64 -#define OPAL_ATOMIC_OR_FETCH64 opal_thread_or_fetch_64 - -#define OPAL_THREAD_XOR_FETCH64 opal_thread_xor_fetch_64 -#define OPAL_ATOMIC_XOR_FETCH64 opal_thread_xor_fetch_64 - -#define OPAL_THREAD_FETCH_ADD64 opal_thread_fetch_add_64 -#define OPAL_ATOMIC_FETCH_ADD64 opal_thread_fetch_add_64 - -#define OPAL_THREAD_FETCH_AND64 opal_thread_fetch_and_64 -#define OPAL_ATOMIC_FETCH_AND64 opal_thread_fetch_and_64 - -#define OPAL_THREAD_FETCH_OR64 opal_thread_fetch_or_64 -#define OPAL_ATOMIC_FETCH_OR64 opal_thread_fetch_or_64 - -#define OPAL_THREAD_FETCH_XOR64 opal_thread_fetch_xor_64 -#define OPAL_ATOMIC_FETCH_XOR64 opal_thread_fetch_xor_64 - -#define OPAL_THREAD_COMPARE_EXCHANGE_STRONG_64 opal_thread_compare_exchange_strong_64 -#define OPAL_ATOMIC_COMPARE_EXCHANGE_STRONG_64 opal_thread_compare_exchange_strong_64 - -#define OPAL_THREAD_SWAP_64 opal_thread_swap_64 -#define OPAL_ATOMIC_SWAP_64 opal_thread_swap_64 - -#endif - -/* thread local storage */ -#if OPAL_C_HAVE__THREAD_LOCAL -#define opal_thread_local _Thread_local -#define OPAL_HAVE_THREAD_LOCAL 1 - -#elif OPAL_C_HAVE___THREAD /* OPAL_C_HAVE__THREAD_LOCAL */ -#define opal_thread_local __thread -#define OPAL_HAVE_THREAD_LOCAL 1 -#endif /* OPAL_C_HAVE___THREAD */ +#ifndef OPAL_THREAD_USAGE_H +#define OPAL_THREAD_USAGE_H 1 -#if !defined(OPAL_HAVE_THREAD_LOCAL) -#define OPAL_HAVE_THREAD_LOCAL 0 -#endif /* !defined(OPAL_HAVE_THREAD_LOCAL) */ +#include "opal/mca/threads/thread_usage.h" -#endif /* !defined(OPAL_THREAD_USAGE_H) */ +#endif /* OPAL_THREAD_USAGE_H */ diff --git a/opal/threads/threads.h b/opal/threads/threads.h index 661d6b00ee0..ba7fcb081c0 100644 --- a/opal/threads/threads.h +++ b/opal/threads/threads.h @@ -24,118 +24,6 @@ #ifndef OPAL_THREAD_H #define OPAL_THREAD_H 1 -#include "opal_config.h" - -#include -#include - -#include "opal/class/opal_object.h" -#if OPAL_ENABLE_DEBUG -#include "opal/util/output.h" -#endif - -#include "mutex.h" -#include "condition.h" - -BEGIN_C_DECLS - -typedef void *(*opal_thread_fn_t) (opal_object_t *); - -#define OPAL_THREAD_CANCELLED ((void*)1); - -struct opal_thread_t { - opal_object_t super; - opal_thread_fn_t t_run; - void* t_arg; - pthread_t t_handle; -}; - -typedef struct opal_thread_t opal_thread_t; - -#if OPAL_ENABLE_DEBUG -OPAL_DECLSPEC extern bool opal_debug_threads; -#endif - - -OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_thread_t); - -#if OPAL_ENABLE_DEBUG -#define OPAL_ACQUIRE_THREAD(lck, cnd, act) \ - do { \ - OPAL_THREAD_LOCK((lck)); \ - if (opal_debug_threads) { \ - opal_output(0, "Waiting for thread %s:%d", \ - __FILE__, __LINE__); \ - } \ - while (*(act)) { \ - opal_condition_wait((cnd), (lck)); \ - } \ - if (opal_debug_threads) { \ - opal_output(0, "Thread obtained %s:%d", \ - __FILE__, __LINE__); \ - } \ - *(act) = true; \ - } while(0); -#else -#define OPAL_ACQUIRE_THREAD(lck, cnd, act) \ - do { \ - OPAL_THREAD_LOCK((lck)); \ - while (*(act)) { \ - opal_condition_wait((cnd), (lck)); \ - } \ - *(act) = true; \ - } while(0); -#endif - - -#if OPAL_ENABLE_DEBUG -#define OPAL_RELEASE_THREAD(lck, cnd, act) \ - do { \ - if (opal_debug_threads) { \ - opal_output(0, "Releasing thread %s:%d", \ - __FILE__, __LINE__); \ - } \ - *(act) = false; \ - opal_condition_broadcast((cnd)); \ - OPAL_THREAD_UNLOCK((lck)); \ - } while(0); -#else -#define OPAL_RELEASE_THREAD(lck, cnd, act) \ - do { \ - *(act) = false; \ - opal_condition_broadcast((cnd)); \ - OPAL_THREAD_UNLOCK((lck)); \ - } while(0); -#endif - - -#define OPAL_WAKEUP_THREAD(cnd, act) \ - do { \ - *(act) = false; \ - opal_condition_broadcast((cnd)); \ - } while(0); - -/* provide a macro for forward-proofing the shifting - * of objects between libevent threads - at some point, we - * may revamp that threading model */ - -/* post an object to another thread - for now, we - * only have a memory barrier */ -#define OPAL_POST_OBJECT(o) opal_atomic_wmb() - -/* acquire an object from another thread - for now, - * we only have a memory barrier */ -#define OPAL_ACQUIRE_OBJECT(o) opal_atomic_rmb() - - - -OPAL_DECLSPEC int opal_thread_start(opal_thread_t *); -OPAL_DECLSPEC int opal_thread_join(opal_thread_t *, void **thread_return); -OPAL_DECLSPEC bool opal_thread_self_compare(opal_thread_t*); -OPAL_DECLSPEC opal_thread_t *opal_thread_get_self(void); -OPAL_DECLSPEC void opal_thread_kill(opal_thread_t *, int sig); -OPAL_DECLSPEC void opal_thread_set_main(void); - -END_C_DECLS +#include "opal/mca/threads/threads.h" #endif /* OPAL_THREAD_H */ diff --git a/opal/threads/tsd.h b/opal/threads/tsd.h index e49c08dd96e..e059f15fca1 100644 --- a/opal/threads/tsd.h +++ b/opal/threads/tsd.h @@ -15,164 +15,6 @@ #ifndef OPAL_THREADS_TSD_H #define OPAL_THREADS_TSD_H -#include "opal_config.h" +#include "opal/mca/threads/tsd.h" -#include - -#include "opal/constants.h" - -BEGIN_C_DECLS - -/** - * @file - * - * Thread Specific Datastore Interface - * - * Functions for providing thread-specific datastore capabilities. - */ - - -/** - * Prototype for callback when tsd data is being destroyed - */ -typedef void (*opal_tsd_destructor_t)(void *value); - -#if defined(DOXYGEN) - -/** - * Typedef for thread-specific data key - */ -typedef void* opal_tsd_key_t; - - -/** - * Delete a thread-specific data key - * - * Delete a thread-specific data key previously returned by - * opal_tsd_key_create(). The destructor associated with the key is - * not fired in any thread and memory cleanup is the responsibility of - * the caller. - * - * @note Unlike pthread_key_delete, this function should not be called - * from within a destructor. It can not be universally supported at - * this time. - * - * @param key[in] The key for accessing thread-specific data - * - * @retval OPAL_SUCCESS Success - * @retval EINVAL Invalid key - */ -OPAL_DECLSPEC int opal_tsd_key_delete(opal_tsd_key_t key); - - -/** - * Set a thread-specific data value - * - * Associates value with key in the current thread. The value for the - * key in other threads is not changed. Different threads may assign - * different values to the same key. - * - * @note This function should not be called within - * opal_tsd_key_delete(). - * - * @param key[in] Thread specific data key to modify - * @param value[in] Value to associate with key - * - * @retval OPAL_SUCCESS Success - * @retval ENOMEM Insufficient memory exists to associate the - * value with the key - * @retval EINVAL Invalid key - */ -OPAL_DECLSPEC int opal_tsd_setspecific(opal_tsd_key_t key, void *value); - - -/** - * Get a thread-specific data value - * - * Get the data associated with the given key, as set by - * opal_tsd_setspecific(). If opal_tsd_setspecific() hasn't been - * called in the current thread with the given key, NULL is returned - * in valuep. - * - * @param key[in] Thread specific data key to modify - * @param value[out] Value to associate with key - * - * @retval OPAL_SUCCESS Success - * @retval ENOMEM Insufficient memory exists to associate the - * value with the key - * @retval EINVAL Invalid key - */ -OPAL_DECLSPEC int opal_tsd_getspecific(opal_tsd_key_t key, void **valuep); - -#else - -typedef pthread_key_t opal_tsd_key_t; - -static inline int -opal_tsd_key_delete(opal_tsd_key_t key) -{ - return pthread_key_delete(key); -} - -static inline int -opal_tsd_setspecific(opal_tsd_key_t key, void *value) -{ - return pthread_setspecific(key, value); -} - -static inline int -opal_tsd_getspecific(opal_tsd_key_t key, void **valuep) -{ - *valuep = pthread_getspecific(key); - return OPAL_SUCCESS; -} - -#endif - -/** - * Create thread-specific data key - * - * Create a thread-specific data key visible to all threads in the - * current process. The returned key is valid in all threads, - * although the values bound to the key by opal_tsd_setspecific() are - * allocated on a per-thread basis and persist for the life of the - * calling thread. - * - * Upon key creation, the value NULL is associated with the new key in - * all active threads. When a new thread is created, the value NULL - * is associated with all defined keys in the new thread. - * - * The destructor parameter may be NULL. At thread exit, if - * destructor is non-NULL AND the thread has a non-NULL value - * associated with the key, the function is called with the current - * value as its argument. - * - * @param key[out] The key for accessing thread-specific data - * @param destructor[in] Cleanup function to call when a thread exits - * - * @retval OPAL_SUCCESS Success - * @retval EAGAIN The system lacked the necessary resource to - * create another thread specific data key - * @retval ENOMEM Insufficient memory exists to create the key - */ -OPAL_DECLSPEC int opal_tsd_key_create(opal_tsd_key_t *key, - opal_tsd_destructor_t destructor); - - -/** - * Destruct all thread-specific data keys - * - * Destruct all thread-specific data keys and invoke the destructor - * - * This should only be invoked in the main thread. - * This is made necessary since destructors are not invoked on the - * keys of the main thread, since there is no such thing as - * pthread_join(main_thread) - * - * @retval OPAL_SUCCESS Success - */ -OPAL_DECLSPEC int opal_tsd_keys_destruct(void); - -END_C_DECLS - -#endif /* OPAL_MTHREADS_TSD_H */ +#endif /* OPAL_THREADS_TSD_H */ diff --git a/opal/threads/wait_sync.h b/opal/threads/wait_sync.h index 3e6c8f1949f..496ebed4f9c 100644 --- a/opal/threads/wait_sync.h +++ b/opal/threads/wait_sync.h @@ -8,7 +8,6 @@ * Copyright (c) 2016 Mellanox Technologies. All rights reserved. * Copyright (c) 2016 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2017 IBM Corporation. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -19,110 +18,6 @@ #if !defined(OPAL_THREADS_WAIT_SYNC_H) #define OPAL_THREADS_WAIT_SYNC_H -#include "opal/sys/atomic.h" -#include "opal/threads/condition.h" -#include - -BEGIN_C_DECLS - -extern int opal_max_thread_in_progress; - -typedef struct ompi_wait_sync_t { - opal_atomic_int32_t count; - int32_t status; - pthread_cond_t condition; - pthread_mutex_t lock; - struct ompi_wait_sync_t *next; - struct ompi_wait_sync_t *prev; - volatile bool signaling; -} ompi_wait_sync_t; - -#define REQUEST_PENDING (void*)0L -#define REQUEST_COMPLETED (void*)1L - -#define SYNC_WAIT(sync) (opal_using_threads() ? ompi_sync_wait_mt (sync) : sync_wait_st (sync)) - -/* The loop in release handles a race condition between the signaling - * thread and the destruction of the condition variable. The signaling - * member will be set to false after the final signaling thread has - * finished operating on the sync object. This is done to avoid - * extra atomics in the signalling function and keep it as fast - * as possible. Note that the race window is small so spinning here - * is more optimal than sleeping since this macro is called in - * the critical path. */ -#define WAIT_SYNC_RELEASE(sync) \ - if (opal_using_threads()) { \ - while ((sync)->signaling) { \ - continue; \ - } \ - pthread_cond_destroy(&(sync)->condition); \ - pthread_mutex_destroy(&(sync)->lock); \ - } - -#define WAIT_SYNC_RELEASE_NOWAIT(sync) \ - if (opal_using_threads()) { \ - pthread_cond_destroy(&(sync)->condition); \ - pthread_mutex_destroy(&(sync)->lock); \ - } - - -#define WAIT_SYNC_SIGNAL(sync) \ - if (opal_using_threads()) { \ - pthread_mutex_lock(&(sync->lock)); \ - pthread_cond_signal(&sync->condition); \ - pthread_mutex_unlock(&(sync->lock)); \ - sync->signaling = false; \ - } - -#define WAIT_SYNC_SIGNALLED(sync){ \ - (sync)->signaling = false; \ -} - -OPAL_DECLSPEC int ompi_sync_wait_mt(ompi_wait_sync_t *sync); -static inline int sync_wait_st (ompi_wait_sync_t *sync) -{ - while (sync->count > 0) { - opal_progress(); - } - - return sync->status; -} - - -#define WAIT_SYNC_INIT(sync,c) \ - do { \ - (sync)->count = (c); \ - (sync)->next = NULL; \ - (sync)->prev = NULL; \ - (sync)->status = 0; \ - (sync)->signaling = (0 != (c)); \ - if (opal_using_threads()) { \ - pthread_cond_init (&(sync)->condition, NULL); \ - pthread_mutex_init (&(sync)->lock, NULL); \ - } \ - } while(0) - -/** - * Update the status of the synchronization primitive. If an error is - * reported the synchronization is completed and the signal - * triggered. The status of the synchronization will be reported to - * the waiting threads. - */ -static inline void wait_sync_update(ompi_wait_sync_t *sync, int updates, int status) -{ - if( OPAL_LIKELY(OPAL_SUCCESS == status) ) { - if( 0 != (OPAL_THREAD_ADD_FETCH32(&sync->count, -updates)) ) { - return; - } - } else { - /* this is an error path so just use the atomic */ - sync->status = OPAL_ERROR; - opal_atomic_wmb (); - opal_atomic_swap_32 (&sync->count, 0); - } - WAIT_SYNC_SIGNAL(sync); -} - -END_C_DECLS +#include "opal/mca/threads/wait_sync.h" #endif /* defined(OPAL_THREADS_WAIT_SYNC_H) */ diff --git a/orte/util/threads.h b/orte/util/threads.h index 5bd1be82b5b..d5f9c9c3369 100644 --- a/orte/util/threads.h +++ b/orte/util/threads.h @@ -27,11 +27,11 @@ * we only have a memory barrier */ #define ORTE_ACQUIRE_OBJECT(o) opal_atomic_rmb() -#define orte_condition_wait(a,b) pthread_cond_wait(a, &(b)->m_lock_pthread) -typedef pthread_cond_t orte_condition_t; -#define orte_condition_broadcast(a) pthread_cond_broadcast(a) -#define orte_condition_signal(a) pthread_cond_signal(a) -#define ORTE_CONDITION_STATIC_INIT PTHREAD_COND_INITIALIZER +#define orte_condition_wait(a,b) opal_cond_wait(a,b) +typedef opal_cond_t orte_condition_t; +#define orte_condition_broadcast(a) opal_cond_broadcast(a) +#define orte_condition_signal(a) opal_cond_signal(a) +#define ORTE_CONDITION_STATIC_INIT OPAL_COND_INITIALIZER /* define a threadshift macro */ #define ORTE_THREADSHIFT(x, eb, f, p) \ @@ -51,14 +51,14 @@ typedef struct { #define ORTE_CONSTRUCT_LOCK(l) \ do { \ OBJ_CONSTRUCT(&(l)->mutex, opal_mutex_t); \ - pthread_cond_init(&(l)->cond, NULL); \ + opal_cond_init(&(l)->cond); \ (l)->active = true; \ } while(0) #define ORTE_DESTRUCT_LOCK(l) \ do { \ OBJ_DESTRUCT(&(l)->mutex); \ - pthread_cond_destroy(&(l)->cond); \ + opal_cond_destroy(&(l)->cond); \ } while(0) diff --git a/test/asm/Makefile.am b/test/asm/Makefile.am index 17f222bbd9d..61bc008caa1 100644 --- a/test/asm/Makefile.am +++ b/test/asm/Makefile.am @@ -43,39 +43,40 @@ atomic_barrier_noinline.c: ln -s $(top_srcdir)/test/asm/atomic_barrier.c atomic_barrier_noinline.c atomic_barrier_noinline_SOURCES = atomic_barrier_noinline.c atomic_barrier_noinline_CFLAGS = $(AM_CFLAGS) -DOMPI_DISABLE_INLINE_ASM +atomic_barrier_noinline_LDADD = $(libs) -lpthread ###################################################################### atomic_spinlock_SOURCES = atomic_spinlock.c -atomic_spinlock_LDADD = $(libs) +atomic_spinlock_LDADD = $(libs) -lpthread atomic_spinlock_noinline.c: ln -s $(top_srcdir)/test/asm/atomic_spinlock.c atomic_spinlock_noinline.c atomic_spinlock_noinline_SOURCES = atomic_spinlock_noinline.c atomic_spinlock_noinline_CFLAGS = $(AM_CFLAGS) -DOMPI_DISABLE_INLINE_ASM -atomic_spinlock_noinline_LDADD = $(libs) +atomic_spinlock_noinline_LDADD = $(libs) -lpthread ###################################################################### atomic_math_SOURCES = atomic_math.c -atomic_math_LDADD = $(libs) +atomic_math_LDADD = $(libs) -lpthread atomic_math_noinline.c: ln -s $(top_srcdir)/test/asm/atomic_math.c atomic_math_noinline.c atomic_math_noinline_SOURCES = atomic_math_noinline.c atomic_math_noinline_CFLAGS = $(AM_CFLAGS) -DOMPI_DISABLE_INLINE_ASM -atomic_math_noinline_LDADD = $(libs) +atomic_math_noinline_LDADD = $(libs) -lpthread ###################################################################### atomic_cmpset_SOURCES = atomic_cmpset.c -atomic_cmpset_LDADD = $(libs) +atomic_cmpset_LDADD = $(libs) -lpthread atomic_cmpset_noinline.c: ln -s $(top_srcdir)/test/asm/atomic_cmpset.c atomic_cmpset_noinline.c atomic_cmpset_noinline_SOURCES = atomic_cmpset_noinline.c atomic_cmpset_noinline_CFLAGS = $(AM_CFLAGS) -DOMPI_DISABLE_INLINE_ASM -atomic_cmpset_noinline_LDADD = $(libs) +atomic_cmpset_noinline_LDADD = $(libs) -lpthread ###################################################################### diff --git a/test/class/Makefile.am b/test/class/Makefile.am index 4dc7daf24cc..46f1c584ac9 100644 --- a/test/class/Makefile.am +++ b/test/class/Makefile.am @@ -92,13 +92,15 @@ ompi_rb_tree_DEPENDENCIES = $(ompi_rb_tree_LDADD) opal_lifo_SOURCES = opal_lifo.c opal_lifo_LDADD = \ $(top_builddir)/opal/lib@OPAL_LIB_PREFIX@open-pal.la \ - $(top_builddir)/test/support/libsupport.a + $(top_builddir)/test/support/libsupport.a \ + -lpthread opal_lifo_DEPENDENCIES = $(opal_lifo_LDADD) opal_fifo_SOURCES = opal_fifo.c opal_fifo_LDADD = \ $(top_builddir)/opal/lib@OPAL_LIB_PREFIX@open-pal.la \ - $(top_builddir)/test/support/libsupport.a + $(top_builddir)/test/support/libsupport.a \ + -lpthread opal_fifo_DEPENDENCIES = $(opal_fifo_LDADD) clean-local: diff --git a/test/class/opal_fifo.c b/test/class/opal_fifo.c index 122524a8d9f..400bfd55222 100644 --- a/test/class/opal_fifo.c +++ b/test/class/opal_fifo.c @@ -18,6 +18,7 @@ #include "opal/runtime/opal.h" #include "opal/constants.h" +#include #include #include #include diff --git a/test/class/opal_lifo.c b/test/class/opal_lifo.c index 521bb4e5d97..7997065b6d0 100644 --- a/test/class/opal_lifo.c +++ b/test/class/opal_lifo.c @@ -20,6 +20,7 @@ #include #include #include +#include #include