This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: Add powerpc-nofpu/e500 support functions for atomic compound assignment and FLT_ROUNDS
- From: Adhemerval Zanella <azanella at linux dot vnet dot ibm dot com>
- To: libc-alpha at sourceware dot org
- Date: Thu, 28 Nov 2013 15:28:32 -0200
- Subject: Re: Add powerpc-nofpu/e500 support functions for atomic compound assignment and FLT_ROUNDS
- Authentication-results: sourceware.org; auth=none
- References: <Pine dot LNX dot 4 dot 64 dot 1311201804530 dot 28804 at digraph dot polyomino dot org dot uk>
Hi Joseph, this patch is ok, thanks!
On 20-11-2013 16:06, Joseph S. Myers wrote:
> C11 atomic compound assignment for _Atomic floating-point types, for
> which support was recently added to GCC, requires a
> compare-and-exchange loop (given the lack of actual hardware support
> for atomic floating-point memory operations), which must clear any
> exceptions resulting from an attempted operation where the
> compare-and-exchange failed because the stored value had changed
> between when it was read and when the result was ready to store back.
>
> The effect of this is that code is needed with the effect of calls to
> feholdexcept, feclearexcept (FE_ALL_EXCEPT) and feupdateenv (see the
> footnote in C11 6.5.16.2). However, GCC can't actually generate calls
> to those functions as that would introduce a dependency on libm and
> established practice is that C code does not require libm unless it
> uses interfaces from <math.h>, <complex.h> and <fenv.h> (both normal
> practice about when users expect to need -lm, and something POSIX says
> about the c99 utility that I have no reason to expect to change when a
> future POSIX edition introduces a compilation utility for C11).
>
> Thus GCC needs to generate code inline without libm dependencies. I
> implemented that for x86, leaving other architectures to the GCC
> architecture maintainers (hopefully maintainers for the main
> architectures will define the required hook in time for the 4.9
> release).
>
> There are some cases where there are problems with inline code simply
> manipulating the FPU state. One is for powerpc-nofpu, where exception
> state for software floating point is in thread-local variables in
> libc. Another is for e500, where prctl syscalls are needed as well as
> modifying the SPEFSCR register.
>
> To address both those cases, it seems natural for libc to provide
> __atomic_fe* functions intended for the compiler to generate calls
> to. This patch adds them for powerpc-nofpu, including the e500 case.
> There's no way to handle errors here, so the functions return void,
> and abort if the prctl syscalls fail (which should never happen).
>
> The same issue applies for the FLT_ROUNDS macro in <float.h>, so this
> patch also adds a function __flt_rounds to handle that. (There, the
> e500 code *can* readily be generated inline by the compiler, but as
> the e500 port uses the same ABI as soft-float it of course needs to
> provide a working version of __flt_rounds anyway.)
>
> In both cases, if the architecture maintainers in GCC add support for
> classic hard float I intend to extend it to call these functions for
> soft-float / e500 GNU/Linux (only when configured with a sufficiently
> recent glibc version in the FLT_ROUNDS case - whereas for the atomics
> I think it's reasonable for GCC to require a recent-enough glibc if
> you use atomic compound assignment with floating point on this
> platform).
>
> Tested with the glibc testsuite for powerpc-nofpu, and some spot tests
> done for e500.
>
> 2013-11-20 Joseph Myers <joseph@codesourcery.com>
>
> * sysdeps/powerpc/nofpu/atomic-feclearexcept.c: New file.
> * sysdeps/powerpc/nofpu/atomic-feholdexcept.c: Likewise.
> * sysdeps/powerpc/nofpu/atomic-feupdateenv.c: Likewise.
> * sysdeps/powerpc/nofpu/flt-rounds.c: Likewise.
> * sysdeps/powerpc/powerpc32/e500/nofpu/atomic-feclearexcept.c:
> Likewise.
> * sysdeps/powerpc/powerpc32/e500/nofpu/atomic-feholdexcept.c:
> Likewise.
> * sysdeps/powerpc/powerpc32/e500/nofpu/atomic-feupdateenv.c:
> Likewise.
> * sysdeps/powerpc/powerpc32/e500/nofpu/flt-rounds.c: Likewise.
> * sysdeps/powerpc/nofpu/Makefile [$(subdir) = soft-fp]
> (sysdep_routines): Add atomic-feholdexcept, atomic-feclearexcept,
> atomic-feupdateenv and flt-rounds.
> * sysdeps/powerpc/nofpu/Versions (libc): Add
> __atomic_feholdexcept, __atomic_feclearexcept,
> __atomic_feupdateenv and __flt_rounds to GLIBC_2.19.
> * sysdeps/powerpc/powerpc32/e500/nofpu/fenv_libc.h
> (__feraiseexcept_soft): Declare and use libc_hidden_proto here.
> * sysdeps/powerpc/powerpc32/e500/nofpu/fraiseexcept-soft.c
> (__feraiseexcept_soft): Don't declare and use libc_hidden_proto
> here.
> * sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/nptl/libc.abilist:
> Update.
>
> diff --git a/sysdeps/powerpc/nofpu/Makefile b/sysdeps/powerpc/nofpu/Makefile
> index b9cbf80..9de7c43 100644
> --- a/sysdeps/powerpc/nofpu/Makefile
> +++ b/sysdeps/powerpc/nofpu/Makefile
> @@ -2,7 +2,8 @@
>
> ifeq ($(subdir),soft-fp)
> sysdep_routines += $(gcc-single-routines) $(gcc-double-routines) \
> - sim-full
> + sim-full atomic-feholdexcept atomic-feclearexcept \
> + atomic-feupdateenv flt-rounds
> endif
>
> ifeq ($(subdir),math)
> diff --git a/sysdeps/powerpc/nofpu/Versions b/sysdeps/powerpc/nofpu/Versions
> index 8ba6021..571b1d2 100644
> --- a/sysdeps/powerpc/nofpu/Versions
> +++ b/sysdeps/powerpc/nofpu/Versions
> @@ -17,6 +17,10 @@ libc {
> __gtdf2; __gtsf2;
> __ltdf2; __ltsf2;
> }
> + GLIBC_2.19 {
> + __atomic_feholdexcept; __atomic_feclearexcept; __atomic_feupdateenv;
> + __flt_rounds;
> + }
> GLIBC_PRIVATE {
> __sim_exceptions_thread;
> __sim_disabled_exceptions_thread;
> diff --git a/sysdeps/powerpc/nofpu/atomic-feclearexcept.c b/sysdeps/powerpc/nofpu/atomic-feclearexcept.c
> new file mode 100644
> index 0000000..c2b2ee9
> --- /dev/null
> +++ b/sysdeps/powerpc/nofpu/atomic-feclearexcept.c
> @@ -0,0 +1,28 @@
> +/* Clear floating-point exceptions for atomic compound assignment.
> + 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/>. */
> +
> +#include "soft-fp.h"
> +#include "soft-supp.h"
> +
> +void
> +__atomic_feclearexcept (void)
> +{
> + /* This function postdates the global variables being turned into
> + compat symbols, so no need to set them. */
> + __sim_exceptions_thread = 0;
> +}
> diff --git a/sysdeps/powerpc/nofpu/atomic-feholdexcept.c b/sysdeps/powerpc/nofpu/atomic-feholdexcept.c
> new file mode 100644
> index 0000000..07b11d0
> --- /dev/null
> +++ b/sysdeps/powerpc/nofpu/atomic-feholdexcept.c
> @@ -0,0 +1,38 @@
> +/* Store current floating-point environment and clear exceptions for
> + atomic compound assignment.
> + 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/>. */
> +
> +#include "soft-fp.h"
> +#include "soft-supp.h"
> +
> +void
> +__atomic_feholdexcept (fenv_t *envp)
> +{
> + fenv_union_t u;
> +
> + u.l[0] = __sim_exceptions_thread;
> + /* The rounding mode is not changed by arithmetic, so no need to
> + save it. */
> + u.l[1] = __sim_disabled_exceptions_thread;
> + *envp = u.fenv;
> +
> + /* This function postdates the global variables being turned into
> + compat symbols, so no need to set them. */
> + __sim_exceptions_thread = 0;
> + __sim_disabled_exceptions_thread = FE_ALL_EXCEPT;
> +}
> diff --git a/sysdeps/powerpc/nofpu/atomic-feupdateenv.c b/sysdeps/powerpc/nofpu/atomic-feupdateenv.c
> new file mode 100644
> index 0000000..9334e11
> --- /dev/null
> +++ b/sysdeps/powerpc/nofpu/atomic-feupdateenv.c
> @@ -0,0 +1,37 @@
> +/* Install given floating-point environment and raise exceptions for
> + atomic compound assignment.
> + 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/>. */
> +
> +#include "soft-fp.h"
> +#include "soft-supp.h"
> +#include <signal.h>
> +
> +void
> +__atomic_feupdateenv (const fenv_t *envp)
> +{
> + fenv_union_t u;
> + int saved_exceptions = __sim_exceptions_thread;
> +
> + /* This function postdates the global variables being turned into
> + compat symbols, so no need to set them. */
> + u.fenv = *envp;
> + __sim_exceptions_thread |= u.l[0];
> + __sim_disabled_exceptions_thread = u.l[1];
> + if (saved_exceptions & ~__sim_disabled_exceptions_thread)
> + raise (SIGFPE);
> +}
> diff --git a/sysdeps/powerpc/nofpu/flt-rounds.c b/sysdeps/powerpc/nofpu/flt-rounds.c
> new file mode 100644
> index 0000000..ad2bf94
> --- /dev/null
> +++ b/sysdeps/powerpc/nofpu/flt-rounds.c
> @@ -0,0 +1,38 @@
> +/* Return current rounding mode as correct value for FLT_ROUNDS.
> + 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/>. */
> +
> +#include "soft-fp.h"
> +#include "soft-supp.h"
> +
> +int
> +__flt_rounds (void)
> +{
> + switch (__sim_round_mode_thread)
> + {
> + case FP_RND_ZERO:
> + return 0;
> + case FP_RND_NEAREST:
> + return 1;
> + case FP_RND_PINF:
> + return 2;
> + case FP_RND_MINF:
> + return 3;
> + default:
> + abort ();
> + }
> +}
> diff --git a/sysdeps/powerpc/powerpc32/e500/nofpu/atomic-feclearexcept.c b/sysdeps/powerpc/powerpc32/e500/nofpu/atomic-feclearexcept.c
> new file mode 100644
> index 0000000..9005119
> --- /dev/null
> +++ b/sysdeps/powerpc/powerpc32/e500/nofpu/atomic-feclearexcept.c
> @@ -0,0 +1,50 @@
> +/* Clear floating-point exceptions for atomic compound assignment.
> + e500 version.
> + Copyright (C) 2004-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/>. */
> +
> +#include <fenv_libc.h>
> +#include <stdlib.h>
> +#include <sysdep.h>
> +#include <sys/prctl.h>
> +
> +void
> +__atomic_feclearexcept (void)
> +{
> + unsigned int fpescr, old_fpescr;
> +
> + /* Get the current state. */
> + old_fpescr = fpescr = fegetenv_register ();
> +
> + /* Clear the relevant bits. */
> + fpescr &= ~SPEFSCR_ALL_EXCEPT;
> +
> + /* Put the new state in effect. */
> + fesetenv_register (fpescr);
> +
> + /* Let the kernel know if the "invalid" or "underflow" bit was
> + cleared. */
> + if (old_fpescr & (SPEFSCR_FINVS | SPEFSCR_FUNFS))
> + {
> + int pflags __attribute__ ((__unused__)), r;
> + INTERNAL_SYSCALL_DECL (err);
> +
> + r = INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &pflags);
> + if (INTERNAL_SYSCALL_ERROR_P (r, err))
> + abort ();
> + }
> +}
> diff --git a/sysdeps/powerpc/powerpc32/e500/nofpu/atomic-feholdexcept.c b/sysdeps/powerpc/powerpc32/e500/nofpu/atomic-feholdexcept.c
> new file mode 100644
> index 0000000..afd225e
> --- /dev/null
> +++ b/sysdeps/powerpc/powerpc32/e500/nofpu/atomic-feholdexcept.c
> @@ -0,0 +1,55 @@
> +/* Store current floating-point environment and clear exceptions for
> + atomic compound assignment. e500 version.
> + Copyright (C) 2004-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/>. */
> +
> +#include <fenv_libc.h>
> +#include <stdlib.h>
> +#include <sysdep.h>
> +#include <sys/prctl.h>
> +
> +void
> +__atomic_feholdexcept (fenv_t *envp)
> +{
> + fenv_union_t u;
> + INTERNAL_SYSCALL_DECL (err);
> + int r;
> +
> + /* Get the current state. */
> + r = INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &u.l[0]);
> + if (INTERNAL_SYSCALL_ERROR_P (r, err))
> + abort ();
> +
> + u.l[1] = fegetenv_register ();
> + *envp = u.fenv;
> +
> + /* Clear everything except for the rounding mode and trapping to the
> + kernel. */
> + u.l[0] &= ~(PR_FP_EXC_DIV
> + | PR_FP_EXC_OVF
> + | PR_FP_EXC_UND
> + | PR_FP_EXC_RES
> + | PR_FP_EXC_INV);
> + u.l[1] &= SPEFSCR_FRMC | (SPEFSCR_ALL_EXCEPT_ENABLE & ~SPEFSCR_FINXE);
> +
> + /* Put the new state in effect. */
> + fesetenv_register (u.l[1]);
> + r = INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC,
> + u.l[0] | PR_FP_EXC_SW_ENABLE);
> + if (INTERNAL_SYSCALL_ERROR_P (r, err))
> + abort ();
> +}
> diff --git a/sysdeps/powerpc/powerpc32/e500/nofpu/atomic-feupdateenv.c b/sysdeps/powerpc/powerpc32/e500/nofpu/atomic-feupdateenv.c
> new file mode 100644
> index 0000000..9ae6b45
> --- /dev/null
> +++ b/sysdeps/powerpc/powerpc32/e500/nofpu/atomic-feupdateenv.c
> @@ -0,0 +1,46 @@
> +/* Install given floating-point environment and raise exceptions for
> + atomic compound assignment. e500 version.
> + Copyright (C) 2004-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/>. */
> +
> +#include <fenv_libc.h>
> +#include <stdlib.h>
> +#include <sysdep.h>
> +#include <sys/prctl.h>
> +
> +void
> +__atomic_feupdateenv (const fenv_t *envp)
> +{
> + int exc;
> + fenv_union_t u;
> + INTERNAL_SYSCALL_DECL (err);
> + int r;
> +
> + /* Save the currently set exceptions. */
> + exc = fegetenv_register () & SPEFSCR_ALL_EXCEPT;
> +
> + u.fenv = *envp;
> +
> + fesetenv_register (u.l[1]);
> + r = INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC,
> + u.l[0] | PR_FP_EXC_SW_ENABLE);
> + if (INTERNAL_SYSCALL_ERROR_P (r, err))
> + abort ();
> +
> + /* Raise (if appropriate) saved exceptions. */
> + __feraiseexcept_soft (exc);
> +}
> diff --git a/sysdeps/powerpc/powerpc32/e500/nofpu/fenv_libc.h b/sysdeps/powerpc/powerpc32/e500/nofpu/fenv_libc.h
> index 9637580..916776a 100644
> --- a/sysdeps/powerpc/powerpc32/e500/nofpu/fenv_libc.h
> +++ b/sysdeps/powerpc/powerpc32/e500/nofpu/fenv_libc.h
> @@ -24,6 +24,9 @@
> int __feraiseexcept_spe (int);
> libm_hidden_proto (__feraiseexcept_spe)
>
> +int __feraiseexcept_soft (int);
> +libc_hidden_proto (__feraiseexcept_soft)
> +
> int __fexcepts_to_spe (int);
> libm_hidden_proto (__fexcepts_to_spe)
>
> diff --git a/sysdeps/powerpc/powerpc32/e500/nofpu/flt-rounds.c b/sysdeps/powerpc/powerpc32/e500/nofpu/flt-rounds.c
> new file mode 100644
> index 0000000..49e6eeb
> --- /dev/null
> +++ b/sysdeps/powerpc/powerpc32/e500/nofpu/flt-rounds.c
> @@ -0,0 +1,39 @@
> +/* Return current rounding mode as correct value for FLT_ROUNDS. e500
> + version.
> + 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/>. */
> +
> +#include <fenv_libc.h>
> +#include <stdlib.h>
> +
> +int
> +__flt_rounds (void)
> +{
> + switch (fegetenv_register () & SPEFSCR_FRMC)
> + {
> + case FE_TOWARDZERO:
> + return 0;
> + case FE_TONEAREST:
> + return 1;
> + case FE_UPWARD:
> + return 2;
> + case FE_DOWNWARD:
> + return 3;
> + default:
> + abort ();
> + }
> +}
> diff --git a/sysdeps/powerpc/powerpc32/e500/nofpu/fraiseexcept-soft.c b/sysdeps/powerpc/powerpc32/e500/nofpu/fraiseexcept-soft.c
> index 0aed72f..22b2bda 100644
> --- a/sysdeps/powerpc/powerpc32/e500/nofpu/fraiseexcept-soft.c
> +++ b/sysdeps/powerpc/powerpc32/e500/nofpu/fraiseexcept-soft.c
> @@ -20,9 +20,6 @@
> #include <fenv_libc.h>
> #include <libc-symbols.h>
>
> -int __feraiseexcept_soft (int);
> -libc_hidden_proto (__feraiseexcept_soft)
> -
> #define __FERAISEEXCEPT_INTERNAL __feraiseexcept_soft
> #include "spe-raise.c"
> libc_hidden_def (__feraiseexcept_soft)
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/nptl/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/nptl/libc.abilist
> index 9b6d663..a54382e 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/nptl/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/nptl/libc.abilist
> @@ -1784,6 +1784,12 @@ GLIBC_2.17
> GLIBC_2.18
> GLIBC_2.18 A
> __cxa_thread_atexit_impl F
> +GLIBC_2.19
> + GLIBC_2.19 A
> + __atomic_feclearexcept F
> + __atomic_feholdexcept F
> + __atomic_feupdateenv F
> + __flt_rounds F
> GLIBC_2.2
> GLIBC_2.2 A
> _IO_adjust_wcolumn F
>