public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
* x86_64: floating-point environment (i.e. fenv.h). BUG.
@ 2018-08-01 10:22 Houder
  2018-08-01 11:00 ` Corinna Vinschen
  0 siblings, 1 reply; 5+ messages in thread
From: Houder @ 2018-08-01 10:22 UTC (permalink / raw)
  To: cygwin

[-- Attachment #1: Type: text/plain, Size: 1667 bytes --]

Hi Corinna,

Short version of my report (as there is more to say about the 
implementation of
"fenv") in Cygwin; this time I restrict myself to a bug in fegetenv() ).

(Note to myself: attach STC)

I am reporting a bug in fegetenv() in winsup/cygwin/fenv.cc. There is no 
hurry
in repairing this bug, as "fenv" is hardly ever (never?) used by anyone.

fegetenv() should be modified as follows:

from:
   __asm__ volatile ("fnstenv %0" : "=m" (envp->_fpu) : );
   if (use_sse)
     __asm__ volatile ("stmxcsr %0" : "=m" (envp->_sse_mxcsr) : );
   return 0

to:
// Henri: copying glibc ...
   __asm__ volatile ("fnstenv %0\n"
                     "fldenv %0" : "=m" (envp->_fpu) : );
   if (use_sse)
     __asm__ volatile ("stmxcsr %0" : "=m" (envp->_sse_mxcsr) : );
   return 0;

Yes, you can verify my modification here:

     https://sourceware.org/git/?p=glibc.git

(sysdeps/x86_64/fpu/fegetenv.c)

The fnstenv statement "copies" the state of the x87 FPU to memory, at 
the same
time MASKING all exceptions ...
However, masking the exceptions is NOT what we desire at this point. For 
this
reason fnstenv must be followed by fldenv, which copies "what has been 
copied
from the FPU" back to the FPU.

The stc is as follows:

  feenableexcept()
  ...
  fegetenv(&fpenv) // save state of fenv (the "control and status 
register")
  //fesetenv(FE_DFL_ENV) // set default environment: would mask all 
exceptions
  provoke exception
  fesetenv(&fpenv) // restore the previous state of fenv
Note: provoke exception, using
  - either feraiseexcept()
  - or double d = 1.0; long l = d + 0.4;

Using feraiseexcept() should trigger an exception; it does not.

Regards,

Henri

[-- Attachment #2: STC-FENV.c --]
[-- Type: text/x-c, Size: 6193 bytes --]

// gcc -Wall -o STC-FENV STC-FENV.c
// Linux: gcc -Wall -o STC-FENV STC-FENV.c -lm

/*
 x86_64:
 This stc does not terminate w/ an exception if one is provoked using feraiseexcept(). This is due to a bug in
 fegetenv() in winsup/cygwin/fenv.cc.
 At first glance, this is weird, as using "double d = 1.0; long l = d + 0.4;" to provoke an exception, results
 in triggering the exception.
 Floating-point in the Intel processor may either use "SSE" or the x87 FPU. On x86_64, SSE is used (mostly?).
 In feraiseexcept() the exception is provoked using the x87 FPU ...
 However, in fegetenv(), as result of the bug, all exceptions will have been masked after calling fegetenv().
 WoW (x86):
 ... an entirely different story (x87 FPU and SSE behave differently when exceptions are enabled again after
 an exception has been provoked while exceptions WERE being masked; moreover the triggering of the exception
 is "delayed" (deferred) in case of the x87 FPU).
 */
/*
Program:
 feenableexcept()
 ...
 fegetenv(&fpenv) // save state of fenv (the "control and status register")
 //fesetenv(FE_DFL_ENV)	set default environment: would mask all exceptions
 provoke exception
 fesetenv(&fpenv) // restore the previous state of fenv
Note: provoke exception, using either feraiseexcept() or double d = 1.0; long l = d + 0.4;
 */

#if !defined __CYGWIN__
#define _GNU_SOURCE
#endif
#include <fenv.h>
#include <time.h>
#include <stdio.h>

const int xxx = 0x3d;

int main()
{
    fenv_t fpenv;

    if (feenableexcept(FE_ALL_EXCEPT) == -1) printf("\tfeenableexcept failed.\n");
printf("\tExceptions ENABLED!\n");

printf(">: fegetexcept() =  %2x enabled\n", fegetexcept() );
printf("0: fegetexcept() =  %2x mask\n", (~fegetexcept() & xxx) );

printf("Getenv(&fpenv) ...\n");
    fegetenv(&fpenv);

#if 0
    printf("Setenv(FE_DFL_ENV) ...\n"); fesetenv(FE_DFL_ENV); // duck
#else
    printf("NO Setenv(FE_DFL_ENV) ...\n");
#endif
printf(">: fegetexcept() =  %2x enabled\n", fegetexcept() );
printf("1: fegetexcept() =  %2x mask\n", (~fegetexcept() & xxx) );

printf("Raise Exception!\n");
    //double d = 1.0; long l = d + 0.4; l = l;
    if (feraiseexcept(FE_INEXACT) == -1) printf("\tfeRAISErexcept() failed.\n");
printf("*: fetestexcept() = %2x status flags\n", fetestexcept(FE_ALL_EXCEPT) );
printf(">: fegetexcept() =  %2x enabled\n", fegetexcept() );
printf("2: fegetexcept() =  %2x mask\n", (~fegetexcept() & xxx) );

printf("Setenv(&fpenv) ...\n");
    fesetenv(&fpenv);
printf("*: fetestexcept() = %2x status flags\n", fetestexcept(FE_ALL_EXCEPT) );
printf(">: fegetexcept() =  %2x enabled\n", fegetexcept() );
printf("3: fegetexcept() =  %2x mask\n", (~fegetexcept() & xxx) );
}

/* Results with the "generic" fenv.cc
Cygwin: ... using feraiseexcept()
64-@@ ./stc-fenv2 <==== Wrong! NO exception! ... Ditto x86 (NO exception!): wrong!
>: fegetexcept() =  3f enabled
0: fegetexcept() =   0 mask
Getenv(&fpenv) ...
NO Setenv(FE_DFL_ENV) ...
>: fegetexcept() =   0 enabled <==== Wrong! See above
1: fegetexcept() =  3d mask
Raise Exception!
*: fetestexcept() = 20 status flags
>: fegetexcept() =   0 enabled
2: fegetexcept() =  3d mask
Setenv(&fpenv) ...
*: fetestexcept() =  0 status flags
>: fegetexcept() =  3f enabled
3: fegetexcept() =   0 mask

64-@@ ./stc-fenv2
>: fegetexcept() =  3f enabled
0: fegetexcept() =   0 mask
Getenv(&fpenv) ...
Setenv(FE_DFL_ENV) ...
>: fegetexcept() =   0 enabled
1: fegetexcept() =  3d mask
Raise Exception!
*: fetestexcept() = 20 status flags
>: fegetexcept() =   0 enabled
2: fegetexcept() =  3d mask
Setenv(&fpenv) ...
*: fetestexcept() =  0 status flags
>: fegetexcept() =  3f enabled
3: fegetexcept() =   0 mask

Linux: ... using feraiseexcept()
@@ ./stc-fenv2
>: fegetexcept() =  3d enabled
0: fegetexcept() =   0 mask
Getenv(&fpenv) ...
NO Setenv(FE_DFL_ENV) ...
>: fegetexcept() =  3d enabled <==== OK
1: fegetexcept() =   0 mask
Raise Exception!
Floating point exception (core dumped)

@@ ./stc-fenv2
>: fegetexcept() =  3d enabled
0: fegetexcept() =   0 mask
Getenv(&fpenv) ...
Setenv(FE_DFL_ENV) ...
>: fegetexcept() =   0 enabled
1: fegetexcept() =  3d mask
Raise Exception!
*: fetestexcept() = 20 status flags
>: fegetexcept() =   0 enabled
2: fegetexcept() =  3d mask
Setenv(&fpenv) ...
*: fetestexcept() =  0 status flags
>: fegetexcept() =  3d enabled
3: fegetexcept() =   0 mask

=====

Cygwin: ... using double d = 1.0; long l = d + 0.4
64-@@ ./stc-fenv2
>: fegetexcept() =  3f enabled
0: fegetexcept() =   0 mask
Getenv(&fpenv) ...
NO Setenv(FE_DFL_ENV) ...
>: fegetexcept() =   0 enabled  <==== Wrong! See above
1: fegetexcept() =  3d mask
Raise Exception!
Floating point exception (core dumped)

	@@ ./stc-fenv2
	>: fegetexcept() =  3f enabled
	0: fegetexcept() =   0 mask
	Getenv(&fpenv) ...
	NO Setenv(FE_DFL_ENV) ...
	>: fegetexcept() =   0 enabled  <==== Wrong! See above
	1: fegetexcept() =  3d mask
	Raise Exception!
	*: fetestexcept() = 20 status flags
	>: fegetexcept() =   0 enabled
	2: fegetexcept() =  3d mask
	Setenv(&fpenv) ...
	*: fetestexcept() =  0 status flags
	>: fegetexcept() =  3f enabled
	3: fegetexcept() =   0 mask

64-@@ ./stc-fenv2
>: fegetexcept() =  3f enabled
0: fegetexcept() =   0 mask
Getenv(&fpenv) ...
Setenv(FE_DFL_ENV) ...
>: fegetexcept() =   0 enabled
1: fegetexcept() =  3d mask
Raise Exception!
*: fetestexcept() = 20 status flags
>: fegetexcept() =   0 enabled
2: fegetexcept() =  3d mask
Setenv(&fpenv) ...
*: fetestexcept() =  0 status flags
>: fegetexcept() =  3f enabled
3: fegetexcept() =   0 mask

Linux: ... using double d = 1.0; long l = d + 0.4
@@ ./stc-fenv2
>: fegetexcept() =  3d enabled
0: fegetexcept() =   0 mask
Getenv(&fpenv) ...
NO Setenv(FE_DFL_ENV) ...
>: fegetexcept() =  3d enabled <==== OK
1: fegetexcept() =   0 mask
Raise Exception!
Floating point exception (core dumped)

@@ ./stc-fenv2
>: fegetexcept() =  3d enabled
0: fegetexcept() =   0 mask
Getenv(&fpenv) ...
Setenv(FE_DFL_ENV) ...
>: fegetexcept() =   0 enabled
1: fegetexcept() =  3d mask
Raise Exception!
*: fetestexcept() = 20 status flags
>: fegetexcept() =   0 enabled
2: fegetexcept() =  3d mask
Setenv(&fpenv) ...
*: fetestexcept() =  0 status flags
>: fegetexcept() =  3d enabled
3: fegetexcept() =   0 mask
 */

[-- Attachment #3: Type: text/plain, Size: 219 bytes --]


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: x86_64: floating-point environment (i.e. fenv.h). BUG.
  2018-08-01 10:22 x86_64: floating-point environment (i.e. fenv.h). BUG Houder
@ 2018-08-01 11:00 ` Corinna Vinschen
  2018-08-01 11:49   ` Houder
  0 siblings, 1 reply; 5+ messages in thread
From: Corinna Vinschen @ 2018-08-01 11:00 UTC (permalink / raw)
  To: cygwin

[-- Attachment #1: Type: text/plain, Size: 1141 bytes --]

On Aug  1 12:22, Houder wrote:
> Hi Corinna,
> 
> Short version of my report (as there is more to say about the implementation
> of
> "fenv") in Cygwin; this time I restrict myself to a bug in fegetenv() ).
> 
> (Note to myself: attach STC)
> 
> I am reporting a bug in fegetenv() in winsup/cygwin/fenv.cc. There is no
> hurry
> in repairing this bug, as "fenv" is hardly ever (never?) used by anyone.
> 
> fegetenv() should be modified as follows:
> 
> from:
>   __asm__ volatile ("fnstenv %0" : "=m" (envp->_fpu) : );
>   if (use_sse)
>     __asm__ volatile ("stmxcsr %0" : "=m" (envp->_sse_mxcsr) : );
>   return 0
> 
> to:
> // Henri: copying glibc ...
>   __asm__ volatile ("fnstenv %0\n"
>                     "fldenv %0" : "=m" (envp->_fpu) : );
>   if (use_sse)
>     __asm__ volatile ("stmxcsr %0" : "=m" (envp->_sse_mxcsr) : );
>   return 0;

Since you know how to fix things, please just send patches to
the cygwin-patches ML.


Thanks,
Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: x86_64: floating-point environment (i.e. fenv.h). BUG.
  2018-08-01 11:00 ` Corinna Vinschen
