This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] Fix static-binary lazy FPU context allocation
- From: "Maciej W. Rozycki" <macro at codesourcery dot com>
- To: <libc-alpha at sourceware dot org>
- Date: Thu, 22 Aug 2013 20:12:55 +0100
- Subject: [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;