This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
[PATCH] fegetenv/getcontext
- From: "Ed Connell" <Ed dot Connell at sas dot com>
- To: <libc-alpha at sources dot redhat dot com>
- Date: Fri, 20 Jun 2003 11:39:15 -0400
- Subject: [PATCH] fegetenv/getcontext
Hi
fegetenv and getcontext currently corrupt the floating point
mask on x86. I have included a patch and a testcase. I
was only able to test this patch on 2.2.93 but looking at
CVS, I see no reason the behavior should be different now.
Someone involved with x86-64 should see if they need a
similar patch. The problem can be seen on RH 8 and RH 9.
Cheers
Ed
2003-05-19 Ed Connell <ed.connell@sas.com>
* sysdeps/unix/sysv/linux/i386/getcontext.S (getcontext):
Retain floating point mask
* sysdeps/i386/fpu/fegetenv.c (fegetenv): Likewise.
--- glibc-2.3.2/sysdeps/i386/fpu/fegetenv.c 2001-07-07 15:21:23.000000000 -0400
+++ glibc-2.3.2/sysdeps/i386/fpu/fegetenv.c.edconn 2003-05-19 16:27:16.000000000 -0400
@@ -25,6 +25,7 @@
__fegetenv (fenv_t *envp)
{
__asm__ ("fnstenv %0" : "=m" (*envp));
+ __asm__ ("fldenv %0" : "=m" (*envp));
/* Success. */
return 0;
--- glibc-2.3.2/sysdeps/unix/sysv/linux/i386/getcontext.S 2002-12-19 22:56:27.000000000 -0500
+++ glibc-2.3.2/sysdeps/unix/sysv/linux/i386/getcontext.S.edconn 2003-05-19 15:12:12.000000000 -0400
@@ -56,6 +56,7 @@
movl %ecx, oFPREGS(%eax)
/* Save the floating-point context. */
fnstenv (%ecx)
+ fldenv (%ecx)
/* Save the current signal mask. */
pushl %ebx
Testcase
gcc -o setjmp_fpmask_test setjmp_fpmask_test.c -lm
gcc -o setjmp_fpmask_test setjmp_fpmask_test.c -lm -DDO_GETCONTEXT
gcc -o setjmp_fpmask_test setjmp_fpmask_test.c -lm -DDO_FEGETENV
Pass: "Correct: got floating point exception."
Fail: "Error: missed floating point exception."
setjmp_fpmask_test.c
********************
#define _GNU_SOURCE
#include <setjmp.h>
#include <fenv.h>
#include <signal.h>
#include <stddef.h>
#include <ucontext.h>
void fpe_hand(int signum, siginfo_t *p1, void *p2)
{
printf("Correct: got floating point exception.\n");
exit(1);
}
int main()
{
struct sigaction act;
double d = 0.0;
ucontext_t uc;
fenv_t fenv;
act.sa_sigaction = fpe_hand;
act.sa_flags = SA_SIGINFO;
memset(&act.sa_mask,0,sizeof(act.sa_mask));
sigaction(SIGFPE, &act, NULL);
feenableexcept(FE_ALL_EXCEPT);
#if defined(DO_GETCONTEXT)
getcontext(&uc);
#elif defined(DO_FEGETENV)
fegetenv(&fenv);
#endif
d = 1.0 / d;
printf("Error: missed floating point exception.\n");
}