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]

[PATCH 1/6] Add framework to test IFUNC implementations on target


Hi,

This patch adds the framework to test IFUNC implementations on target.
When mulit-arch is enabled, __libc_func is added which takes a function
name and returns the NULL terminated array of IFUNC implementations
supported on target machine.  FOR_EACH_IMPL is updated to run each
implementation returned from __libc_func.  OK to install?

Thanks.


H.J.
---
 ChangeLog.test-ifunc        | 20 ++++++++++++++++
 Rules                       |  5 ++++
 include/libc-func.h         | 37 +++++++++++++++++++++++++++++
 string/Makefile             |  6 +++++
 string/Versions             |  6 +++++
 string/test-string.h        | 57 ++++++++++++++++++++++++++++++++++++++++++++-
 sysdeps/generic/libc-func.c | 28 ++++++++++++++++++++++
 7 files changed, 158 insertions(+), 1 deletion(-)
 create mode 100644 ChangeLog.test-ifunc
 create mode 100644 include/libc-func.h
 create mode 100644 sysdeps/generic/libc-func.c

diff --git a/ChangeLog.test-ifunc b/ChangeLog.test-ifunc
new file mode 100644
index 0000000..815076b
--- /dev/null
+++ b/ChangeLog.test-ifunc
@@ -0,0 +1,20 @@
+2012-09-26  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* Rules (tests): Filter out $(tests-ifunc) if multi-arch isn't
+	enabled.
+	(xtests): Filter out $(xtests-ifunc) if multi-arch isn't enabled.
+	* include/libc-func.h: New file.
+	* sysdeps/generic/libc-func.c: LIkewise.
+	* string/Makefile: Include ../Makeconfig.
+	(routines): Add libc-func if $(multi-arch) is yes.
+	* string/Versions: Add __libc_func to GLIBC_PRIVATE if
+	USE_MULTIARCH is defined.
+	* string/test-string.h: Include <libc-func.h>.
+	(func_list): New.  Defined only if TEST_IFUNC and TEST_NAME are
+	defined.
+	(impl_count): Likewise.
+	(impl_array): Likewise.
+	(FOR_EACH_IMPL): Support func_list if TEST_IFUNC and TEST_NAME
+	are defined.
+	(test_init): Call __libc_func to initialize func_list only if
+	TEST_IFUNC and TEST_NAME are defined.
diff --git a/Rules b/Rules
index 17d938e..ccc003e 100644
--- a/Rules
+++ b/Rules
@@ -84,6 +84,11 @@ common-generated += dummy.o dummy.c
 # This makes all the auxiliary and test programs.
 
 .PHONY: others tests
+ifneq ($(multi-arch),yes)
+tests := $(filter-out $(tests-ifunc), $(tests))
+xtests := $(filter-out $(xtests-ifunc), $(xtests))
+endif
+
 ifeq ($(build-programs),yes)
 others: $(addprefix $(objpfx),$(others) $(sysdep-others) $(extra-objs))
 else
diff --git a/include/libc-func.h b/include/libc-func.h
new file mode 100644
index 0000000..467c7f2
--- /dev/null
+++ b/include/libc-func.h
@@ -0,0 +1,37 @@
+/* Copyright (C) 2012 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, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _LIBC_FUNC_H
+#define _LIBC_FUNC_H	1
+
+struct libc_func_test
+{
+  /* The name of function to be tested.  */
+  const char *name;
+  /* The address of function to be tested.  */
+  void (*fn) (void);
+};
+
+/* Initializer for struct libc_func_test entry.  */
+#define LIBC_FUNC_INIT(fn) { #fn, (void (*) (void)) fn }
+
+/* Return the NULL terminated array of IFUNC implementations supported
+   on target machine.  */
+extern const struct libc_func_test *__libc_func (const char *);
+
+#endif /* libc-func.h */
diff --git a/string/Makefile b/string/Makefile
index a1204d9..0171ff2 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -20,6 +20,8 @@
 #
 subdir	:= string
 
+include ../Makeconfig
+
 headers	:= string.h strings.h memory.h endian.h bits/endian.h \
 	   argz.h envz.h byteswap.h bits/byteswap.h bits/byteswap-16.h \
 	   bits/string.h bits/string2.h bits/string3.h
@@ -41,6 +43,10 @@ routines	:= strcat strchr strcmp strcoll strcpy strcspn		\
 		   strcoll_l strxfrm_l string-inlines memrchr		\
 		   xpg-strerror strerror_l
 
