From 0e9f9a280af0e4944c18996beb6e110f48fe841e Mon Sep 17 00:00:00 2001 From: Dana Robinson Date: Fri, 26 Feb 2021 11:34:53 -0800 Subject: Adds MacOS work-around for sigtimedwait(2) in the VFD SWMR tests --- configure.ac | 132 +++++++++++++++++++++++-------------------------- test/vfd_swmr_common.c | 85 ++++++++++++++++++++++++++++++- 2 files changed, 147 insertions(+), 70 deletions(-) diff --git a/configure.ac b/configure.ac index 6d869f9..2307b4a 100644 --- a/configure.ac +++ b/configure.ac @@ -1750,84 +1750,78 @@ esac if test "X$THREADSAFE" = "Xyes"; then AC_DEFINE([HAVE_THREADSAFE], [1], [Define if we have thread safe support]) +fi - ## ---------------------------------------------------------------------- - ## Is the Pthreads library present? It has a header file `pthread.h' and - ## a library `-lpthread' and their locations might be specified with the - ## `--with-pthread' command-line switch. The value is an include path - ## and/or a library path. If the library path is specified then it must - ## be preceded by a comma. - ## - ## Thread-safety in HDF5 only uses Pthreads via configure, so the - ## default is "check", though this only has an effect when - ## --enable-threadsafe is specified. - AC_SUBST([HAVE_PTHREAD]) HAVE_PTHREAD=yes - AC_ARG_WITH([pthread], - [AS_HELP_STRING([--with-pthread=DIR], - [Specify alternative path to Pthreads library when - thread-safe capability is built.])],, - [withval=check]) +## ---------------------------------------------------------------------- +## Is the Pthreads library present? It has a header file `pthread.h' and +## a library `-lpthread' and their locations might be specified with the +## `--with-pthread' command-line switch. The value is an include path +## and/or a library path. If the library path is specified then it must +## be preceded by a comma. +AC_SUBST([HAVE_PTHREAD]) + +AC_ARG_WITH([pthread], + [AS_HELP_STRING([--with-pthread=DIR], + [Specify alternative path to Pthreads library when + thread-safe capability is built.])],, + [withval=check]) +case "$withval" in + check | yes) + AC_CHECK_HEADERS([pthread.h],,) + AC_CHECK_LIB([pthread], [pthread_self]) + ;; + no) + AC_MSG_RESULT([suppressed]) + ;; + *) case "$withval" in - check | yes) - AC_CHECK_HEADERS([pthread.h],, [unset HAVE_PTHREAD]) - if test "x$HAVE_PTHREAD" = "xyes"; then - AC_CHECK_LIB([pthread], [pthread_self],, [unset HAVE_PTHREAD]) - fi - ;; - no) - AC_MSG_ERROR([Must use Pthreads with thread safety]) + *,*) + pthread_inc="`echo $withval | cut -f1 -d,`" + pthread_lib="`echo $withval | cut -f2 -d, -s`" ;; *) - case "$withval" in - *,*) - pthread_inc="`echo $withval | cut -f1 -d,`" - pthread_lib="`echo $withval | cut -f2 -d, -s`" - ;; - *) - if test -n "$withval"; then - pthread_inc="$withval/include" - pthread_lib="$withval/lib" - fi - ;; - esac - - if test -n "$pthread_inc"; then - saved_CPPFLAGS="$CPPFLAGS" - saved_AM_CPPFLAGS="$AM_CPPFLAGS" - CPPFLAGS="$CPPFLAGS -I$pthread_inc" - AM_CPPFLAGS="$AM_CPPFLAGS -I$pthread_inc" - AC_CHECK_HEADERS([pthread.h],, [CPPFLAGS="$saved_CPPFLAGS"; AM_CPPFLAGS="$saved_AM_CPPFLAGS"; unset HAVE_PTHREAD]) - else - AC_CHECK_HEADERS([pthread.h],, [unset HAVE_PTHREAD]) - fi - - if test "x$HAVE_PTHREAD" = "xyes"; then - if test -n "$pthread_lib"; then - saved_LDFLAGS="$LDFLAGS" - saved_AM_LDFLAGS="$AM_LDFLAGS" - LDFLAGS="$LDFLAGS -L$pthread_lib" - AM_LDFLAGS="$AM_LDFLAGS -L$pthread_lib" - AC_CHECK_LIB([pthread], [pthread_self],, - [LDFLAGS="$saved_LDFLAGS"; AM_LDFLAGS="$saved_AM_LDFLAGS"; unset HAVE_PTHREAD]) - else - AC_CHECK_LIB([pthread], [pthread_self],, [unset HAVE_PTHREAD]) - fi + if test -n "$withval"; then + pthread_inc="$withval/include" + pthread_lib="$withval/lib" fi ;; esac - ## ---------------------------------------------------------------------- - ## Check if pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM) - ## is supported on this system - ## - ## Unfortunately, this probably needs to be an AC_RUN_IFELSE since - ## it's impossible to determine if PTHREAD_SCOPE_SYSTEM is - ## supported a priori. POSIX.1-2001 requires that a conformant - ## system need only support one of SYSTEM or PROCESS scopes. - ## - ## For cross-compiling, we've added a pessimistic 'no'. You can - ## hand-hack the config file if you know otherwise. + if test -n "$pthread_inc"; then + saved_CPPFLAGS="$CPPFLAGS" + saved_AM_CPPFLAGS="$AM_CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I$pthread_inc" + AM_CPPFLAGS="$AM_CPPFLAGS -I$pthread_inc" + AC_CHECK_HEADERS([pthread.h],,[CPPFLAGS="$saved_CPPFLAGS"; AM_CPPFLAGS="$saved_AM_CPPFLAGS";]) + else + AC_CHECK_HEADERS([pthread.h]) + fi + + if test -n "$pthread_lib"; then + saved_LDFLAGS="$LDFLAGS" + saved_AM_LDFLAGS="$AM_LDFLAGS" + LDFLAGS="$LDFLAGS -L$pthread_lib" + AM_LDFLAGS="$AM_LDFLAGS -L$pthread_lib" + AC_CHECK_LIB([pthread], [pthread_self],,[LDFLAGS="$saved_LDFLAGS"; AM_LDFLAGS="$saved_AM_LDFLAGS";]) + else + AC_CHECK_LIB([pthread], [pthread_self]) + fi + ;; +esac + +## ---------------------------------------------------------------------- +## Check if pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM) +## is supported on this system +## +## Unfortunately, this probably needs to be an AC_RUN_IFELSE since +## it's impossible to determine if PTHREAD_SCOPE_SYSTEM is +## supported a priori. POSIX.1-2001 requires that a conformant +## system need only support one of SYSTEM or PROCESS scopes. +## +## For cross-compiling, we've added a pessimistic 'no'. You can +## hand-hack the config file if you know otherwise. +if test "x$HAVE_PTHREAD" = "xyes"; then AC_MSG_CHECKING([Pthreads supports system scope]) AC_CACHE_VAL([hdf5_cv_system_scope_threads], [AC_RUN_IFELSE( diff --git a/test/vfd_swmr_common.c b/test/vfd_swmr_common.c index 043b7ed..d4bb8ef 100644 --- a/test/vfd_swmr_common.c +++ b/test/vfd_swmr_common.c @@ -20,6 +20,9 @@ /***********/ #include /* for err(3) */ +#if defined(__APPLE__) && defined(__MACH__) +#include +#endif #include "h5test.h" #include "vfd_swmr_common.h" @@ -178,6 +181,55 @@ strsignal(int signum) } #endif +#if defined(__APPLE__) && defined(__MACH__) + +typedef struct timer_params_t { + struct timespec *tick; + hid_t fid; +} timer_params_t; + +pthread_mutex_t timer_mutex; +hbool_t timer_stop = FALSE; + +static void * +timer_function(void *arg) +{ + timer_params_t *params = (timer_params_t *)arg; + sigset_t sleepset; + hbool_t done = FALSE; + + /* Ignore any signals */ + sigfillset(&sleepset); + pthread_sigmask(SIG_SETMASK, &sleepset, NULL); + + for (;;) { + estack_state_t es; + + nanosleep(params->tick, NULL); + + /* Check the mutex */ + pthread_mutex_lock(&timer_mutex); + done = timer_stop; + pthread_mutex_unlock(&timer_mutex); + if (done) + break; + + /* Avoid deadlock with peer: periodically enter the API so that + * tick processing occurs and data is flushed so that the peer + * can see it. + * + * The call we make will fail, but that's ok, + * so squelch errors. + */ + es = disable_estack(); + (void)H5Aexists_by_name(params->fid, "nonexistent", "nonexistent", H5P_DEFAULT); + restore_estack(es); + } + + return NULL; +} +#endif + /* Wait for any signal to occur and then return. Wake periodically * during the wait to perform API calls: in this way, the * VFD SWMR tick number advances and recent changes do not languish @@ -186,8 +238,8 @@ strsignal(int signum) void await_signal(hid_t fid) { - sigset_t sleepset; struct timespec tick = {.tv_sec = 0, .tv_nsec = 1000000000 / 100}; + sigset_t sleepset; if (sigfillset(&sleepset) == -1) { err(EXIT_FAILURE, "%s.%d: could not initialize signal mask", @@ -202,7 +254,37 @@ await_signal(hid_t fid) dbgf(1, "waiting for signal\n"); +#if defined(__APPLE__) && defined(__MACH__) + { + /* MacOS does not have sigtimedwait(2), so use an alternative. + * XXX: Replace with configure macros later. + */ + timer_params_t params; + int rc; + pthread_t timer; + + params.tick = &tick; + params.fid = fid; + + pthread_mutex_init(&timer_mutex, NULL); + + pthread_create(&timer, NULL, timer_function, ¶ms); + + rc = sigwait(&sleepset, NULL); + + if (rc != -1) { + fprintf(stderr, "Received signal, wrapping things up.\n"); + pthread_mutex_lock(&timer_mutex); + timer_stop = TRUE; + pthread_mutex_unlock(&timer_mutex); + pthread_join(timer, NULL); + } + else + err(EXIT_FAILURE, "%s: sigtimedwait", __func__); + } +#else for (;;) { + /* Linux and other systems */ const int rc = sigtimedwait(&sleepset, NULL, &tick); if (rc != -1) { @@ -226,6 +308,7 @@ await_signal(hid_t fid) } else if (rc == -1) err(EXIT_FAILURE, "%s: sigtimedwait", __func__); } +#endif } /* Revised support routines that can be used for all VFD SWMR integration tests -- cgit v0.12