@ 2018-08-01 11:49   ` Houder
  2018-08-01 18:28     ` Achim Gratz
  2018-08-02 15:14     ` Houder
  0 siblings, 2 replies; 5+ messages in thread
From: Houder @ 2018-08-01 11:49 UTC (permalink / raw)
  To: cygwin

On 2018-08-01 13:00, Corinna Vinschen wrote:
> On Aug  1 12:22, Houder wrote:
>> Hi Corinna,
>> 
>> Short version of my report (as there is more to say about the 
>> implementation
>> of
>> "fenv") in Cygwin; this time I restrict myself to a bug in fegetenv() 
>> ).
>> 
>> (Note to myself: attach STC)
>> 
>> I am reporting a bug in fegetenv() in winsup/cygwin/fenv.cc. There is 
>> no
>> hurry
>> in repairing this bug, as "fenv" is hardly ever (never?) used by 
>> anyone.
>> 
>> fegetenv() should be modified as follows:
>> 
>> from:
>>   __asm__ volatile ("fnstenv %0" : "=m" (envp->_fpu) : );
>>   if (use_sse)
>>     __asm__ volatile ("stmxcsr %0" : "=m" (envp->_sse_mxcsr) : );
>>   return 0
>> 
>> to:
>> // Henri: copying glibc ...
>>   __asm__ volatile ("fnstenv %0\n"
>>                     "fldenv %0" : "=m" (envp->_fpu) : );
>>   if (use_sse)
>>     __asm__ volatile ("stmxcsr %0" : "=m" (envp->_sse_mxcsr) : );
>>   return 0;
> 
> Since you know how to fix things, please just send patches to
> the cygwin-patches ML.

Ah ... Agreed. However, as I am not set up for building (anymore), this
will take some time ... (not even git is installed).

(yes, I did verify the above modification (and more), however I did that
  "locally" (basically, I included winsup/cygwin/fenv.cc in my  STC) ).

Regards,

Henri

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: x86_64: floating-point environment (i.e. fenv.h). BUG.
  2018-08-01 11:49   ` Houder
