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). --- ChangeLog | 67 ++++++++++ NEWS | 17 +-- math/Makefile | 3 +- math/test-fenv-tls.c | 208 ++++++++++++++++++++++++++++++ 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 ++++-- sysdeps/powerpc/soft-fp/sfp-machine.h | 23 ++-- 22 files changed, 390 insertions(+), 76 deletions(-) create mode 100644 math/test-fenv-tls.c diff --git a/ChangeLog b/ChangeLog index 9568016864..0f032197aa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,70 @@ +2013-11-19 Joseph Myers + + [BZ #15483] + * sysdeps/powerpc/nofpu/sim-full.c (__sim_exceptions): Change to + thread-local __sim_exceptions_thread and global + __sim_exceptions_global. + (__sim_disabled_exceptions): Change to thread-local + __sim_disabled_exceptions_thread and global + __sim_disabled_exceptions_global. + (__sim_round_mode): Change to thread-local __sim_round_mode_thread + and global __sim_round_mode_global. + (__simulate_exceptions): Use thread-local floating-point state and + set global state from it as needed. + * sysdeps/powerpc/nofpu/Versions (GLIBC_PRIVATE): Add + __sim_exceptions_thread, __sim_disabled_exceptions_thread and + __sim_round_mode_thread. + * sysdeps/powerpc/nofpu/soft-supp.h: Include . + (__sim_exceptions): Change to thread-local __sim_exceptions_thread + and global __sim_exceptions_global. + (__sim_disabled_exceptions): Change to thread-local + __sim_disabled_exceptions_thread and global + __sim_disabled_exceptions_global. + (__sim_round_mode): Change to thread-local __sim_round_mode_thread + and global __sim_round_mode_global. + [SIM_GLOBAL_COMPAT] (SIM_COMPAT_SYMBOL): New macro. + (SIM_SET_GLOBAL): Likewise. + * sysdeps/powerpc/soft-fp/sfp-machine.h + [!(__NO_FPRS__ && !_SOFT_FLOAT)] (FP_ROUNDMODE): Use + __sim_round_mode_thread. + [!(__NO_FPRS__ && !_SOFT_FLOAT)] (FP_TRAPPING_EXCEPTIONS): Use + __sim_disabled_exceptions_thread. + (__sim_exceptions): Change to __sim_exceptions_thread. + (__sim_disabled_exceptions): Change to + __sim_disabled_exceptions_thread. + (__sim_round_mode): Change to __sim_round_mode_thread. + * sysdeps/powerpc/nofpu/fclrexcpt.c (__feclearexcept): Use + thread-local floating-point state and set global state from it as + needed. + * sysdeps/powerpc/nofpu/fedisblxcpt.c (fedisableexcept): Likewise. + * sysdeps/powerpc/nofpu/feenablxcpt.c: Include "soft-supp.h". + (__sim_disabled_exceptions): Remove extern declaration. + (feenableexcept): Use thread-local floating-point state and set + global state from it as needed. + * sysdeps/powerpc/nofpu/fegetenv.c (__sim_exceptions): Remove + extern declaration. + (__sim_disabled_exceptions): Likewise. + (__sim_round_mode): Likewise. + (__fegetenv): Use thread-local floating-point state. + * sysdeps/powerpc/nofpu/fegetexcept.c (fegetexcept): Likewise. + * sysdeps/powerpc/nofpu/fegetround.c (fegetround): Likewise. + * sysdeps/powerpc/nofpu/fesetenv.c (__fesetenv): Use thread-local + floating-point state and set global state from it as needed. + * sysdeps/powerpc/nofpu/fesetround.c (fesetround): Likewise. + * sysdeps/powerpc/nofpu/feupdateenv.c (__feupdateenv): Likewise. + * sysdeps/powerpc/nofpu/fgetexcptflg.c (__fegetexceptflag): + Likewise. + * sysdeps/powerpc/nofpu/fraiseexcpt.c (__feraiseexcept): Likewise. + * sysdeps/powerpc/nofpu/fsetexcptflg.c (__fesetexceptflag): + Likewise. + sysdeps/powerpc/nofpu/ftestexcept.c (fetestexcept): Likewise. + * sysdeps/powerpc/nofpu/get-rounding-mode.h (get_rounding_mode): + Use __sim_round_mode_thread. + * math/test-fenv-tls.c: New file. + * math/Makefile (tests): Add test-fenv-tls. + ($(objpfx)test-fenv-tls): Depend on + $(common-objpfx)nptl/libpthread.so. + 2013-11-19 Andreas Schwab * locale/programs/locale.c (show_info): Decode wordarray elements. diff --git a/NEWS b/NEWS index 26fdfd47c8..0fdc535dd4 100644 --- a/NEWS +++ b/NEWS @@ -11,14 +11,15 @@ Version 2.19 156, 387, 431, 832, 2801, 7003, 9954, 10253, 10278, 11087, 13028, 13982, 13985, 14029, 14143, 14155, 14547, 14699, 14752, 14876, 14910, 15048, - 15218, 15277, 15308, 15362, 15374, 15400, 15427, 15522, 15531, 15532, - 15608, 15609, 15610, 15632, 15640, 15670, 15672, 15680, 15681, 15723, - 15734, 15735, 15736, 15748, 15749, 15754, 15760, 15763, 15764, 15797, - 15799, 15825, 15844, 15847, 15849, 15855, 15856, 15857, 15859, 15867, - 15886, 15887, 15890, 15892, 15893, 15895, 15897, 15905, 15909, 15917, - 15919, 15921, 15923, 15939, 15948, 15963, 15966, 15985, 15988, 15997, - 16032, 16034, 16036, 16037, 16041, 16055, 16071, 16072, 16074, 16078, - 16103, 16112, 16143, 16144, 16146, 16150, 16151, 16153, 16167, 16172. + 15218, 15277, 15308, 15362, 15374, 15400, 15427, 15483, 15522, 15531, + 15532, 15608, 15609, 15610, 15632, 15640, 15670, 15672, 15680, 15681, + 15723, 15734, 15735, 15736, 15748, 15749, 15754, 15760, 15763, 15764, + 15797, 15799, 15825, 15844, 15847, 15849, 15855, 15856, 15857, 15859, + 15867, 15886, 15887, 15890, 15892, 15893, 15895, 15897, 15905, 15909, + 15917, 15919, 15921, 15923, 15939, 15948, 15963, 15966, 15985, 15988, + 15997, 16032, 16034, 16036, 16037, 16041, 16055, 16071, 16072, 16074, + 16078, 16103, 16112, 16143, 16144, 16146, 16150, 16151, 16153, 16167, + 16172. * CVE-2012-4412 The strcoll implementation caches indices and rules for large collation sequences to optimize multiple passes. This cache diff --git a/math/Makefile b/math/Makefile index a9bd49baee..fcccab2051 100644 --- a/math/Makefile +++ b/math/Makefile @@ -90,7 +90,7 @@ tests = test-matherr test-fenv atest-exp atest-sincos atest-exp2 basic-test \ test-misc test-fpucw test-fpucw-ieee tst-definitions test-tgmath \ test-tgmath-ret bug-nextafter bug-nexttoward bug-tgmath1 \ test-tgmath-int test-tgmath2 test-powl tst-CMPLX tst-CMPLX2 test-snan \ - $(tests-static) + test-fenv-tls $(tests-static) tests-static = test-fpucw-static test-fpucw-ieee-static # We do the `long double' tests only if this data type is available and # distinct from `double'. @@ -232,3 +232,4 @@ gmp-objs = $(patsubst %,$(common-objpfx)stdlib/%.o,\ $(objpfx)atest-exp: $(gmp-objs) $(objpfx)atest-sincos: $(gmp-objs) $(objpfx)atest-exp2: $(gmp-objs) +$(objpfx)test-fenv-tls: $(common-objpfx)nptl/libpthread.so diff --git a/math/test-fenv-tls.c b/math/test-fenv-tls.c new file mode 100644 index 0000000000..879c9f9518 --- /dev/null +++ b/math/test-fenv-tls.c @@ -0,0 +1,208 @@ +/* Test floating-point environment is thread-local. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include + +#define TEST_ONE_RM(RM) \ + do \ + { \ + if (fesetround (RM) == 0) \ + { \ + rm = fegetround (); \ + if (rm != RM) \ + { \ + printf ("expected " #RM ", got %d\n", rm); \ + ret = 1; \ + } \ + } \ + } \ + while (0) + +static void * +test_round (void *arg) +{ + intptr_t ret = 0; + for (int i = 0; i < 10000; i++) + { + int rm; +#ifdef FE_DOWNWARD + TEST_ONE_RM (FE_DOWNWARD); +#endif +#ifdef FE_TONEAREST + TEST_ONE_RM (FE_TONEAREST); +#endif +#ifdef FE_TOWARDZERO + TEST_ONE_RM (FE_TOWARDZERO); +#endif +#ifdef FE_UPWARD + TEST_ONE_RM (FE_UPWARD); +#endif + } + return (void *) ret; +} + +#define TEST_ONE_RAISE(EX) \ + do \ + { \ + if (feraiseexcept (EX) == 0) \ + if (fetestexcept (EX) != EX) \ + { \ + printf (#EX " not raised\n"); \ + ret = 1; \ + } \ + if (feclearexcept (FE_ALL_EXCEPT) == 0) \ + if (fetestexcept (FE_ALL_EXCEPT) != 0) \ + { \ + printf ("exceptions not all cleared\n"); \ + ret = 1; \ + } \ + } \ + while (0) + +static void * +test_raise (void *arg) +{ + intptr_t ret = 0; + for (int i = 0; i < 10000; i++) + { +#ifdef FE_DIVBYZERO + TEST_ONE_RAISE (FE_DIVBYZERO); +#endif +#ifdef FE_INEXACT + TEST_ONE_RAISE (FE_INEXACT); +#endif +#ifdef FE_INVALID + TEST_ONE_RAISE (FE_INVALID); +#endif +#ifdef FE_OVERFLOW + TEST_ONE_RAISE (FE_OVERFLOW); +#endif +#ifdef UNDERFLOW + TEST_ONE_RAISE (FE_UNDERFLOW); +#endif + } + return (void *) ret; +} + +#define TEST_ONE_ENABLE(EX) \ + do \ + { \ + if (feenableexcept (EX) != -1) \ + if (fegetexcept () != EX) \ + { \ + printf (#EX " not enabled\n"); \ + ret = 1; \ + } \ + if (fedisableexcept (EX) != -1) \ + if (fegetexcept () != 0) \ + { \ + printf ("exceptions not all disabled\n"); \ + ret = 1; \ + } \ + } \ + while (0) + +static void * +test_enable (void *arg) +{ + intptr_t ret = 0; + for (int i = 0; i < 10000; i++) + { +#ifdef FE_DIVBYZERO + TEST_ONE_ENABLE (FE_DIVBYZERO); +#endif +#ifdef FE_INEXACT + TEST_ONE_ENABLE (FE_INEXACT); +#endif +#ifdef FE_INVALID + TEST_ONE_ENABLE (FE_INVALID); +#endif +#ifdef FE_OVERFLOW + TEST_ONE_ENABLE (FE_OVERFLOW); +#endif +#ifdef UNDERFLOW + TEST_ONE_ENABLE (FE_UNDERFLOW); +#endif + } + return (void *) ret; +} + +static int +do_test (void) +{ + int ret = 0; + void *vret; + pthread_t thread_id; + int pret; + + pret = pthread_create (&thread_id, NULL, test_round, NULL); + if (pret != 0) + { + printf ("pthread_create failed: %d\n", pret); + return 1; + } + vret = test_round (NULL); + ret |= (intptr_t) vret; + pret = pthread_join (thread_id, &vret); + if (pret != 0) + { + printf ("pthread_join failed: %d\n", pret); + return 1; + } + ret |= (intptr_t) vret; + + pret = pthread_create (&thread_id, NULL, test_raise, NULL); + if (pret != 0) + { + printf ("pthread_create failed: %d\n", pret); + return 1; + } + vret = test_raise (NULL); + ret |= (intptr_t) vret; + pret = pthread_join (thread_id, &vret); + if (pret != 0) + { + printf ("pthread_join failed: %d\n", pret); + return 1; + } + ret |= (intptr_t) vret; + + pret = pthread_create (&thread_id, NULL, test_enable, NULL); + if (pret != 0) + { + printf ("pthread_create failed: %d\n", pret); + return 1; + } + vret = test_enable (NULL); + ret |= (intptr_t) vret; + pret = pthread_join (thread_id, &vret); + if (pret != 0) + { + printf ("pthread_join failed: %d\n", pret); + return 1; + } + ret |= (intptr_t) vret; + + return ret; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" 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; diff --git a/sysdeps/powerpc/soft-fp/sfp-machine.h b/sysdeps/powerpc/soft-fp/sfp-machine.h index 0411878071..35a38b0031 100644 --- a/sysdeps/powerpc/soft-fp/sfp-machine.h +++ b/sysdeps/powerpc/soft-fp/sfp-machine.h @@ -95,21 +95,18 @@ libc_hidden_proto (__feraiseexcept_soft) # define FP_EX_INEXACT (1 << (31 - 6)) # define FP_HANDLE_EXCEPTIONS __simulate_exceptions (_fex) -# define FP_ROUNDMODE __sim_round_mode -# define FP_TRAPPING_EXCEPTIONS (~__sim_disabled_exceptions & 0x3e000000) +# define FP_ROUNDMODE __sim_round_mode_thread +# define FP_TRAPPING_EXCEPTIONS \ + (~__sim_disabled_exceptions_thread & 0x3e000000) #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")); extern void __simulate_exceptions (int x) attribute_hidden; -- cgit 1.4.1