This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

Re: [Patch][aarch64] Use IFUNCs to enable LSE instructions in libatomic on aarch64


On Tue, 2017-08-29 at 12:25 +0100, Szabolcs Nagy wrote:
> 
> in glibc the hwcap is not used, because it has accesses to
> cached dispatch info, but in libatomic using the hwcap
> argument is the right way.

Here is an updated version of the patch to allow aarch64 to use ifuncs
in libatomic.

The main difference from the last patch is that the library does not
access the hwcap value directly but accesses it through the ifunc
resolver argument.  That means that we no longer need the
init_cpu_revision static constructor to set a flag that the resolver
checks, instead the resolver just does a comparision of its incoming
argument with HWCAP_ATOMICS.

This did mean I had to change the prototype for the resolver functions
in libatomic_i.h to have an argument, which is the way glibc calls
them.  One complication of this is that the type of the argument can
differ between platforms and ABIs so I added code to configure.tgt to
set the type.  I used uint64_t for aarch64 and 'long unsigned int'
for everything else.  That is not correct for all platforms but at 
this point no other platforms access the argument so it should not
matter.  If and when platforms do need to access it they can change
the type if necessary.

Steve Ellcey
sellcey@cavium.com


2017-08-31  Steve Ellcey  <sellcey@cavium.com>

	* Makefile.am (ARCH_AARCH64_LINUX_LSE): Add IFUNC_OPTIONS and
	libatomic_la_LIBADD.
	* config/linux/aarch64/host-config.h: New file.
	* configure.ac (HWCAP_TYPE): Define.
	(AC_CHECK_HEADERS): Check for sys/auxv.h.
	(AC_CHECK_FUNCS): Check for getauxval.
	(ARCH_AARCH64_LINUX_LSE): New conditional for IFUNC builds.
	* configure.tgt (aarch64): Set AARCH and try_ifunc.
	(aarch64*-*-linux*) Update config_path.
	(aarch64*-*-linux*) Set HWCAP_TYPE.
	* libatomic_i.h (GEN_SELECTOR): Add "HWCAP_TYPE hwcap" argument.
	* Makefile.in: Regenerate.
	* auto-config.h.in: Regenerate.
	* configure: Regenerate.

diff --git a/libatomic/Makefile.am b/libatomic/Makefile.am
index d731406..a35df1e 100644
--- a/libatomic/Makefile.am
+++ b/libatomic/Makefile.am
@@ -122,6 +122,10 @@ libatomic_la_LIBADD = $(foreach s,$(SIZES),$(addsuffix _$(s)_.lo,$(SIZEOBJS)))
 
 ## On a target-specific basis, include alternates to be selected by IFUNC.
 if HAVE_IFUNC
+if ARCH_AARCH64_LINUX_LSE
+IFUNC_OPTIONS	     = -mcpu=thunderx2t99
+libatomic_la_LIBADD += $(foreach s,$(SIZES),$(addsuffix _$(s)_1_.lo,$(SIZEOBJS)))
+endif
 if ARCH_ARM_LINUX
 IFUNC_OPTIONS	     = -march=armv7-a -DHAVE_KERNEL64
 libatomic_la_LIBADD += $(foreach s,$(SIZES),$(addsuffix _$(s)_1_.lo,$(SIZEOBJS)))
diff --git a/libatomic/config/linux/aarch64/host-config.h b/libatomic/config/linux/aarch64/host-config.h
index e69de29..2e5e97a 100644
--- a/libatomic/config/linux/aarch64/host-config.h
+++ b/libatomic/config/linux/aarch64/host-config.h
@@ -0,0 +1,39 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+
+   This file is part of the GNU Atomic Library (libatomic).
+
+   Libatomic is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   Libatomic 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 General Public License for
+   more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#if HAVE_IFUNC
+#include <stdlib.h>
+#ifdef HAVE_SYS_AUXV_H
+# include <sys/auxv.h>
+#endif
+
+# ifdef HWCAP_ATOMICS
+#  define IFUNC_COND_1	(hwcap & HWCAP_ATOMICS)
+# else
+#  define IFUNC_COND_1	(false)
+# endif
+# define IFUNC_NCOND(N)	(1)
+
+#endif /* HAVE_IFUNC */
+
+#include_next <host-config.h>
diff --git a/libatomic/configure.ac b/libatomic/configure.ac
index 023f172..4e06ffe 100644
--- a/libatomic/configure.ac
+++ b/libatomic/configure.ac
@@ -163,6 +163,10 @@ if test -n "$UNSUPPORTED"; then
   AC_MSG_ERROR([Configuration ${target} is unsupported.])
 fi
 
+# Write out the ifunc resolver arg type.
+AC_DEFINE_UNQUOTED(HWCAP_TYPE, $HWCAP_TYPE,
+	[Define type of ifunc resolver function argument.])
+
 # Disable fallbacks to __sync routines from libgcc.  Otherwise we'll
 # make silly decisions about what the cpu can do.
 CFLAGS="$save_CFLAGS -fno-sync-libcalls $XCFLAGS"
