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]

Add powerpc-nofpu/e500 support functions for atomic compound assignment and FLT_ROUNDS


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

-- 
Joseph S. Myers
joseph@codesourcery.com


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