This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix static-binary lazy FPU context allocation


Hi,

 We have an issue with FPU control word initialization in static binaries.  
We do it unconditionally, defeating any lazy FPU context allocation the OS 
may implement.

 In dynamic binaries we avoid unnecessary initialization by examining the 
`AT_FPUCW' auxiliary vector tag or if absent -- such as in the case of the 
majority of Linux ports -- assuming the value of _FPU_DEFAULT and 
refraininig from writing the FPU control word if the value we are about to 
write is the same as one the kernel will set in hardware regardless the 
first time the FPU is accessed.  In static binaries we refrain from 
checking the value of `AT_FPUCW' tag or making any assumptions though and 
write the FPU control word in all cases.

 I tried to find a reference that could justify such a difference and got 
what follows:

1. The original commit that introduced the special case:

1998-09-21  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* elf/Makefile (dl-routines, elide-routines.os, rtld-routines):
	Undo last change.
	* elf/Versions: Undo last change.  Export _dl_fpu_control and
	_dl_fpu_control_set.
	* elf/rtld.c (_dl_fpu_control, _dl_fpu_control_set): New
	variables.  Include <fpu_control.h>.
	* sysdeps/generic/dl-sysdep.c: Store AT_FPUCW value in
	_dl_fpu_control instead of __fpu_control, set _dl_fpu_control_set
	to indicate that is was seen.
	* sysdeps/unix/sysv/linux/init-first.c: Omit call to __setfpucw
	only if _dl_fpu_control was set and is equal to desired value.
	* math/Makefile (aux): Undo last change.
	* math/Versions: Export __fpu_control with version GLIBC_2.0.

-- or GIT commit c94a8080d840d47e02b63eda74d26889aa8867fa (more stuff is 
included alongside).

2. The commit that introduced the handling of the auxiliary vector in 
   static binaries:

2001-01-04  H.J. Lu  <hjl@gnu.org>

	* elf/dl-support.c (DL_FIND_AUXV): New.  Defined if not defined.
	(_dl_clktck): Declared.
	(non_dynamic_init): Take 3 arguments.
	Set _dl_pagesize, _dl_platform and _dl_clktck from AUX.

-- or GIT commit f8f900ecb9096ec47f5b7bb7626e29223c69061a (again, more 
stuff there).

 So it looks to me the special case for `AT_FPUCW' could have been removed 
at the time of the second commit quoted, but the opportunity was missed 
back then and during the following 12 years.  Well, I guess better late 
than never and therefore the change proposed makes the behaviour of static 
binaries match that of dynamic binaries now.

 No regressions in mips-linux-gnu testing, o32, n64 and n32 ABIs.  OK to 
apply?

2013-08-22  Maciej W. Rozycki  <macro@codesourcery.com>

	* csu/init-first.c (_init): Remove the !SHARED condition around
	FPU control word initialization.
	* elf/dl-support.c (_dl_fpu_control): New variable.
	(_dl_aux_init) <AT_FPUCW>: Initialize it.

  Maciej

glibc-static-fpucw.diff
Index: glibc-fsf-trunk-quilt/csu/init-first.c
===================================================================
--- glibc-fsf-trunk-quilt.orig/csu/init-first.c	2013-05-07 22:59:41.000000000 +0100
+++ glibc-fsf-trunk-quilt/csu/init-first.c	2013-08-22 19:46:48.168109470 +0100
@@ -61,11 +61,8 @@ _init (int argc, char **argv, char **env
   if (!__libc_multiple_libcs)
     {
       /* Set the FPU control word to the proper default value if the
-	 kernel would use a different value.  (In a static program we
-	 don't have this information.)  */
-#ifdef SHARED
+	 kernel would use a different value.  */
       if (__fpu_control != GLRO(dl_fpu_control))
-#endif
 	__setfpucw (__fpu_control);
     }
 
Index: glibc-fsf-trunk-quilt/elf/dl-support.c
===================================================================
--- glibc-fsf-trunk-quilt.orig/elf/dl-support.c	2013-08-20 15:18:10.000000000 +0100
+++ glibc-fsf-trunk-quilt/elf/dl-support.c	2013-08-21 20:07:55.169669153 +0100
@@ -167,6 +167,8 @@ size_t _dl_phnum;
 uint64_t _dl_hwcap __attribute__ ((nocommon));
 uint64_t _dl_hwcap2 __attribute__ ((nocommon));
 
+fpu_control_t _dl_fpu_control = _FPU_DEFAULT;
+
 /* This is not initialized to HWCAP_IMPORTANT, matching the definition
    of _dl_important_hwcaps, below, where no hwcap strings are ever
    used.  This mask is still used to mediate the lookups in the cache
@@ -253,6 +255,9 @@ _dl_aux_init (ElfW(auxv_t) *av)
       case AT_HWCAP2:
 	GLRO(dl_hwcap2) = (unsigned long int) av->a_un.a_val;
 	break;
+      case AT_FPUCW:
+	GLRO(dl_fpu_control) = av->a_un.a_val;
+	break;
 #ifdef NEED_DL_SYSINFO
       case AT_SYSINFO:
 	GL(dl_sysinfo) = av->a_un.a_val;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]