+ifeq ($(multi-arch),yes)
+routines	+= libc-func
+endif
+
 # Gcc internally generates calls to unbounded memcpy and memset
 # for -fbounded-pointer compiles.  Glibc uses memchr for explicit checks.
 o-objects.ob	:= memcpy.o memset.o memchr.o
diff --git a/string/Versions b/string/Versions
index f145fd3..24c77f2 100644
--- a/string/Versions
+++ b/string/Versions
@@ -80,4 +80,10 @@ libc {
   GLIBC_2.6 {
     strerror_l;
   }
+
+%ifdef USE_MULTIARCH
+  GLIBC_PRIVATE {
+    __libc_func;
+  }
+%endif
 }
diff --git a/string/test-string.h b/string/test-string.h
index c94d822..074a79c 100644
--- a/string/test-string.h
+++ b/string/test-string.h
@@ -50,6 +50,7 @@ extern impl_t __start_impls[], __stop_impls[];
 #include <error.h>
 #include <errno.h>
 #include <time.h>
+#include <libc-func.h>
 #define GL(x) _##x
 #define GLRO(x) _##x
 #include <hp-timing.h>
@@ -106,9 +107,59 @@ size_t iterations = 100000;
 #define CALL(impl, ...)	\
   (* (proto_t) (impl)->fn) (__VA_ARGS__)
 
-#define FOR_EACH_IMPL(impl, notall) \
+#if defined TEST_IFUNC && defined TEST_NAME
+static const struct libc_func_test *func_list;
+static int impl_count = -1;
+static impl_t *impl_array;
+
+# define FOR_EACH_IMPL(impl, notall) \
+  impl_t *impl;								\
+  int count;								\
+  if (impl_count == -1)							\
+    {									\
+      impl_count = 0;							\
+      if (func_list)							\
+	{								\
+	  const struct libc_func_test *p;				\
+	  impl_t *skip = NULL;						\
+	  for (impl = __start_impls; impl < __stop_impls; ++impl)	\
+	    if (strcmp (impl->name, TEST_NAME) == 0)			\
+	      skip = impl;						\
+	    else							\
+	      impl_count++;						\
+	  for (p = func_list; p && p->name; ++p)			\
+	    impl_count++;						\
+	  if (impl_count)						\
+	    {								\
+	      impl_t *a;						\
+	      a = impl_array = malloc (impl_count * sizeof (impl_t));	\
+	      for (impl = __start_impls; impl < __stop_impls; ++impl)	\
+	        if (impl != skip)					\
+		  *a++ = *impl;						\
+	      for (p = func_list; p && p->name; ++p)			\
+		{							\
+		  a->name = p->name;					\
+		  a->fn = p->fn;					\
+		  a->test = 1;						\
+		  a++;							\
+		}							\
+	    }								\
+	}								\
+      else								\
+        {								\
+	  for (impl = __start_impls; impl < __stop_impls; ++impl)	\
+	    impl_count++;						\
+	  impl_array = __start_impls;					\
+        }								\
+    }									\
+  impl = impl_array;							\
+  for (count = 0; count < impl_count; ++count, ++impl)			\
+    if (!notall || impl->test)
+#else
+# define FOR_EACH_IMPL(impl, notall) \
   for (impl_t *impl = __start_impls; impl < __stop_impls; ++impl)	\
     if (!notall || impl->test)
+#endif
 
 #define HP_TIMING_BEST(best_time, start, end)	\
   do									\
@@ -127,6 +178,10 @@ size_t iterations = 100000;
 static void
 test_init (void)
 {
+#if defined TEST_IFUNC && defined TEST_NAME
+  func_list = __libc_func (TEST_NAME);
+#endif
+
   page_size = 2 * getpagesize ();
 #ifdef MIN_PAGE_SIZE
   if (page_size < MIN_PAGE_SIZE)
diff --git a/sysdeps/generic/libc-func.c b/sysdeps/generic/libc-func.c
new file mode 100644
index 0000000..edbbf01
--- /dev/null
+++ b/sysdeps/generic/libc-func.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2012 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, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <stdlib.h>
+#include <libc-func.h>
+
+/* Return the NULL terminated array of functions.  */
+
+const struct libc_func_test *
+__libc_func (const char *name __attribute__ ((unused)))
+{
+  return NULL;
+}
-- 
1.7.11.4


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