bug-glibc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] fegetenv/getcontext


From: Ed Connell
Subject: [PATCH] fegetenv/getcontext
Date: Mon, 19 May 2003 17:00:48 -0400

Hello,

I previously reported the x86 instruction 'fnstenv' (used in
getcontext()) was resetting floating point mask info improperly.  
http://sources.redhat.com/ml/bug-glibc/2002-12/msg00047.html

I now have a patch and a testcase.  I was only able to test this
on 2.2.93 but I see no reason the behavior should be different.
Someone involved with x86-64 should see if they need a similar
patch.

Cheers
Ed

2003-05-19  Ed Connell  <address@hidden>

        * 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");
}
********************




reply via email to

[Prev in Thread] Current Thread [Next in Thread]