From 76a9cb772b6d8e98dc2fc8ef1ea197e0851e1037 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Thu, 28 Feb 2019 15:13:19 +0100 Subject: [PATCH] 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 --- winsup/cygwin/dcrt0.cc | 2 +- winsup/cygwin/fenv.cc | 22 +++++++++++++--------- winsup/cygwin/include/fenv.h | 2 +- winsup/cygwin/miscfuncs.cc | 3 +++ winsup/cygwin/timerfd.cc | 13 ++++--------- 5 files changed, 22 insertions(+), 20 deletions(-) diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 11edcdf0d..bc7eeb42b 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -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); } diff --git a/winsup/cygwin/fenv.cc b/winsup/cygwin/fenv.cc index 396f98af4..a2c835915 100644 --- a/winsup/cygwin/fenv.cc +++ b/winsup/cygwin/fenv.cc @@ -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); } - diff --git a/winsup/cygwin/include/fenv.h b/winsup/cygwin/include/fenv.h index a355c4775..3c9b5382a 100644 --- a/winsup/cygwin/include/fenv.h +++ b/winsup/cygwin/include/fenv.h @@ -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 diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc index b5dfffc7d..ed32a505e 100644 --- a/winsup/cygwin/miscfuncs.cc +++ b/winsup/cygwin/miscfuncs.cc @@ -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); diff --git a/winsup/cygwin/timerfd.cc b/winsup/cygwin/timerfd.cc index 8e4c94e66..c4faf305b 100644 --- a/winsup/cygwin/timerfd.cc +++ b/winsup/cygwin/timerfd.cc @@ -15,6 +15,7 @@ details. */ #include "cygerrno.h" #include #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");