Cygwin: initialize FP environment for each applicaiton thread

Also, initialize FP environment in timerfd thread before calling
RegisterClassW to avoid a spurious STATUS_FLOAT_INEXACT_RESULT
from msvcrt.dll.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2019-02-28 15:13:19 +01:00
parent 90232fa641
commit 76a9cb772b
5 changed files with 22 additions and 20 deletions

View File

@ -1079,7 +1079,7 @@ _dll_crt0 ()
fork_info->alloc_stack ();
#endif
_feinitialise ();
_feinitialise (true);
_main_tls = &_my_tls;
_main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
}

View File

@ -420,7 +420,7 @@ fesetprec (int prec)
/* Set up the FPU and SSE environment at the start of execution. */
void
_feinitialise (void)
_feinitialise (bool pre_main)
{
unsigned int edx, eax;
@ -442,14 +442,18 @@ _feinitialise (void)
if (use_sse)
__asm__ volatile ("ldmxcsr %0" :: "m" (mxcsr));
/* Setup unmasked environment, but leave __FE_DENORM masked. */
feenableexcept (FE_ALL_EXCEPT);
fegetenv (&fe_nomask_env);
if (pre_main)
{
/* Setup unmasked environment, but leave __FE_DENORM masked. */
feenableexcept (FE_ALL_EXCEPT);
fegetenv (&fe_nomask_env);
/* Restore default exception masking (all masked). */
fedisableexcept (FE_ALL_EXCEPT);
/* Restore default exception masking (all masked). */
fedisableexcept (FE_ALL_EXCEPT);
/* Finally cache state as default environment. */
fegetenv (&fe_dfl_env);
/* Finally cache state as default environment. */
fegetenv (&fe_dfl_env);
}
else
fedisableexcept (FE_ALL_EXCEPT);
}

View File

@ -168,7 +168,7 @@ extern int fesetprec (int __prec);
#ifdef __INSIDE_CYGWIN__
/* This is Cygwin-custom, not from the standard, for use in the Cygwin CRT. */
extern void _feinitialise ();
extern void _feinitialise (bool);
#endif
#ifdef __cplusplus

View File

@ -16,6 +16,7 @@ details. */
#include "fhandler.h"
#include "exception.h"
#include "tls_pbuf.h"
#include "fenv.h"
int __reg2
check_invalid_virtual_addr (const void *s, unsigned sz)
@ -397,6 +398,8 @@ pthread_wrapper (PVOID arg)
wrapper_arg.guardsize -= wincap.page_size ();
SetThreadStackGuarantee (&wrapper_arg.guardsize);
}
/* FP initialization. */
_feinitialise (false);
/* Initialize new _cygtls. */
_my_tls.init_thread (wrapper_arg.stackbase - CYGTLS_PADSIZE,
(DWORD (*)(void*, void*)) wrapper_arg.func);

View File

@ -15,6 +15,7 @@ details. */
#include "cygerrno.h"
#include <sys/timerfd.h>
#include "timerfd.h"
#include "fenv.h"
#define TFD_CANCEL_FLAGS (TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET)
@ -32,15 +33,9 @@ timerfd_tracker::create_timechange_window ()
wclass.lpfnWndProc = DefWindowProcW;
wclass.hInstance = user_data->hmodule;
wclass.lpszClassName = cname;
/* This sleep is required on Windows 10 64 bit only, and only when running
under strace. One of the child processes inheriting the timerfd
descriptor will get a STATUS_FLOAT_INEXACT_RESULT exception inside of
msvcrt.dll. While this is completely crazy in itself, it's apparently
some timing problem. It occurs in 4 out of 5 runs under strace only.
The sleep is required before calling RegisterClassW. Moving it before
CreateWindowExW does not work. What the heck? */
if (being_debugged ())
Sleep (1L);
/* Avoid a potential STATUS_FLOAT_INEXACT_RESULT in msvcrt.dll.
Only observed on x86_64 W10 under strace. */
_feinitialise (false);
atom = RegisterClassW (&wclass);
if (!atom)
debug_printf ("RegisterClass %E");