This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH v2] Fix static-binary lazy FPU context allocation
- From: "Maciej W. Rozycki" <macro at codesourcery dot com>
- To: Carlos O'Donell <carlos at redhat dot com>
- Cc: <libc-alpha at sourceware dot org>
- Date: Thu, 5 Sep 2013 17:10:25 +0100
- Subject: [PATCH v2] Fix static-binary lazy FPU context allocation
- Authentication-results: sourceware.org; auth=none
- References: <alpine dot DEB dot 1 dot 10 dot 1308221904520 dot 8514 at tp dot orcam dot me dot uk> <52260408 dot 2030809 at redhat dot com>
On Tue, 3 Sep 2013, Carlos O'Donell wrote:
> > No regressions in mips-linux-gnu testing, o32, n64 and n32 ABIs. OK to
> > apply?
>
> What existing test case checks for this?
We've got math/test-fpucw that gives partial coverage; this won't check
static semantics though unless $(build-shared) is (unusually) set to `no'.
> Could you please add a static test that verifies this is set correctly?
The update below adds static coverage in all cases and extends dynamic
coverage to non-default __fpu_control initialisation; the only portable
way of doing that is I believe with the use of the _FPU_IEEE macro, so
I've chosen that (it is worth noting however that the use of anything but
_FPU_DEFAULT breaks ISO C compliance).
Note that the test cases rely on the presence of the _FPU_GETCW macro so
some ports are not covered (Alpha). Also the only Linux port that
currently actually produces the AT_FPUCW tag is Renesas SuperH.
> > 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));
> >
>
> This needs a detailed comment here explaining the behaviour of this
> internal variable. I would also welcome an expounding of the semantics
> of __fpu_control and the behaviour for static and dynamic applications.
I've added a note on _dl_fpu_control now; NB most of these variables are
undocumented here.
I'm not sure what you'd like to see on `__fpu_control' and where (an
expansion of the note in math/fpu_control.c perhaps?), I'll appreciate
guidance. The semantics of this variable is supposed to be the same
whether a static or a dynamic app.
> In summary:
> - Test case.
> - Comment for _dl_fpu_control.
Thanks for your review, here's an updated patch. No failures with the
test-fpucw* cases on MIPS/Linux; regrettably I have no way to test
SuperH/Linux. OK for this version (barring any `__fpu_control' doc
update)?
BTW, I have realised I am supposed to add myself to wiki/MAINTAINERS --
can you please grant me a write privilege to do so (ID: macro)?
2013-09-05 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.
* math/test-fpucw.c [!FPU_CONTROL] (FPU_CONTROL): New macro.
(main): Replace _FPU_DEFAULT with FPU_CONTROL throughout.
* math/test-fpucw-static.c: New file.
* math/test-fpucw-ieee.c: New file.
* math/test-fpucw-ieee-static.c: New file.
* math/Makefile (tests): Add `test-fpucw-ieee' and
`$(tests-static)'.
(tests-static): New variable.
[($(build-shared),yes)] ($(addprefix $(objpfx),$(tests))): Move
dependency to...
[($(build-shared),yes)]
($(addprefix $(objpfx),$(filter-out $(tests-static),$(tests)))):
... this.
[($(build-shared),yes)] ($(addprefix $(objpfx),$(tests-static))):
New dependency.
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-09-05 17:06:45.407939629 +0100
@@ -167,6 +167,9 @@ size_t _dl_phnum;
uint64_t _dl_hwcap __attribute__ ((nocommon));
uint64_t _dl_hwcap2 __attribute__ ((nocommon));
+/* The value of the FPU control word the kernel will preset in hardware. */
+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 +256,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: glibc-fsf-trunk-quilt/math/Makefile
===================================================================
--- glibc-fsf-trunk-quilt.orig/math/Makefile 2013-06-14 01:57:07.000000000 +0100
+++ glibc-fsf-trunk-quilt/math/Makefile 2013-09-04 22:35:10.468404476 +0100
@@ -87,9 +87,11 @@ long-c-yes = $(calls:=l)
# Rules for the test suite.
tests = test-matherr test-fenv atest-exp atest-sincos atest-exp2 basic-test \
- test-misc test-fpucw tst-definitions test-tgmath test-tgmath-ret \
- bug-nextafter bug-nexttoward bug-tgmath1 test-tgmath-int \
- test-tgmath2 test-powl tst-CMPLX tst-CMPLX2 test-snan
+ test-misc test-fpucw test-fpucw-ieee tst-definitions test-tgmath \
+ test-tgmath-ret bug-nextafter bug-nexttoward bug-tgmath1 \
+ test-tgmath-int test-tgmath2 test-powl tst-CMPLX tst-CMPLX2 test-snan \
+ $(tests-static)
+tests-static = test-fpucw-static test-fpucw-ieee-static
# We do the `long double' tests only if this data type is available and
# distinct from `double'.
test-longdouble-yes = test-ldouble test-ildoubl
@@ -217,7 +219,8 @@ $(objpfx)libieee.a: $(objpfx)ieee-math.o
$(LN_S) $(<F) $(@F)
ifeq ($(build-shared),yes)
-$(addprefix $(objpfx),$(tests)): $(objpfx)libm.so$(libm.so-version)
+$(addprefix $(objpfx),$(filter-out $(tests-static),$(tests))): $(objpfx)libm.so$(libm.so-version)
+$(addprefix $(objpfx),$(tests-static)): $(objpfx)libm.a
else
$(addprefix $(objpfx),$(tests)): $(objpfx)libm.a
endif
Index: glibc-fsf-trunk-quilt/math/test-fpucw-ieee-static.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc-fsf-trunk-quilt/math/test-fpucw-ieee-static.c 2013-09-04 18:47:08.638421823 +0100
@@ -0,0 +1 @@
+#include "test-fpucw-ieee.c"
Index: glibc-fsf-trunk-quilt/math/test-fpucw-ieee.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc-fsf-trunk-quilt/math/test-fpucw-ieee.c 2013-09-04 18:46:37.148423857 +0100
@@ -0,0 +1,24 @@
+/* FPU control word overridden initialization test.
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define FPU_CONTROL _FPU_IEEE
+
+#include "test-fpucw.c"
+
+/* Preempt the library's definition of `__fpu_control'. */
+fpu_control_t __fpu_control = _FPU_IEEE;
Index: glibc-fsf-trunk-quilt/math/test-fpucw-static.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc-fsf-trunk-quilt/math/test-fpucw-static.c 2013-09-04 18:43:54.677640608 +0100
@@ -0,0 +1 @@
+#include "test-fpucw.c"
Index: glibc-fsf-trunk-quilt/math/test-fpucw.c
===================================================================
--- glibc-fsf-trunk-quilt.orig/math/test-fpucw.c 2013-01-16 00:04:04.000000000 +0000
+++ glibc-fsf-trunk-quilt/math/test-fpucw.c 2013-09-04 18:45:29.657640413 +0100
@@ -19,6 +19,10 @@
#include <fpu_control.h>
#include <stdio.h>
+#ifndef FPU_CONTROL
+# define FPU_CONTROL _FPU_DEFAULT
+#endif
+
int
main (void)
{
@@ -30,11 +34,11 @@ main (void)
cw &= ~_FPU_RESERVED;
- if (cw != (_FPU_DEFAULT & ~_FPU_RESERVED))
+ if (cw != (FPU_CONTROL & ~_FPU_RESERVED))
printf ("control word is 0x%lx but should be 0x%lx.\n",
- (long int) cw, (long int) (_FPU_DEFAULT & ~_FPU_RESERVED));
+ (long int) cw, (long int) (FPU_CONTROL & ~_FPU_RESERVED));
- return cw != (_FPU_DEFAULT & ~_FPU_RESERVED);
+ return cw != (FPU_CONTROL & ~_FPU_RESERVED);
#else
return 0;