summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2019-01-27 18:30:16 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2019-01-27 18:30:16 +0000
commit592bf5d9862783d712f906e6014515abae90c64a (patch)
treebc189d25235745886f7b9a785082b9177d12680d
parentf79ac796ca6326648311669eebe001379c315b17 (diff)
downloadmpfr-592bf5d9862783d712f906e6014515abae90c64a.tar.gz
Shared cache: cleanup and various improvements / corrections.
* acinclude.m4: - test $enable_shared_cache instead of $mpfr_want_shared_cache; - check ISO C11 thread support and/or POSIX thread support only when necessary; - when checking support for POSIX threads (pthread), also check that pthread_rwlock_t is supported, as it is needed by MPFR and conditionally defined in glibc's bits/pthreadtypes.h (via <pthread.h>); - with POSIX threads, also set CC="$PTHREAD_CC" as documented by ax_pthread (autoconf-archive). This is not guaranteed to work, but according to the ax_pthread.m4 source, in the cases where "$PTHREAD_CC" != "$CC", not setting it will probably not work either; - handle --enable-shared-cache early in MPFR_CONFIGS, because the use of POSIX threads (pthread) may need to change CC, CFLAGS, and LIBS (thus affecting other tests); - removed the now useless MPFR_CHECK_SHARED_CACHE function. * configure.ac: no longer set the mpfr_want_shared_cache variable, as enable_shared_cache (now used) already has the same usage. * acinclude.m4, configure.ac: moved the compatibility test of the configure options even earlier, from acinclude.m4 to configure.ac, just after the code that defines them. Also added an associated AC_MSG_CHECKING message for better clarity. * src/mpfr-impl.h: added a comment about the cache-related types, which depend on the locking methods. * src/mpfr-thread.h: fixed the lock macros: - in case of failure, one must abort, otherwise this would generally be undefined behavior; - added missing "do {} while (0)" (currently not mandatory). * tests/tversion.c: update concerning the shared cache, to be consistent with the other mpfr_buildopt_*_p features: - check that mpfr_buildopt_sharedcache_p() and MPFR_WANT_SHARED_CACHE match; - for the output of the value, test mpfr_buildopt_sharedcache_p() instead of the macro. * NEWS: update. (merged changesets r13032,13390-13396,13410,13412 from the trunk) git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/4.0@13416 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--NEWS1
-rw-r--r--acinclude.m4117
-rw-r--r--configure.ac26
-rw-r--r--src/mpfr-impl.h4
-rw-r--r--src/mpfr-thread.h81
-rw-r--r--tests/tversion.c22
6 files changed, 132 insertions, 119 deletions
diff --git a/NEWS b/NEWS
index e2d78b9a7..e4f334270 100644
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,7 @@ https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
Changes from version 4.0.1 to version 4.0.2:
- Corrected minimal GMP version in the INSTALL file and the MPFR manual.
+- Shared caches: cleanup; really detect lock failures (abort in this case).
- Improved MPFR manual. In particular, corrected/completed the
mpfr_get_str description in order to follow the historical behavior
and GMP's mpf_get_str function.
diff --git a/acinclude.m4 b/acinclude.m4
index 5cc1df4c6..02a11973c 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -44,6 +44,66 @@ AC_REQUIRE([MPFR_CHECK_LIBQUADMATH])
AC_REQUIRE([AC_HEADER_TIME])
AC_REQUIRE([AC_CANONICAL_HOST])
+dnl Features for the MPFR shared cache. This needs to be done
+dnl quite early since this may change CC, CFLAGS and LIBS, which
+dnl may affect the other tests.
+
+if test "$enable_shared_cache" = yes; then
+
+dnl Prefer ISO C11 threads (as in mpfr-thread.h).
+ MPFR_CHECK_C11_THREAD()
+
+ if test "$mpfr_c11_thread_ok" != yes; then
+dnl Check for POSIX threads. Since the AX_PTHREAD macro is not standard
+dnl (it is provided by autoconf-archive), we need to detect whether it
+dnl is left unexpanded, otherwise the configure script won't fail and
+dnl "make distcheck" won't give any error, yielding buggy tarballs!
+dnl The \b is necessary to avoid an error with recent ax_pthread.m4
+dnl (such as with Debian's autoconf-archive 20160320-1), which contains
+dnl AX_PTHREAD_ZOS_MISSING, etc. It is not documented, but see:
+dnl https://lists.gnu.org/archive/html/autoconf/2015-03/msg00011.html
+dnl
+dnl Note: each time a change is done in m4_pattern_forbid, autogen.sh
+dnl should be tested with and without ax_pthread.m4 availability (in
+dnl the latter case, there should be an error).
+ m4_pattern_forbid([AX_PTHREAD\b])
+ AX_PTHREAD([])
+ if test "$ax_pthread_ok" = yes; then
+ CC="$PTHREAD_CC"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LIBS="$LIBS $PTHREAD_LIBS"
+dnl Do a compilation test, as this is currently not done by AX_PTHREAD.
+dnl Moreover, MPFR needs pthread_rwlock_t, which is conditionally defined
+dnl in glibc's bits/pthreadtypes.h (via <pthread.h>), not sure why...
+ AC_MSG_CHECKING([for pthread_rwlock_t])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <pthread.h>
+]], [[
+pthread_rwlock_t lock; (void) lock;
+]])],
+ [AC_MSG_RESULT([yes])
+ mpfr_pthread_ok=yes],
+ [AC_MSG_RESULT([no])
+ mpfr_pthread_ok=no])
+ else
+ mpfr_pthread_ok=no
+ fi
+ fi
+
+ AC_MSG_CHECKING(if shared cache can be supported)
+ if test "$mpfr_c11_thread_ok" = yes; then
+ AC_MSG_RESULT([yes, with ISO C11 threads])
+ elif test "$mpfr_pthread_ok" = yes; then
+ AC_MSG_RESULT([yes, with pthread])
+ else
+ AC_MSG_RESULT(no)
+ AC_MSG_ERROR([shared cache needs C11 threads or pthread support])
+ fi
+
+fi
+
+dnl End of features for the MPFR shared cache.
+
AC_CHECK_HEADER([limits.h],, AC_MSG_ERROR([limits.h not found]))
AC_CHECK_HEADER([float.h],, AC_MSG_ERROR([float.h not found]))
AC_CHECK_HEADER([string.h],, AC_MSG_ERROR([string.h not found]))
@@ -206,24 +266,6 @@ fi
dnl Check for attribute constructor and destructor
MPFR_CHECK_CONSTRUCTOR_ATTR()
-dnl Check for POSIX Thread. Since the AX_PTHREAD macro is not standard
-dnl (it is provided by autoconf-archive), we need to detect whether it
-dnl is left unexpanded, otherwise the configure script won't fail and
-dnl "make distcheck" won't give any error, yielding buggy tarballs!
-dnl The \b is necessary to avoid an error with recent ax_pthread.m4
-dnl (such as with Debian's autoconf-archive 20160320-1), which contains
-dnl AX_PTHREAD_ZOS_MISSING, etc. It is not documented, but see:
-dnl https://lists.gnu.org/archive/html/autoconf/2015-03/msg00011.html
-dnl
-dnl Note: each time a change is done in m4_pattern_forbid, autogen.sh
-dnl should be tested with and without ax_pthread.m4 availability (in
-dnl the latter case, there should be an error).
-m4_pattern_forbid([AX_PTHREAD\b])
-AX_PTHREAD([])
-
-dnl Check for ISO C11 Thread
-MPFR_CHECK_C11_THREAD()
-
dnl Check for fesetround
AC_CACHE_CHECK([for fesetround], mpfr_cv_have_fesetround, [
saved_LIBS="$LIBS"
@@ -504,14 +546,6 @@ LIBS="$saved_LIBS"
dnl Now try to check the long double format
MPFR_C_LONG_DOUBLE_FORMAT
-if test "$enable_logging" = yes; then
- if test "$enable_thread_safe" = yes; then
- AC_MSG_ERROR([enable either `Logging' or `thread-safe', not both])
- else
- enable_thread_safe=no
- fi
-fi
-
dnl Check if thread-local variables are supported.
dnl At least two problems can occur in practice:
dnl 1. The compilation fails, e.g. because the compiler doesn't know
@@ -690,11 +724,6 @@ if test "$enable_lto" = "yes" ; then
MPFR_LTO
fi
-dnl Check if the shared cache was requested and its requirements are ok.
-if test "$mpfr_want_shared_cache" = yes ;then
- MPFR_CHECK_SHARED_CACHE()
-fi
-
])
dnl end of MPFR_CONFIGS
@@ -1517,32 +1546,6 @@ mpfr_compile_and_link()
rm -f conftest*
])
-dnl MPFR_CHECK_SHARED_CACHE
-dnl ----------------------
-dnl Check if the conditions for the shared cache are met:
-dnl * either pthread / C11 are available.
-dnl * either constructor or once.
-AC_DEFUN([MPFR_CHECK_SHARED_CACHE], [
- AC_MSG_CHECKING(if shared cache is supported)
- if test "$enable_logging" = yes ; then
- AC_MSG_RESULT(no)
- AC_MSG_ERROR([shared cache does not work with logging support.])
-dnl because logging support disables threading support
- elif test "$enable_thread_safe" != yes ; then
- AC_MSG_RESULT(no)
- AC_MSG_ERROR([shared cache needs thread attribute.])
- elif test "$ax_pthread_ok" != yes && "$mpfr_c11_thread_ok" != yes ; then
- AC_MSG_RESULT(no)
- AC_MSG_ERROR([shared cache needs pthread/C11 library.])
- else
- AC_MSG_RESULT(yes)
- if test "$ax_pthread_ok" = yes ; then
- CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
- LIBS="$LIBS $PTHREAD_LIBS"
- fi
- fi
-])
-
dnl MPFR_CHECK_CONSTRUCTOR_ATTR
dnl ---------------------------
dnl Check for constructor/destructor attributes to function.
diff --git a/configure.ac b/configure.ac
index 2f8ae8fd3..19f83b85d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -167,7 +167,7 @@ AC_ARG_ENABLE(shared-cache,
for all MPFR constants. It usually makes MPFR
dependent on PTHREAD [[default=no]]],
[ case $enableval in
- yes) mpfr_want_shared_cache=yes
+ yes)
AC_DEFINE([MPFR_WANT_SHARED_CACHE],1,[Want shared cache]) ;;
no) ;;
*) AC_MSG_ERROR([bad value for --enable-shared-cache: yes or no]) ;;
@@ -204,6 +204,30 @@ AC_ARG_ENABLE(tune-for-coverage,
*) AC_MSG_ERROR([bad value for --enable-tune-for-coverage]) ;;
esac])
+dnl First, detect incompatibilities between the above configure options.
+AC_MSG_CHECKING([whether configure options are compatible])
+if test "$enable_logging" = yes; then
+ if test "$enable_thread_safe" = yes; then
+ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([enable either logging or thread-safe, not both])
+ fi
+dnl The following test is done only to output a specific error message,
+dnl as there would otherwise be an error due to enable_thread_safe=no.
+ if test "$enable_shared_cache" = yes; then
+ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([shared cache does not work with logging support])
+ fi
+ enable_thread_safe=no
+fi
+if test "$enable_shared_cache" = yes; then
+ if test "$enable_thread_safe" = no; then
+ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([shared cache needs thread-safe support])
+ fi
+ enable_thread_safe=yes
+fi
+AC_MSG_RESULT([yes])
+
dnl
dnl Setup CC and CFLAGS
diff --git a/src/mpfr-impl.h b/src/mpfr-impl.h
index d2843ab68..805e3cb4a 100644
--- a/src/mpfr-impl.h
+++ b/src/mpfr-impl.h
@@ -213,6 +213,10 @@ extern "C" {
# define MPFR_CACHE_ATTR MPFR_THREAD_ATTR
#endif
+/* Note: The following structure and types depend on the MPFR build options
+ (including compiler options), due to the various locking methods affecting
+ MPFR_DEFERRED_INIT_SLAVE_DECL and MPFR_LOCK_DECL. But since this is only
+ internal, that's OK. */
struct __gmpfr_cache_s {
mpfr_t x;
int inexact;
diff --git a/src/mpfr-thread.h b/src/mpfr-thread.h
index ed04d9bcf..6ae66745a 100644
--- a/src/mpfr-thread.h
+++ b/src/mpfr-thread.h
@@ -64,38 +64,21 @@ https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
#define MPFR_LOCK_DECL(_lock) \
mtx_t _lock;
-#define MPFR_LOCK_INIT(_lock) do { \
- int error_code = mtx_init(&(_lock), mtx_plain); \
- MPFR_ASSERTD( error_code == thrd_success); \
+#define MPFR_LOCK_C(E) \
+ do { \
+ if ((E) != thrd_success) \
+ abort (); \
} while (0)
-#define MPFR_LOCK_CLEAR(_lock) do { \
- mtx_destroy(&(_lock)); \
- } while (0)
-
-#define MPFR_LOCK_READ(_lock) do { \
- int error_code = mtx_lock(&(_lock)); \
- MPFR_ASSERTD(error_code == thrd_success); \
- } while (0)
-
-#define MPFR_UNLOCK_READ(_lock) do { \
- int error_code = mtx_unlock(&(_lock)); \
- MPFR_ASSERTD(error_code == thrd_success); \
- } while (0)
+#define MPFR_LOCK_INIT(_lock) MPFR_LOCK_C(mtx_init(&(_lock), mtx_plain))
+#define MPFR_LOCK_CLEAR(_lock) do { mtx_destroy(&(_lock)); } while (0)
+#define MPFR_LOCK_READ(_lock) MPFR_LOCK_C(mtx_lock(&(_lock)))
+#define MPFR_UNLOCK_READ(_lock) MPFR_LOCK_C(mtx_unlock(&(_lock)))
+#define MPFR_LOCK_WRITE(_lock) MPFR_LOCK_C(mtx_lock(&(_lock)))
+#define MPFR_UNLOCK_WRITE(_lock) MPFR_LOCK_C(mtx_unlock(&(_lock)))
-#define MPFR_LOCK_WRITE(_lock) do { \
- int error_code = mtx_lock(&(_lock)); \
- MPFR_ASSERTD(error_code == thrd_success); \
- } while (0)
-
-#define MPFR_UNLOCK_WRITE(_lock) do { \
- int error_code = mtx_unlock(&(_lock)); \
- MPFR_ASSERTD(error_code == thrd_success); \
- } while (0)
-
-#define MPFR_LOCK_READ2WRITE(_lock)
-
-#define MPFR_LOCK_WRITE2READ(_lock)
+#define MPFR_LOCK_READ2WRITE(_lock) do {} while (0)
+#define MPFR_LOCK_WRITE2READ(_lock) do {} while (0)
#define MPFR_ONCE_DECL(_once) \
once_flag _once;
@@ -121,37 +104,25 @@ https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
#include <pthread.h>
-#define MPFR_LOCK_DECL(_lock) \
+#define MPFR_LOCK_DECL(_lock) \
pthread_rwlock_t _lock;
-#define MPFR_LOCK_INIT(_lock) do { \
- int error_code = pthread_rwlock_init(&(_lock), NULL); \
- MPFR_ASSERTD( error_code == 0); \
+#define MPFR_LOCK_C(E) \
+ do { \
+ if ((E) != 0) \
+ abort (); \
} while (0)
+#define MPFR_LOCK_INIT(_lock) MPFR_LOCK_C(pthread_rwlock_init(&(_lock), NULL))
+
#define MPFR_LOCK_CLEAR(_lock) do { \
pthread_rwlock_destroy(&(_lock)); \
} while (0)
-#define MPFR_LOCK_READ(_lock) do { \
- int error_code = pthread_rwlock_rdlock(&(_lock)); \
- MPFR_ASSERTD(error_code == 0); \
- } while (0)
-
-#define MPFR_UNLOCK_READ(_lock) do { \
- int error_code = pthread_rwlock_unlock(&(_lock)); \
- MPFR_ASSERTD(error_code == 0); \
- } while (0)
-
-#define MPFR_LOCK_WRITE(_lock) do { \
- int error_code = pthread_rwlock_wrlock(&(_lock)); \
- MPFR_ASSERTD(error_code == 0); \
- } while (0)
-
-#define MPFR_UNLOCK_WRITE(_lock) do { \
- int error_code = pthread_rwlock_unlock(&(_lock)); \
- MPFR_ASSERTD(error_code == 0); \
- } while (0)
+#define MPFR_LOCK_READ(_lock) MPFR_LOCK_C(pthread_rwlock_rdlock(&(_lock)))
+#define MPFR_UNLOCK_READ(_lock) MPFR_LOCK_C(pthread_rwlock_unlock(&(_lock)))
+#define MPFR_LOCK_WRITE(_lock) MPFR_LOCK_C(pthread_rwlock_wrlock(&(_lock)))
+#define MPFR_UNLOCK_WRITE(_lock) MPFR_LOCK_C(pthread_rwlock_unlock(&(_lock)))
#define MPFR_LOCK_READ2WRITE(_lock) do { \
MPFR_UNLOCK_READ(_lock); \
@@ -168,10 +139,8 @@ https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
#define MPFR_ONCE_INIT_VALUE PTHREAD_ONCE_INIT
-#define MPFR_ONCE_CALL(_once, _func) do { \
- int error_code = pthread_once (&(_once), (_func)); \
- MPFR_ASSERTD (error_code == 0); \
- } while (0)
+#define MPFR_ONCE_CALL(_once, _func) \
+ MPFR_LOCK_C(pthread_once (&(_once), (_func)))
#define MPFR_NEED_DEFERRED_INIT 1
diff --git a/tests/tversion.c b/tests/tversion.c
index 902aed6f8..bffa8d37c 100644
--- a/tests/tversion.c
+++ b/tests/tversion.c
@@ -268,6 +268,17 @@ main (void)
err = 1;
}
+ if (
+#ifdef MPFR_WANT_SHARED_CACHE
+ !
+#endif
+ mpfr_buildopt_sharedcache_p ())
+ {
+ printf ("ERROR! mpfr_buildopt_sharedcache_p() and macros"
+ " do not match!\n");
+ err = 1;
+ }
+
(printf) ("[tversion] TLS = %s, float128 = %s, decimal = %s,"
" GMP internals = %s\n",
mpfr_buildopt_tls_p () ? "yes" : "no",
@@ -281,13 +292,14 @@ main (void)
")" : "no",
mpfr_buildopt_gmpinternals_p () ? "yes" : "no");
- (puts) ("[tversion] Shared cache = "
-#if defined(MPFR_WANT_SHARED_CACHE)
- "yes (" MPFR_THREAD_LOCK_METHOD ")"
+#ifdef MPFR_THREAD_LOCK_METHOD
+# define LOCK_METHOD " (lock method: " MPFR_THREAD_LOCK_METHOD ")"
#else
- "no"
+# define LOCK_METHOD ""
#endif
- );
+
+ (printf) ("[tversion] Shared cache = %s\n",
+ mpfr_buildopt_sharedcache_p () ? "yes" LOCK_METHOD : "no");
(puts) ("[tversion] intmax_t = "
#if defined(_MPFR_H_HAVE_INTMAX_T)