Upload Tizen:Base source
[external/eglibc.git] / sysdeps / unix / sysv / linux / powerpc / powerpc32 / fpu / fe_nomask.c
1 /* Procedure definition for FE_NOMASK_ENV for Linux/ppc.
2    Copyright (C) 2000, 2006, 2008 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <fenv_libc.h>
21 #include <errno.h>
22 #include <signal.h>
23 #include <unistd.h>
24 #include <sysdep.h>
25 #include <sys/prctl.h>
26 #include <kernel-features.h>
27
28 #if __ASSUME_NEW_PRCTL_SYSCALL == 0
29 /* This is rather fiddly under Linux.  We don't have direct access,
30    and there is no system call, but we can change the bits
31    in a signal handler's context...  */
32
33 static struct sigaction oact;
34
35 static void
36 fe_nomask_handler (int signum, struct sigcontext *sc)
37 {
38   sc->regs->msr |= 0x900ul;  /* FE0 | FE1 */
39   sigaction (SIGUSR1, &oact, NULL);
40 }
41 #endif
42
43 const fenv_t *
44 __fe_nomask_env (void)
45 {
46 #if __ASSUME_NEW_PRCTL_SYSCALL == 0
47 # if defined PR_SET_FPEXC && defined PR_FP_EXC_PRECISE
48   int result = INLINE_SYSCALL (prctl, 2, PR_SET_FPEXC, PR_FP_EXC_PRECISE);
49
50   if (result == -1 && errno == EINVAL)
51 # endif
52     {
53       struct sigaction act;
54
55       act.sa_handler = (sighandler_t) fe_nomask_handler;
56       sigemptyset (&act.sa_mask);
57       act.sa_flags = 0;
58
59       sigaction (SIGUSR1, &act, &oact);
60       raise (SIGUSR1);
61     }
62 #else
63   INTERNAL_SYSCALL_DECL (err);
64   INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, PR_FP_EXC_PRECISE);
65 #endif
66
67   return FE_ENABLED_ENV;
68 }
69 libm_hidden_def (__fe_nomask_env)