about summary refs log tree commit diff
path: root/math
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2023-10-24 08:37:16 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2023-12-19 15:12:38 -0300
commit787282dede7f134fdb22155cee0c35172e3e28f3 (patch)
treeef7d2a333bd0cf9118f1afd3183186db07ed0513 /math
parent47a9eeb9ba72fd30766bdf4faa7d46b8ca33a7fd (diff)
downloadglibc-787282dede7f134fdb22155cee0c35172e3e28f3.tar.gz
glibc-787282dede7f134fdb22155cee0c35172e3e28f3.tar.xz
glibc-787282dede7f134fdb22155cee0c35172e3e28f3.zip
x86: Do not raises floating-point exception traps on fesetexceptflag (BZ 30990)
According to ISO C23 (7.6.4.4), fesetexcept is supposed to set
floating-point exception flags without raising a trap (unlike
feraiseexcept, which is supposed to raise a trap if feenableexcept
was called with the appropriate argument).

The flags can be set in the 387 unit or in the SSE unit.  When we need
to clear a flag, we need to do so in both units, due to the way
fetestexcept is implemented.

When we need to set a flag, it is sufficient to do it in the SSE unit,
because that is guaranteed to not trap.  However, on i386 CPUs that have
only a 387 unit, set the flags in the 387, as long as this cannot trap.

Co-authored-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Diffstat (limited to 'math')
-rw-r--r--math/test-fexcept-traps.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/math/test-fexcept-traps.c b/math/test-fexcept-traps.c
index 998c241058..ac63fbca2f 100644
--- a/math/test-fexcept-traps.c
+++ b/math/test-fexcept-traps.c
@@ -19,6 +19,7 @@
 #include <fenv.h>
 #include <stdio.h>
 #include <math-tests.h>
+#include <math-barriers.h>
 
 static int
 do_test (void)
@@ -65,12 +66,32 @@ do_test (void)
 
   /* The test is that this does not cause exception traps.  For architectures
      where setting the exception might result in traps the function should
-     return a nonzero value.  */
+     return a nonzero value.
+     Also check if the function does not alter the exception mask.  */
   ret = fesetexceptflag (&saved, FE_ALL_EXCEPT);
 
   _Static_assert (!(EXCEPTION_SET_FORCES_TRAP && !EXCEPTION_TESTS(float)),
 		  "EXCEPTION_SET_FORCES_TRAP only makes sense if the "
 		  "architecture suports exceptions");
+  {
+    int exc_before = fegetexcept ();
+    ret = fesetexceptflag (&saved, FE_ALL_EXCEPT);
+    int exc_after = fegetexcept ();
+    if (exc_before != exc_after)
+      {
+	puts ("fesetexceptflag (FE_ALL_EXCEPT) changed the exceptions mask");
+	return 1;
+      }
+  }
+
+  /* Execute some floating-point operations, since on some CPUs exceptions
+     triggers a trap only at the next floating-point instruction.  */
+  volatile double a = 1.0;
+  volatile double b = a + a;
+  math_force_eval (b);
+  volatile long double al = 1.0L;
+  volatile long double bl = al + al;
+  math_force_eval (bl);
 
   if (ret != 0 && !EXCEPTION_SET_FORCES_TRAP)
     {