From 73c1ce4fdbdf117b4d91b6e894686228155bd702 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Tue, 19 Nov 2013 13:39:56 +0000 Subject: Make powerpc-nofpu floating-point state thread-local (bug 15483). --- sysdeps/powerpc/nofpu/Versions | 5 ++++ sysdeps/powerpc/nofpu/fclrexcpt.c | 3 ++- sysdeps/powerpc/nofpu/fedisblxcpt.c | 6 +++-- sysdeps/powerpc/nofpu/feenablxcpt.c | 9 +++---- sysdeps/powerpc/nofpu/fegetenv.c | 10 +++----- sysdeps/powerpc/nofpu/fegetexcept.c | 2 +- sysdeps/powerpc/nofpu/fegetround.c | 2 +- sysdeps/powerpc/nofpu/fesetenv.c | 10 +++++--- sysdeps/powerpc/nofpu/fesetround.c | 3 ++- sysdeps/powerpc/nofpu/feupdateenv.c | 7 +++--- sysdeps/powerpc/nofpu/fgetexcptflg.c | 2 +- sysdeps/powerpc/nofpu/fraiseexcpt.c | 5 ++-- sysdeps/powerpc/nofpu/fsetexcptflg.c | 4 +++- sysdeps/powerpc/nofpu/ftestexcept.c | 2 +- sysdeps/powerpc/nofpu/get-rounding-mode.h | 2 +- sysdeps/powerpc/nofpu/sim-full.c | 39 ++++++++++++++++++++----------- sysdeps/powerpc/nofpu/soft-supp.h | 37 ++++++++++++++++++++--------- 17 files changed, 94 insertions(+), 54 deletions(-) (limited to 'sysdeps/powerpc/nofpu') diff --git a/sysdeps/powerpc/nofpu/Versions b/sysdeps/powerpc/nofpu/Versions index 1a29319d5a..8ba6021e9e 100644 --- a/sysdeps/powerpc/nofpu/Versions +++ b/sysdeps/powerpc/nofpu/Versions @@ -17,4 +17,9 @@ libc { __gtdf2; __gtsf2; __ltdf2; __ltsf2; } + GLIBC_PRIVATE { + __sim_exceptions_thread; + __sim_disabled_exceptions_thread; + __sim_round_mode_thread; + } } diff --git a/sysdeps/powerpc/nofpu/fclrexcpt.c b/sysdeps/powerpc/nofpu/fclrexcpt.c index fabda0ab98..da0b61a894 100644 --- a/sysdeps/powerpc/nofpu/fclrexcpt.c +++ b/sysdeps/powerpc/nofpu/fclrexcpt.c @@ -23,7 +23,8 @@ int __feclearexcept (int x) { - __sim_exceptions &= ~x; + __sim_exceptions_thread &= ~x; + SIM_SET_GLOBAL (__sim_exceptions_global, __sim_exceptions_thread); return 0; } diff --git a/sysdeps/powerpc/nofpu/fedisblxcpt.c b/sysdeps/powerpc/nofpu/fedisblxcpt.c index e06c8f7676..00490fd6ed 100644 --- a/sysdeps/powerpc/nofpu/fedisblxcpt.c +++ b/sysdeps/powerpc/nofpu/fedisblxcpt.c @@ -24,9 +24,11 @@ int fedisableexcept (int x) { - int old_exceptions = ~__sim_disabled_exceptions & FE_ALL_EXCEPT; + int old_exceptions = ~__sim_disabled_exceptions_thread & FE_ALL_EXCEPT; - __sim_disabled_exceptions |= x; + __sim_disabled_exceptions_thread |= x; + SIM_SET_GLOBAL (__sim_disabled_exceptions_global, + __sim_disabled_exceptions_thread); return old_exceptions; } diff --git a/sysdeps/powerpc/nofpu/feenablxcpt.c b/sysdeps/powerpc/nofpu/feenablxcpt.c index 93249abf6c..09eb823b8b 100644 --- a/sysdeps/powerpc/nofpu/feenablxcpt.c +++ b/sysdeps/powerpc/nofpu/feenablxcpt.c @@ -17,16 +17,17 @@ License along with the GNU C Library. If not, see . */ +#include "soft-supp.h" #include -extern int __sim_disabled_exceptions; - int feenableexcept (int exceptions) { - int old_exceptions = ~__sim_disabled_exceptions & FE_ALL_EXCEPT; + int old_exceptions = ~__sim_disabled_exceptions_thread & FE_ALL_EXCEPT; - __sim_disabled_exceptions &= ~exceptions; + __sim_disabled_exceptions_thread &= ~exceptions; + SIM_SET_GLOBAL (__sim_disabled_exceptions_global, + __sim_disabled_exceptions_thread); return old_exceptions; } diff --git a/sysdeps/powerpc/nofpu/fegetenv.c b/sysdeps/powerpc/nofpu/fegetenv.c index 51bcef30a1..351e5526c7 100644 --- a/sysdeps/powerpc/nofpu/fegetenv.c +++ b/sysdeps/powerpc/nofpu/fegetenv.c @@ -20,18 +20,14 @@ #include "soft-fp.h" #include "soft-supp.h" -extern int __sim_exceptions; -extern int __sim_disabled_exceptions; -extern int __sim_round_mode; - int __fegetenv (fenv_t *envp) { fenv_union_t u; - u.l[0] = __sim_exceptions; - u.l[0] |= __sim_round_mode; - u.l[1] = __sim_disabled_exceptions; + u.l[0] = __sim_exceptions_thread; + u.l[0] |= __sim_round_mode_thread; + u.l[1] = __sim_disabled_exceptions_thread; *envp = u.fenv; diff --git a/sysdeps/powerpc/nofpu/fegetexcept.c b/sysdeps/powerpc/nofpu/fegetexcept.c index ea39a82b73..d907555fb6 100644 --- a/sysdeps/powerpc/nofpu/fegetexcept.c +++ b/sysdeps/powerpc/nofpu/fegetexcept.c @@ -23,5 +23,5 @@ int fegetexcept (void) { - return (__sim_disabled_exceptions ^ FE_ALL_EXCEPT) & FE_ALL_EXCEPT; + return (__sim_disabled_exceptions_thread ^ FE_ALL_EXCEPT) & FE_ALL_EXCEPT; } diff --git a/sysdeps/powerpc/nofpu/fegetround.c b/sysdeps/powerpc/nofpu/fegetround.c index c232ae3794..016602fac6 100644 --- a/sysdeps/powerpc/nofpu/fegetround.c +++ b/sysdeps/powerpc/nofpu/fegetround.c @@ -24,5 +24,5 @@ int fegetround (void) { - return __sim_round_mode; + return __sim_round_mode_thread; } diff --git a/sysdeps/powerpc/nofpu/fesetenv.c b/sysdeps/powerpc/nofpu/fesetenv.c index 3f35909b6d..fa84169836 100644 --- a/sysdeps/powerpc/nofpu/fesetenv.c +++ b/sysdeps/powerpc/nofpu/fesetenv.c @@ -26,9 +26,13 @@ __fesetenv (const fenv_t *envp) fenv_union_t u; u.fenv = *envp; - __sim_exceptions = u.l[0] & FE_ALL_EXCEPT; - __sim_round_mode = u.l[0] & 0x3; - __sim_disabled_exceptions = u.l[1]; + __sim_exceptions_thread = u.l[0] & FE_ALL_EXCEPT; + SIM_SET_GLOBAL (__sim_exceptions_global, __sim_exceptions_thread); + __sim_round_mode_thread = u.l[0] & 0x3; + SIM_SET_GLOBAL (__sim_round_mode_global, __sim_round_mode_thread); + __sim_disabled_exceptions_thread = u.l[1]; + SIM_SET_GLOBAL (__sim_disabled_exceptions_global, + __sim_disabled_exceptions_thread); return 0; } diff --git a/sysdeps/powerpc/nofpu/fesetround.c b/sysdeps/powerpc/nofpu/fesetround.c index 028c1300cc..ab0d52f237 100644 --- a/sysdeps/powerpc/nofpu/fesetround.c +++ b/sysdeps/powerpc/nofpu/fesetround.c @@ -26,7 +26,8 @@ fesetround (int round) if ((unsigned int) round > FE_DOWNWARD) return 1; - __sim_round_mode = round; + __sim_round_mode_thread = round; + SIM_SET_GLOBAL (__sim_round_mode_global, __sim_round_mode_thread); return 0; } diff --git a/sysdeps/powerpc/nofpu/feupdateenv.c b/sysdeps/powerpc/nofpu/feupdateenv.c index 163f673102..8a26cb86d1 100644 --- a/sysdeps/powerpc/nofpu/feupdateenv.c +++ b/sysdeps/powerpc/nofpu/feupdateenv.c @@ -28,14 +28,15 @@ __feupdateenv (const fenv_t *envp) int saved_exceptions; /* Save currently set exceptions. */ - saved_exceptions = __sim_exceptions; + saved_exceptions = __sim_exceptions_thread; /* Set environment. */ fesetenv (envp); /* Raise old exceptions. */ - __sim_exceptions |= saved_exceptions; - if (saved_exceptions & ~__sim_disabled_exceptions) + __sim_exceptions_thread |= saved_exceptions; + SIM_SET_GLOBAL (__sim_exceptions_global, __sim_exceptions_thread); + if (saved_exceptions & ~__sim_disabled_exceptions_thread) raise (SIGFPE); return 0; diff --git a/sysdeps/powerpc/nofpu/fgetexcptflg.c b/sysdeps/powerpc/nofpu/fgetexcptflg.c index 2373fa4002..b7fd90d71e 100644 --- a/sysdeps/powerpc/nofpu/fgetexcptflg.c +++ b/sysdeps/powerpc/nofpu/fgetexcptflg.c @@ -23,7 +23,7 @@ int __fegetexceptflag (fexcept_t *flagp, int excepts) { - *flagp = (fexcept_t) __sim_exceptions & excepts & FE_ALL_EXCEPT; + *flagp = (fexcept_t) __sim_exceptions_thread & excepts & FE_ALL_EXCEPT; return 0; } diff --git a/sysdeps/powerpc/nofpu/fraiseexcpt.c b/sysdeps/powerpc/nofpu/fraiseexcpt.c index cd142b60be..215a70b4bf 100644 --- a/sysdeps/powerpc/nofpu/fraiseexcpt.c +++ b/sysdeps/powerpc/nofpu/fraiseexcpt.c @@ -25,8 +25,9 @@ int __feraiseexcept (int x) { - __sim_exceptions |= x; - if (x & ~__sim_disabled_exceptions) + __sim_exceptions_thread |= x; + SIM_SET_GLOBAL (__sim_exceptions_global, __sim_exceptions_thread); + if (x & ~__sim_disabled_exceptions_thread) raise (SIGFPE); return 0; } diff --git a/sysdeps/powerpc/nofpu/fsetexcptflg.c b/sysdeps/powerpc/nofpu/fsetexcptflg.c index 3dc368fdda..ee2aa81a4e 100644 --- a/sysdeps/powerpc/nofpu/fsetexcptflg.c +++ b/sysdeps/powerpc/nofpu/fsetexcptflg.c @@ -24,7 +24,9 @@ int __fesetexceptflag(const fexcept_t *flagp, int excepts) { /* Ignore exceptions not listed in 'excepts'. */ - __sim_exceptions = (__sim_exceptions & ~excepts) | (*flagp & excepts); + __sim_exceptions_thread + = (__sim_exceptions_thread & ~excepts) | (*flagp & excepts); + SIM_SET_GLOBAL (__sim_exceptions_global, __sim_exceptions_thread); return 0; } diff --git a/sysdeps/powerpc/nofpu/ftestexcept.c b/sysdeps/powerpc/nofpu/ftestexcept.c index f5d01e881c..42e861da33 100644 --- a/sysdeps/powerpc/nofpu/ftestexcept.c +++ b/sysdeps/powerpc/nofpu/ftestexcept.c @@ -23,6 +23,6 @@ int fetestexcept (int x) { - return __sim_exceptions & x; + return __sim_exceptions_thread & x; } libm_hidden_def (fetestexcept) diff --git a/sysdeps/powerpc/nofpu/get-rounding-mode.h b/sysdeps/powerpc/nofpu/get-rounding-mode.h index 20eb81030f..6d327f57c7 100644 --- a/sysdeps/powerpc/nofpu/get-rounding-mode.h +++ b/sysdeps/powerpc/nofpu/get-rounding-mode.h @@ -29,7 +29,7 @@ static inline int get_rounding_mode (void) { - return __sim_round_mode; + return __sim_round_mode_thread; } #endif /* get-rounding-mode.h */ diff --git a/sysdeps/powerpc/nofpu/sim-full.c b/sysdeps/powerpc/nofpu/sim-full.c index e16703323d..fb09d1bc9d 100644 --- a/sysdeps/powerpc/nofpu/sim-full.c +++ b/sysdeps/powerpc/nofpu/sim-full.c @@ -21,26 +21,37 @@ #include "soft-fp.h" #include "soft-supp.h" -/* FIXME: these variables should be thread specific (see bugzilla bug - 15483) and ideally preserved across signal handlers, like hardware - FP status words, but the latter is quite difficult to accomplish in - userland. */ - -/* Global to store sticky exceptions. */ -int __sim_exceptions __attribute__ ((nocommon)); -libc_hidden_data_def (__sim_exceptions); +/* Thread-local to store sticky exceptions. */ +__thread int __sim_exceptions_thread __attribute__ ((nocommon)); +libc_hidden_data_def (__sim_exceptions_thread); /* By default, no exceptions should trap. */ -int __sim_disabled_exceptions = 0xffffffff; -libc_hidden_data_def (__sim_disabled_exceptions); +__thread int __sim_disabled_exceptions_thread = 0xffffffff; +libc_hidden_data_def (__sim_disabled_exceptions_thread); + +__thread int __sim_round_mode_thread __attribute__ ((nocommon)); +libc_hidden_data_def (__sim_round_mode_thread); + +#if SIM_GLOBAL_COMPAT +int __sim_exceptions_global __attribute__ ((nocommon)); +libc_hidden_data_def (__sim_exceptions_global); +SIM_COMPAT_SYMBOL (__sim_exceptions_global, __sim_exceptions); + +int __sim_disabled_exceptions_global = 0xffffffff; +libc_hidden_data_def (__sim_disabled_exceptions_global); +SIM_COMPAT_SYMBOL (__sim_disabled_exceptions_global, + __sim_disabled_exceptions); -int __sim_round_mode __attribute__ ((nocommon)); -libc_hidden_data_def (__sim_round_mode); +int __sim_round_mode_global __attribute__ ((nocommon)); +libc_hidden_data_def (__sim_round_mode_global); +SIM_COMPAT_SYMBOL (__sim_round_mode_global, __sim_round_mode); +#endif void __simulate_exceptions (int x) { - __sim_exceptions |= x; - if (x & ~__sim_disabled_exceptions) + __sim_exceptions_thread |= x; + SIM_SET_GLOBAL (__sim_exceptions_global, __sim_exceptions_thread); + if (x & ~__sim_disabled_exceptions_thread) raise (SIGFPE); } diff --git a/sysdeps/powerpc/nofpu/soft-supp.h b/sysdeps/powerpc/nofpu/soft-supp.h index 18b4550e3b..0a0614aa6a 100644 --- a/sysdeps/powerpc/nofpu/soft-supp.h +++ b/sysdeps/powerpc/nofpu/soft-supp.h @@ -33,16 +33,31 @@ typedef union #endif -/* FIXME: these variables should be thread specific (see bugzilla bug - 15483) and ideally preserved across signal handlers, like hardware - FP status words, but the latter is quite difficult to accomplish in - userland. */ - -extern int __sim_exceptions; -libc_hidden_proto (__sim_exceptions); -extern int __sim_disabled_exceptions; -libc_hidden_proto (__sim_disabled_exceptions); -extern int __sim_round_mode; -libc_hidden_proto (__sim_round_mode); +extern __thread int __sim_exceptions_thread attribute_tls_model_ie; +libc_hidden_tls_proto (__sim_exceptions_thread, tls_model ("initial-exec")); +extern __thread int __sim_disabled_exceptions_thread attribute_tls_model_ie; +libc_hidden_tls_proto (__sim_disabled_exceptions_thread, + tls_model ("initial-exec")); +extern __thread int __sim_round_mode_thread attribute_tls_model_ie; +libc_hidden_tls_proto (__sim_round_mode_thread, tls_model ("initial-exec")); + +/* These variables were formerly global, so there are compat symbols + for global versions as well. */ + +#include +#define SIM_GLOBAL_COMPAT SHLIB_COMPAT (libc, GLIBC_2_3_2, GLIBC_2_19) +#if SIM_GLOBAL_COMPAT +extern int __sim_exceptions_global; +libc_hidden_proto (__sim_exceptions_global); +extern int __sim_disabled_exceptions_global ; +libc_hidden_proto (__sim_disabled_exceptions_global); +extern int __sim_round_mode_global; +libc_hidden_proto (__sim_round_mode_global); +# define SIM_COMPAT_SYMBOL(GLOBAL_NAME, NAME) \ + compat_symbol (libc, GLOBAL_NAME, NAME, GLIBC_2_3_2) +# define SIM_SET_GLOBAL(GLOBAL_VAR, THREAD_VAR) ((GLOBAL_VAR) = (THREAD_VAR)) +#else +# define SIM_SET_GLOBAL(GLOBAL_VAR, THREAD_VAR) ((void) 0) +#endif extern void __simulate_exceptions (int x) attribute_hidden; -- cgit v1.2.3