This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH 1/6] Add framework to test IFUNC implementations on target
- From: "H.J. Lu" <hjl dot tools at gmail dot com>
- To: GNU C Library <libc-alpha at sourceware dot org>
- Date: Wed, 26 Sep 2012 07:41:31 -0700
- Subject: [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