aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog67
-rw-r--r--NEWS17
-rw-r--r--math/Makefile3
-rw-r--r--math/test-fenv-tls.c208
-rw-r--r--sysdeps/powerpc/nofpu/Versions5
-rw-r--r--sysdeps/powerpc/nofpu/fclrexcpt.c3
-rw-r--r--sysdeps/powerpc/nofpu/fedisblxcpt.c6
-rw-r--r--sysdeps/powerpc/nofpu/feenablxcpt.c9
-rw-r--r--sysdeps/powerpc/nofpu/fegetenv.c10
-rw-r--r--sysdeps/powerpc/nofpu/fegetexcept.c2
-rw-r--r--sysdeps/powerpc/nofpu/fegetround.c2
-rw-r--r--sysdeps/powerpc/nofpu/fesetenv.c10
-rw-r--r--sysdeps/powerpc/nofpu/fesetround.c3
-rw-r--r--sysdeps/powerpc/nofpu/feupdateenv.c7
-rw-r--r--sysdeps/powerpc/nofpu/fgetexcptflg.c2
-rw-r--r--sysdeps/powerpc/nofpu/fraiseexcpt.c5
-rw-r--r--sysdeps/powerpc/nofpu/fsetexcptflg.c4
-rw-r--r--sysdeps/powerpc/nofpu/ftestexcept.c2
-rw-r--r--sysdeps/powerpc/nofpu/get-rounding-mode.h2
-rw-r--r--sysdeps/powerpc/nofpu/sim-full.c39
-rw-r--r--sysdeps/powerpc/nofpu/soft-supp.h37
-rw-r--r--sysdeps/powerpc/soft-fp/sfp-machine.h23
22 files changed, 390 insertions, 76 deletions
diff --git a/ChangeLog b/ChangeLog
index 9568016864..0f032197aa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
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
+ <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)
{
- *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 <shlib-compat.h>
+#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;