diff options
| author | Joseph Myers <joseph@codesourcery.com> | 2013-11-19 13:39:56 +0000 |
|---|---|---|
| committer | Joseph Myers <joseph@codesourcery.com> | 2013-11-19 13:39:56 +0000 |
| commit | 73c1ce4fdbdf117b4d91b6e894686228155bd702 (patch) | |
| tree | a996f6b56852c7fc2a39dec8d5a41456365990cf | |
| parent | b5449b12962da665c29f0a1c85f705de4bc4abf2 (diff) | |
| download | glibc-73c1ce4fdbdf117b4d91b6e894686228155bd702.tar.xz glibc-73c1ce4fdbdf117b4d91b6e894686228155bd702.zip | |
Make powerpc-nofpu floating-point state thread-local (bug 15483).
| -rw-r--r-- | ChangeLog | 67 | ||||
| -rw-r--r-- | NEWS | 17 | ||||
| -rw-r--r-- | math/Makefile | 3 | ||||
| -rw-r--r-- | math/test-fenv-tls.c | 208 | ||||
| -rw-r--r-- | sysdeps/powerpc/nofpu/Versions | 5 | ||||
| -rw-r--r-- | sysdeps/powerpc/nofpu/fclrexcpt.c | 3 | ||||
| -rw-r--r-- | sysdeps/powerpc/nofpu/fedisblxcpt.c | 6 | ||||
| -rw-r--r-- | sysdeps/powerpc/nofpu/feenablxcpt.c | 9 | ||||
| -rw-r--r-- | sysdeps/powerpc/nofpu/fegetenv.c | 10 | ||||
| -rw-r--r-- | sysdeps/powerpc/nofpu/fegetexcept.c | 2 | ||||
| -rw-r--r-- | sysdeps/powerpc/nofpu/fegetround.c | 2 | ||||
| -rw-r--r-- | sysdeps/powerpc/nofpu/fesetenv.c | 10 | ||||
| -rw-r--r-- | sysdeps/powerpc/nofpu/fesetround.c | 3 | ||||
| -rw-r--r-- | sysdeps/powerpc/nofpu/feupdateenv.c | 7 | ||||
| -rw-r--r-- | sysdeps/powerpc/nofpu/fgetexcptflg.c | 2 | ||||
| -rw-r--r-- | sysdeps/powerpc/nofpu/fraiseexcpt.c | 5 | ||||
| -rw-r--r-- | sysdeps/powerpc/nofpu/fsetexcptflg.c | 4 | ||||
| -rw-r--r-- | sysdeps/powerpc/nofpu/ftestexcept.c | 2 | ||||
| -rw-r--r-- | sysdeps/powerpc/nofpu/get-rounding-mode.h | 2 | ||||
| -rw-r--r-- | sysdeps/powerpc/nofpu/sim-full.c | 39 | ||||
| -rw-r--r-- | sysdeps/powerpc/nofpu/soft-supp.h | 37 | ||||
| -rw-r--r-- | sysdeps/powerpc/soft-fp/sfp-machine.h | 23 |
22 files changed, 390 insertions, 76 deletions
@@ -1,3 +1,70 @@ +2013-11-19 Joseph Myers <joseph@codesourcery.com> + + [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 <shlib-compat.h>. + (__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 <schwab@suse.de> * locale/programs/locale.c (show_info): Decode wordarray elements. @@ -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 + <http://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <pthread.h> +#include <stdio.h> +#include <stdint.h> + +#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 <http://www.gnu.org/licenses/>. */ +#include "soft-supp.h" #include <fenv.h> -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) { |
