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:
parent
90232fa641
commit
76a9cb772b
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in New Issue