summaryrefslogtreecommitdiff
path: root/sysdeps/powerpc/nofpu
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2013-11-19 13:39:56 +0000
committerJoseph Myers <joseph@codesourcery.com>2013-11-19 13:39:56 +0000
commit73c1ce4fdbdf117b4d91b6e894686228155bd702 (patch)
treea996f6b56852c7fc2a39dec8d5a41456365990cf /sysdeps/powerpc/nofpu
parentb5449b12962da665c29f0a1c85f705de4bc4abf2 (diff)
Make powerpc-nofpu floating-point state thread-local (bug 15483).
Diffstat (limited to 'sysdeps/powerpc/nofpu')
-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
17 files changed, 94 insertions, 54 deletions
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;