@@ -171,7 +175,8 @@ CFLAGS="$save_CFLAGS -fno-sync-libcalls $XCFLAGS"
 AC_STDC_HEADERS
 ACX_HEADER_STRING
 GCC_HEADER_STDINT(gstdint.h)
-AC_CHECK_HEADERS([fenv.h])
+AC_CHECK_HEADERS([fenv.h sys/auxv.h])
+AC_CHECK_FUNCS(getauxval)
 
 # Check for common type sizes
 LIBAT_FORALL_MODES([LIBAT_HAVE_INT_MODE])
@@ -247,6 +252,8 @@ AC_SUBST(LIBS)
 AC_SUBST(SIZES)
 
 AM_CONDITIONAL(HAVE_IFUNC, test x$libat_cv_have_ifunc = xyes)
+AM_CONDITIONAL(ARCH_AARCH64_LINUX_LSE,
+	       [expr "$config_path" : ".* linux/aarch64 .*" > /dev/null])
 AM_CONDITIONAL(ARCH_ARM_LINUX,
 	       [expr "$config_path" : ".* linux/arm .*" > /dev/null])
 AM_CONDITIONAL(ARCH_I386,
diff --git a/libatomic/configure.tgt b/libatomic/configure.tgt
index b8af3ab..0bb5c66 100644
--- a/libatomic/configure.tgt
+++ b/libatomic/configure.tgt
@@ -40,6 +40,14 @@ case "${target_cpu}" in
   riscv*)		ARCH=riscv ;;
   sh*)			ARCH=sh ;;
 
+  aarch64*)
+	ARCH=aarch64
+	case "${target}" in
+	    aarch64*-*-linux*)
+		try_ifunc=yes
+		;;
+	esac
+	;;
   arm*)
 	ARCH=arm
 	case "${target}" in
@@ -109,6 +117,11 @@ fi
 
 # Other system configury
 case "${target}" in
+  aarch64*-*-linux*)
+	# OS support for atomic primitives.
+	config_path="${config_path} linux/aarch64 posix"
+	;;
+
   arm*-*-linux*)
 	# OS support for atomic primitives.
 	config_path="${config_path} linux/arm posix"
@@ -153,3 +166,14 @@ case "${target}" in
 	UNSUPPORTED=1
 	;;
 esac
+
+# glibc will pass hwcap to ifunc resolver functions as an argument.
+# The type may be different on different architectures.
+case "${target}" in
+  aarch64*-*-*)
+	HWCAP_TYPE=uint64_t
+	;;
+  *)
+	HWCAP_TYPE="unsigned long int"
+	;;
+esac
diff --git a/libatomic/libatomic_i.h b/libatomic/libatomic_i.h
index 4eb372a..e7f2050 100644
--- a/libatomic/libatomic_i.h
+++ b/libatomic/libatomic_i.h
@@ -240,7 +240,7 @@ bool libat_is_lock_free (size_t, void *) MAN(is_lock_free);
 # if IFUNC_NCOND(N) == 1
 #  define GEN_SELECTOR(X)					\
 	extern typeof(C2(libat_,X)) C3(libat_,X,_i1) HIDDEN;	\
-	static void * C2(select_,X) (void)			\
+	static void * C2(select_,X) (HWCAP_TYPE hwcap)		\
 	{							\
 	  if (IFUNC_COND_1)					\
 	    return C3(libat_,X,_i1);				\
@@ -250,7 +250,7 @@ bool libat_is_lock_free (size_t, void *) MAN(is_lock_free);
 #  define GEN_SELECTOR(X)					\
 	extern typeof(C2(libat_,X)) C3(libat_,X,_i1) HIDDEN;	\
 	extern typeof(C2(libat_,X)) C3(libat_,X,_i2) HIDDEN;	\
-	static void * C2(select_,X) (void)			\
+	static void * C2(select_,X) (HWCAP_TYPE hwcap)		\
 	{							\
 	  if (IFUNC_COND_1)					\
 	    return C3(libat_,X,_i1);				\
@@ -263,7 +263,7 @@ bool libat_is_lock_free (size_t, void *) MAN(is_lock_free);
 	extern typeof(C2(libat_,X)) C3(libat_,X,_i1) HIDDEN;	\
 	extern typeof(C2(libat_,X)) C3(libat_,X,_i2) HIDDEN;	\
 	extern typeof(C2(libat_,X)) C3(libat_,X,_i3) HIDDEN;	\
-	static void * C2(select_,X) (void)			\
+	static void * C2(select_,X) (HWCAP_TYPE hwcap)		\
 	{							\
 	  if (IFUNC_COND_1)					\
 	    return C3(libat_,X,_i1);				\

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