diff options
Diffstat (limited to 'sysdeps/unix/sysv/linux/powerpc/powerpc32/fe_nomask.c')
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/powerpc32/fe_nomask.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fe_nomask.c b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fe_nomask.c index e51714d312..2c85a3a9e9 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fe_nomask.c +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fe_nomask.c @@ -21,7 +21,11 @@ #include <errno.h> #include <signal.h> #include <unistd.h> +#include <sysdep.h> +#include <sys/prctl.h> +#include "kernel-features.h" +#if __ASSUME_NEW_PRCTL_SYSCALL == 0 /* This is rather fiddly under Linux. We don't have direct access, and there is no system call, but we can change the bits in a signal handler's context... */ @@ -34,18 +38,31 @@ fe_nomask_handler (int signum, struct sigcontext *sc) sc->regs->msr |= 0x900ul; /* FE0 | FE1 */ sigaction (SIGUSR1, &oact, NULL); } +#endif const fenv_t * __fe_nomask_env (void) { - struct sigaction act; +#if __ASSUME_NEW_PRCTL_SYSCALL == 0 +# if defined PR_SET_FPEXC && defined PR_FP_EXC_PRECISE + int result = INLINE_SYSCALL (prctl, 2, PR_SET_FPEXC, PR_FP_EXC_PRECISE); - act.sa_handler = (sighandler_t) fe_nomask_handler; - sigemptyset (&act.sa_mask); - act.sa_flags = 0; + if (result == -1 && errno == EINVAL) +# endif + { + struct sigaction act; - sigaction (SIGUSR1, &act, &oact); - raise (SIGUSR1); + act.sa_handler = (sighandler_t) fe_nomask_handler; + sigemptyset (&act.sa_mask); + act.sa_flags = 0; + + sigaction (SIGUSR1, &act, &oact); + raise (SIGUSR1); + } +#else + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, PR_FP_EXC_PRECISE); +#endif return FE_ENABLED_ENV; } |