summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2016-02-26 12:05:16 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2016-02-26 12:05:16 +0000
commit54b618f6192912c8596d1bf28966a2ecd24e0c2b (patch)
tree01257b8db35598e1251ba73d86826c1c234a9da8
parent9bc7aa290e6c686715cdbb727352022be3f08a0d (diff)
downloadmpfr-54b618f6192912c8596d1bf28966a2ecd24e0c2b.tar.gz
Better threading support:
* Support for _Thread_local (C11). * Support build as thread-safe DLL on Windows (mainly changes from Stephan Tolksdorf). (merged changesets r7954,8245,9684,9778 from the trunk, with mpfr_flags_t replaced by unsigned int) git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/3.1@10130 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--acinclude.m447
-rw-r--r--src/const_catalan.c8
-rw-r--r--src/const_euler.c8
-rw-r--r--src/const_log2.c10
-rw-r--r--src/const_pi.c10
-rw-r--r--src/exceptions.c6
-rw-r--r--src/mpfr-impl.h96
-rw-r--r--src/mpfr-thread.h9
-rw-r--r--src/set_dfl_prec.c7
-rw-r--r--src/set_rnd.c8
10 files changed, 174 insertions, 35 deletions
diff --git a/acinclude.m4 b/acinclude.m4
index 40965e019..4639ced32 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -401,11 +401,12 @@ dnl there is some ld configuration problem. One of the effects can
dnl be that thread-local variables always evaluate to 0. So, it is
dnl important to run the test below.
if test "$enable_thread_safe" != no; then
-AC_MSG_CHECKING(for TLS support)
+AC_MSG_CHECKING(for TLS support using C11)
saved_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS -I$srcdir/src"
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#define MPFR_USE_THREAD_SAFE 1
+#define MPFR_USE_C11_THREAD_SAFE 1
#include "mpfr-thread.h"
MPFR_THREAD_ATTR int x = 17;
int main (void) {
@@ -414,20 +415,46 @@ int main (void) {
]])],
[AC_MSG_RESULT(yes)
AC_DEFINE([MPFR_USE_THREAD_SAFE],1,[Build MPFR as thread safe])
+ AC_DEFINE([MPFR_USE_C11_THREAD_SAFE],1,[Build MPFR as thread safe using C11])
+ tls_c11_support=yes
],
[AC_MSG_RESULT(no)
- if test "$enable_thread_safe" = yes; then
- AC_MSG_ERROR([please configure with --disable-thread-safe])
- fi
],
- [if test "$enable_thread_safe" = yes; then
- AC_MSG_RESULT([cannot test, assume yes])
- AC_DEFINE([MPFR_USE_THREAD_SAFE],1,[Build MPFR as thread safe])
- else
- AC_MSG_RESULT([cannot test, assume no])
- fi
+ [AC_MSG_RESULT([cannot test, assume no])
])
CPPFLAGS="$saved_CPPFLAGS"
+
+if test "$tls_c11_support" != "yes"
+then
+
+ AC_MSG_CHECKING(for TLS support)
+ saved_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS -I$srcdir/src"
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[
+ #define MPFR_USE_THREAD_SAFE 1
+ #include "mpfr-thread.h"
+ MPFR_THREAD_ATTR int x = 17;
+ int main() {
+ return x != 17;
+ }
+ ]])],
+ [AC_MSG_RESULT(yes)
+ AC_DEFINE([MPFR_USE_THREAD_SAFE],1,[Build MPFR as thread safe])
+ ],
+ [AC_MSG_RESULT(no)
+ if test "$enable_thread_safe" = yes; then
+ AC_MSG_ERROR([please configure with --disable-thread-safe])
+ fi
+ ],
+ [if test "$enable_thread_safe" = yes; then
+ AC_MSG_RESULT([cannot test, assume yes])
+ AC_DEFINE([MPFR_USE_THREAD_SAFE],1,[Build MPFR as thread safe])
+ else
+ AC_MSG_RESULT([cannot test, assume no])
+ fi
+ ])
+ CPPFLAGS="$saved_CPPFLAGS"
+ fi
fi
])
dnl end of MPFR_CONFIGS
diff --git a/src/const_catalan.c b/src/const_catalan.c
index db27b9d33..41b6bd97d 100644
--- a/src/const_catalan.c
+++ b/src/const_catalan.c
@@ -26,6 +26,14 @@ http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
/* Declare the cache */
MPFR_DECL_INIT_CACHE(__gmpfr_cache_const_catalan, mpfr_const_catalan_internal);
+#ifdef MPFR_WIN_THREAD_SAFE_DLL
+mpfr_cache_t *
+__gmpfr_cache_const_catalan_f()
+{
+ return &__gmpfr_cache_const_catalan;
+}
+#endif
+
/* Set User Interface */
#undef mpfr_const_catalan
int
diff --git a/src/const_euler.c b/src/const_euler.c
index bf538761a..e00dda53d 100644
--- a/src/const_euler.c
+++ b/src/const_euler.c
@@ -26,6 +26,14 @@ http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
/* Declare the cache */
MPFR_DECL_INIT_CACHE(__gmpfr_cache_const_euler, mpfr_const_euler_internal);
+#ifdef MPFR_WIN_THREAD_SAFE_DLL
+mpfr_cache_t *
+__gmpfr_cache_const_euler_f()
+{
+ return &__gmpfr_cache_const_euler;
+}
+#endif
+
/* Set User Interface */
#undef mpfr_const_euler
int
diff --git a/src/const_log2.c b/src/const_log2.c
index ababdeb5c..8496d2d58 100644
--- a/src/const_log2.c
+++ b/src/const_log2.c
@@ -32,6 +32,16 @@ MPFR_DECL_INIT_CACHE(__gmpfr_logging_log2, mpfr_const_log2_internal);
MPFR_THREAD_ATTR mpfr_cache_ptr __gmpfr_cache_const_log2 = __gmpfr_normal_log2;
#endif
+#ifdef MPFR_WIN_THREAD_SAFE_DLL
+# ifndef MPFR_USE_LOGGING
+mpfr_cache_t * __gmpfr_cache_const_log2_f() { return &__gmpfr_cache_const_log2; }
+# else
+mpfr_cache_t * __gmpfr_normal_log2_f() { return &__gmpfr_normal_log2; }
+mpfr_cache_t * __gmpfr_logging_log2_f() { return &__gmpfr_logging_log2; }
+mpfr_cache_ptr * __gmpfr_cache_const_log2_f() { return &__gmpfr_cache_const_log2; }
+# endif
+#endif
+
/* Set User interface */
#undef mpfr_const_log2
int
diff --git a/src/const_pi.c b/src/const_pi.c
index 05579f49a..7c555c9ee 100644
--- a/src/const_pi.c
+++ b/src/const_pi.c
@@ -31,6 +31,16 @@ MPFR_DECL_INIT_CACHE(__gmpfr_logging_pi, mpfr_const_pi_internal);
MPFR_THREAD_ATTR mpfr_cache_ptr __gmpfr_cache_const_pi = __gmpfr_normal_pi;
#endif
+#ifdef MPFR_WIN_THREAD_SAFE_DLL
+# ifndef MPFR_USE_LOGGING
+mpfr_cache_t * __gmpfr_cache_const_pi_f() { return &__gmpfr_cache_const_pi; }
+# else
+mpfr_cache_t * __gmpfr_normal_pi_f() { return &__gmpfr_normal_pi; }
+mpfr_cache_t * __gmpfr_logging_pi_f() { return &__gmpfr_logging_pi; }
+mpfr_cache_ptr * __gmpfr_cache_const_pi_f() { return &__gmpfr_cache_const_pi; }
+# endif
+#endif
+
/* Set User Interface */
#undef mpfr_const_pi
int
diff --git a/src/exceptions.c b/src/exceptions.c
index 555f3c2c8..ad8beb2c4 100644
--- a/src/exceptions.c
+++ b/src/exceptions.c
@@ -27,6 +27,12 @@ MPFR_THREAD_ATTR unsigned int __gmpfr_flags = 0;
MPFR_THREAD_ATTR mpfr_exp_t __gmpfr_emin = MPFR_EMIN_DEFAULT;
MPFR_THREAD_ATTR mpfr_exp_t __gmpfr_emax = MPFR_EMAX_DEFAULT;
+#ifdef MPFR_WIN_THREAD_SAFE_DLL
+unsigned int * __gmpfr_flags_f() { return &__gmpfr_flags; }
+mpfr_exp_t * __gmpfr_emin_f() { return &__gmpfr_emin; }
+mpfr_exp_t * __gmpfr_emax_f() { return &__gmpfr_emax; }
+#endif
+
#undef mpfr_get_emin
mpfr_exp_t
diff --git a/src/mpfr-impl.h b/src/mpfr-impl.h
index 00a38bad2..ea05ef2d8 100644
--- a/src/mpfr-impl.h
+++ b/src/mpfr-impl.h
@@ -235,6 +235,10 @@ typedef __gmp_const mp_limb_t *mpfr_limb_srcptr;
************* Global Internal Variables **************
******************************************************/
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
/* Cache struct */
struct __gmpfr_cache_s {
mpfr_t x;
@@ -244,32 +248,86 @@ struct __gmpfr_cache_s {
typedef struct __gmpfr_cache_s mpfr_cache_t[1];
typedef struct __gmpfr_cache_s *mpfr_cache_ptr;
-#if defined (__cplusplus)
-extern "C" {
+#if __GMP_LIBGMP_DLL
+# define MPFR_WIN_THREAD_SAFE_DLL 1
#endif
-__MPFR_DECLSPEC extern MPFR_THREAD_ATTR unsigned int __gmpfr_flags;
-__MPFR_DECLSPEC extern MPFR_THREAD_ATTR mpfr_exp_t __gmpfr_emin;
-__MPFR_DECLSPEC extern MPFR_THREAD_ATTR mpfr_exp_t __gmpfr_emax;
-__MPFR_DECLSPEC extern MPFR_THREAD_ATTR mpfr_prec_t __gmpfr_default_fp_bit_precision;
-__MPFR_DECLSPEC extern MPFR_THREAD_ATTR mpfr_rnd_t __gmpfr_default_rounding_mode;
-__MPFR_DECLSPEC extern MPFR_THREAD_ATTR mpfr_cache_t __gmpfr_cache_const_euler;
-__MPFR_DECLSPEC extern MPFR_THREAD_ATTR mpfr_cache_t __gmpfr_cache_const_catalan;
+/* Detect some possible inconsistencies under Unix. */
+#if defined(__unix__)
+# if defined(_WIN32)
+# error "Both __unix__ and _WIN32 are defined"
+# endif
+# if __GMP_LIBGMP_DLL
+# error "__unix__ is defined and __GMP_LIBGMP_DLL is true"
+# endif
+# if defined(MPFR_WIN_THREAD_SAFE_DLL)
+# error "Both __unix__ and MPFR_WIN_THREAD_SAFE_DLL are defined"
+# endif
+#endif
-#ifndef MPFR_USE_LOGGING
-__MPFR_DECLSPEC extern MPFR_THREAD_ATTR mpfr_cache_t __gmpfr_cache_const_pi;
-__MPFR_DECLSPEC extern MPFR_THREAD_ATTR mpfr_cache_t __gmpfr_cache_const_log2;
-#else
+#if defined(__MPFR_WITHIN_MPFR) || !defined(MPFR_WIN_THREAD_SAFE_DLL)
+extern MPFR_THREAD_ATTR unsigned int __gmpfr_flags;
+extern MPFR_THREAD_ATTR mpfr_exp_t __gmpfr_emin;
+extern MPFR_THREAD_ATTR mpfr_exp_t __gmpfr_emax;
+extern MPFR_THREAD_ATTR mpfr_prec_t __gmpfr_default_fp_bit_precision;
+extern MPFR_THREAD_ATTR mpfr_rnd_t __gmpfr_default_rounding_mode;
+extern MPFR_THREAD_ATTR mpfr_cache_t __gmpfr_cache_const_euler;
+extern MPFR_THREAD_ATTR mpfr_cache_t __gmpfr_cache_const_catalan;
+# ifndef MPFR_USE_LOGGING
+extern MPFR_THREAD_ATTR mpfr_cache_t __gmpfr_cache_const_pi;
+extern MPFR_THREAD_ATTR mpfr_cache_t __gmpfr_cache_const_log2;
+# else
/* Two constants are used by the logging functions (via mpfr_fprintf,
then mpfr_log, for the base conversion): pi and log(2). Since the
mpfr_cache function isn't re-entrant when working on the same cache,
we need to define two caches for each constant. */
-__MPFR_DECLSPEC extern MPFR_THREAD_ATTR mpfr_cache_t __gmpfr_normal_pi;
-__MPFR_DECLSPEC extern MPFR_THREAD_ATTR mpfr_cache_t __gmpfr_normal_log2;
-__MPFR_DECLSPEC extern MPFR_THREAD_ATTR mpfr_cache_t __gmpfr_logging_pi;
-__MPFR_DECLSPEC extern MPFR_THREAD_ATTR mpfr_cache_t __gmpfr_logging_log2;
-__MPFR_DECLSPEC extern MPFR_THREAD_ATTR mpfr_cache_ptr __gmpfr_cache_const_pi;
-__MPFR_DECLSPEC extern MPFR_THREAD_ATTR mpfr_cache_ptr __gmpfr_cache_const_log2;
+extern MPFR_THREAD_ATTR mpfr_cache_t __gmpfr_normal_pi;
+extern MPFR_THREAD_ATTR mpfr_cache_t __gmpfr_normal_log2;
+extern MPFR_THREAD_ATTR mpfr_cache_t __gmpfr_logging_pi;
+extern MPFR_THREAD_ATTR mpfr_cache_t __gmpfr_logging_log2;
+extern MPFR_THREAD_ATTR mpfr_cache_ptr __gmpfr_cache_const_pi;
+extern MPFR_THREAD_ATTR mpfr_cache_ptr __gmpfr_cache_const_log2;
+# endif
+#endif
+
+#ifdef MPFR_WIN_THREAD_SAFE_DLL
+__MPFR_DECLSPEC unsigned int * __gmpfr_flags_f();
+__MPFR_DECLSPEC mpfr_exp_t * __gmpfr_emin_f();
+__MPFR_DECLSPEC mpfr_exp_t * __gmpfr_emax_f();
+__MPFR_DECLSPEC mpfr_prec_t * __gmpfr_default_fp_bit_precision_f();
+__MPFR_DECLSPEC mpfr_rnd_t * __gmpfr_default_rounding_mode_f();
+__MPFR_DECLSPEC mpfr_cache_t * __gmpfr_cache_const_euler_f();
+__MPFR_DECLSPEC mpfr_cache_t * __gmpfr_cache_const_catalan_f();
+# ifndef MPFR_USE_LOGGING
+__MPFR_DECLSPEC mpfr_cache_t * __gmpfr_cache_const_pi_f();
+__MPFR_DECLSPEC mpfr_cache_t * __gmpfr_cache_const_log2_f();
+# else
+__MPFR_DECLSPEC mpfr_cache_t * __gmpfr_normal_pi_f();
+__MPFR_DECLSPEC mpfr_cache_t * __gmpfr_normal_log2_f();
+__MPFR_DECLSPEC mpfr_cache_t * __gmpfr_logging_pi_f();
+__MPFR_DECLSPEC mpfr_cache_t * __gmpfr_logging_log2_f();
+__MPFR_DECLSPEC mpfr_cache_ptr * __gmpfr_cache_const_pi_f();
+__MPFR_DECLSPEC mpfr_cache_ptr * __gmpfr_cache_const_log2_f();
+# endif
+# ifndef __MPFR_WITHIN_MPFR
+# define __gmpfr_flags (*__gmpfr_flags_f())
+# define __gmpfr_emin (*__gmpfr_emin_f())
+# define __gmpfr_emax (*__gmpfr_emax_f())
+# define __gmpfr_default_fp_bit_precision (*__gmpfr_default_fp_bit_precision_f())
+# define __gmpfr_default_rounding_mode (*__gmpfr_default_rounding_mode_f())
+# define __gmpfr_cache_const_euler (*__gmpfr_cache_const_euler_f())
+# define __gmpfr_cache_const_catalan (*__gmpfr_cache_const_catalan_f())
+# ifndef MPFR_USE_LOGGING
+# define __gmpfr_cache_const_pi (*__gmpfr_cache_const_pi_f())
+# define __gmpfr_cache_const_log2 (*__gmpfr_cache_const_log2_f())
+# else
+# define __gmpfr_normal_pi (*__gmpfr_normal_pi_f())
+# define __gmpfr_logging_pi (*__gmpfr_logging_pi_f())
+# define __gmpfr_logging_log2 (*__gmpfr_logging_log2_f())
+# define __gmpfr_cache_const_pi (*__gmpfr_cache_const_pi_f())
+# define __gmpfr_cache_const_log2 (*__gmpfr_cache_const_log2_f())
+# endif
+# endif
#endif
#define BASE_MAX 62
diff --git a/src/mpfr-thread.h b/src/mpfr-thread.h
index 32d9aef41..1ccaa17c3 100644
--- a/src/mpfr-thread.h
+++ b/src/mpfr-thread.h
@@ -31,12 +31,9 @@ http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
#ifndef MPFR_THREAD_ATTR
# ifdef MPFR_USE_THREAD_SAFE
# if defined(_MSC_VER)
-# if defined(_WINDLL)
-# error "Can't build MPFR DLL as thread safe."
-# define MPFR_THREAD_ATTR
-# else
-# define MPFR_THREAD_ATTR __declspec( thread )
-# endif
+# define MPFR_THREAD_ATTR __declspec( thread )
+# elif defined(MPFR_USE_C11_THREAD_SAFE)
+# define MPFR_THREAD_ATTR _Thread_local
# else
# define MPFR_THREAD_ATTR __thread
# endif
diff --git a/src/set_dfl_prec.c b/src/set_dfl_prec.c
index c11ded8d1..96464c459 100644
--- a/src/set_dfl_prec.c
+++ b/src/set_dfl_prec.c
@@ -26,6 +26,13 @@ http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
MPFR_THREAD_ATTR mpfr_prec_t __gmpfr_default_fp_bit_precision \
= IEEE_DBL_MANT_DIG;
+#ifdef MPFR_WIN_THREAD_SAFE_DLL
+mpfr_prec_t * __gmpfr_default_fp_bit_precision_f()
+{
+ return &__gmpfr_default_fp_bit_precision;
+}
+#endif
+
void
mpfr_set_default_prec (mpfr_prec_t prec)
{
diff --git a/src/set_rnd.c b/src/set_rnd.c
index 6336a9852..10fc23231 100644
--- a/src/set_rnd.c
+++ b/src/set_rnd.c
@@ -25,6 +25,14 @@ http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
MPFR_THREAD_ATTR mpfr_rnd_t __gmpfr_default_rounding_mode = MPFR_RNDN;
+#ifdef MPFR_WIN_THREAD_SAFE_DLL
+mpfr_rnd_t *
+__gmpfr_default_rounding_mode_f()
+{
+ return &__gmpfr_default_rounding_mode;
+}
+#endif
+
void
mpfr_set_default_rounding_mode (mpfr_rnd_t rnd_mode)
{