@ 2018-08-01 18:28     ` Achim Gratz
  2018-08-02 15:14     ` Houder
  1 sibling, 0 replies; 5+ messages in thread
From: Achim Gratz @ 2018-08-01 18:28 UTC (permalink / raw)
  To: cygwin

Houder writes:
>> Since you know how to fix things, please just send patches to
>> the cygwin-patches ML.
>
> Ah ... Agreed. However, as I am not set up for building (anymore), this
> will take some time ... (not even git is installed).

Just make a unified diff of your changes…


Regards,
Achim.
-- 
+<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+

Waldorf MIDI Implementation & additional documentation:
http://Synth.Stromeko.net/Downloads.html#WaldorfDocs

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: x86_64: floating-point environment (i.e. fenv.h). BUG.
  2018-08-01 11:49   ` Houder
  2018-08-01 18:28     ` Achim Gratz
@ 2018-08-02 15:14     ` Houder
  1 sibling, 0 replies; 5+ messages in thread
From: Houder @ 2018-08-02 15:14 UTC (permalink / raw)
  To: cygwin

On 2018-08-01 13:49, Houder wrote:
> On 2018-08-01 13:00, Corinna Vinschen wrote:
>> On Aug  1 12:22, Houder wrote:
>>> Hi Corinna,
>>> 
>>> Short version of my report (as there is more to say about the 
>>> implementation
>>> of
>>> "fenv") in Cygwin; this time I restrict myself to a bug in fegetenv() 
>>> ).
>>> 
>>> (Note to myself: attach STC)
>>> 
>>> I am reporting a bug in fegetenv() in winsup/cygwin/fenv.cc. There is 
>>> no
>>> hurry
>>> in repairing this bug, as "fenv" is hardly ever (never?) used by 
>>> anyone.
>>> 
>>> fegetenv() should be modified as follows:
>>> 
>>> from:
>>>   __asm__ volatile ("fnstenv %0" : "=m" (envp->_fpu) : );
>>>   if (use_sse)
>>>     __asm__ volatile ("stmxcsr %0" : "=m" (envp->_sse_mxcsr) : );
>>>   return 0
>>> 
>>> to:
>>> // Henri: copying glibc ...
>>>   __asm__ volatile ("fnstenv %0\n"
>>>                     "fldenv %0" : "=m" (envp->_fpu) : );
>>>   if (use_sse)
>>>     __asm__ volatile ("stmxcsr %0" : "=m" (envp->_sse_mxcsr) : );
>>>   return 0;
>> 
>> Since you know how to fix things, please just send patches to
>> the cygwin-patches ML.
> 
> Ah ... Agreed. However, as I am not set up for building (anymore), this
> will take some time ... (not even git is installed).
> 
> (yes, I did verify the above modification (and more), however I did 
> that
>  "locally" (basically, I included winsup/cygwin/fenv.cc in my  STC) ).

Corinna,

As requested by you, I made an attempt. See cygwin-patches.

Regards,

Henri

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-08-02 15:14 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-01 10:22 x86_64: floating-point environment (i.e. fenv.h). BUG Houder
2018-08-01 11:00 ` Corinna Vinschen
2018-08-01 11:49   ` Houder
2018-08-01 18:28     ` Achim Gratz
2018-08-02 15:14     ` Houder

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).