diff --git a/debug/test-stpcpy_chk.c b/debug/test-stpcpy_chk.c index d717ca7..1f8f588 100644 --- a/debug/test-stpcpy_chk.c +++ b/debug/test-stpcpy_chk.c @@ -20,6 +20,7 @@ #define STRCPY_RESULT(dst, len) ((dst) + (len)) #define TEST_MAIN +#define TEST_NAME "stpcpy_chk" #include "../string/test-string.h" extern void __attribute__ ((noreturn)) __chk_fail (void); diff --git a/debug/test-strcpy_chk.c b/debug/test-strcpy_chk.c index e08141d..05bd0cb 100644 --- a/debug/test-strcpy_chk.c +++ b/debug/test-strcpy_chk.c @@ -21,6 +21,7 @@ #ifndef STRCPY_RESULT # define STRCPY_RESULT(dst, len) dst # define TEST_MAIN +# define TEST_NAME "strcpy_chk" # include "../string/test-string.h" extern void __attribute__ ((noreturn)) __chk_fail (void); diff --git a/include/libc-test.h b/include/libc-test.h new file mode 100644 index 0000000..edd814f --- /dev/null +++ b/include/libc-test.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2010 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_TEST_H +#define _LIBC_TEST_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); +}; + +/* Return the NULL terminated array of functions. */ +extern const struct libc_func_test *__libc_func (const char *); + +#endif /* libc-symbols.h */ diff --git a/string/Makefile b/string/Makefile index f836f59..d25d23d 100644 --- a/string/Makefile +++ b/string/Makefile @@ -40,7 +40,7 @@ routines := strcat strchr strcmp strcoll strcpy strcspn \ addsep replace) \ envz basename \ strcoll_l strxfrm_l string-inlines memrchr \ - xpg-strerror strerror_l + xpg-strerror strerror_l libc-test # Gcc internally generates calls to unbounded memcpy and memset # for -fbounded-pointer compiles. Glibc uses memchr for explicit checks. diff --git a/string/Versions b/string/Versions index f145fd3..fe6a418 100644 --- a/string/Versions +++ b/string/Versions @@ -80,4 +80,7 @@ libc { GLIBC_2.6 { strerror_l; } + GLIBC_2.13 { + __libc_func; + } } diff --git a/string/test-memccpy.c b/string/test-memccpy.c index 2653263..c5676cf 100644 --- a/string/test-memccpy.c +++ b/string/test-memccpy.c @@ -19,6 +19,7 @@ 02111-1307 USA. */ #define TEST_MAIN +#define TEST_NAME "memccpy" #include "test-string.h" void *simple_memccpy (void *, const void *, int, size_t); diff --git a/string/test-memchr.c b/string/test-memchr.c index cd9a01e..ab510ef 100644 --- a/string/test-memchr.c +++ b/string/test-memchr.c @@ -19,6 +19,7 @@ 02111-1307 USA. */ #define TEST_MAIN +#define TEST_NAME "memchr" #include "test-string.h" typedef char *(*proto_t) (const char *, int, size_t); diff --git a/string/test-memcmp.c b/string/test-memcmp.c index 3040e21..4fbfa54 100644 --- a/string/test-memcmp.c +++ b/string/test-memcmp.c @@ -19,6 +19,7 @@ 02111-1307 USA. */ #define TEST_MAIN +#define TEST_NAME "memcmp" #include "test-string.h" typedef int (*proto_t) (const char *, const char *, size_t); diff --git a/string/test-memcpy.c b/string/test-memcpy.c index 7b0723a..5b5c657 100644 --- a/string/test-memcpy.c +++ b/string/test-memcpy.c @@ -22,6 +22,7 @@ # define MEMCPY_RESULT(dst, len) dst # define MIN_PAGE_SIZE 131072 # define TEST_MAIN +# define TEST_NAME "memcpy" # include "test-string.h" char *simple_memcpy (char *, const char *, size_t); diff --git a/string/test-memmem.c b/string/test-memmem.c index 91b661b..4402623 100644 --- a/string/test-memmem.c +++ b/string/test-memmem.c @@ -19,6 +19,7 @@ 02111-1307 USA. */ #define TEST_MAIN +#define TEST_NAME "memmem" #define BUF1PAGES 20 #define ITERATIONS 500 #include "test-string.h" diff --git a/string/test-memmove.c b/string/test-memmove.c index 2f3a8f7..cf3fa1e 100644 --- a/string/test-memmove.c +++ b/string/test-memmove.c @@ -19,6 +19,7 @@ 02111-1307 USA. */ #define TEST_MAIN +#define TEST_NAME "memmove" #include "test-string.h" typedef char *(*proto_t) (char *, const char *, size_t); diff --git a/string/test-mempcpy.c b/string/test-mempcpy.c index f8b0267..9bf2e86 100644 --- a/string/test-mempcpy.c +++ b/string/test-mempcpy.c @@ -20,6 +20,7 @@ #define MEMCPY_RESULT(dst, len) (dst) + (len) #define TEST_MAIN +#define TEST_NAME "mempcpy" #include "test-string.h" char *simple_mempcpy (char *, const char *, size_t); diff --git a/string/test-memset.c b/string/test-memset.c index 601ace4..cdc51d0 100644 --- a/string/test-memset.c +++ b/string/test-memset.c @@ -19,6 +19,7 @@ 02111-1307 USA. */ #define TEST_MAIN +#define TEST_NAME "memset" #define MIN_PAGE_SIZE 131072 #include "test-string.h" diff --git a/string/test-stpcpy.c b/string/test-stpcpy.c index c8d4cc4..0582aaa 100644 --- a/string/test-stpcpy.c +++ b/string/test-stpcpy.c @@ -20,6 +20,7 @@ #define STRCPY_RESULT(dst, len) ((dst) + (len)) #define TEST_MAIN +#define TEST_NAME "stpcpy" #include "test-string.h" char *simple_stpcpy (char *, const char *); diff --git a/string/test-stpncpy.c b/string/test-stpncpy.c index 8784588..115cf79 100644 --- a/string/test-stpncpy.c +++ b/string/test-stpncpy.c @@ -20,6 +20,7 @@ #define STRNCPY_RESULT(dst, len, n) ((dst) + ((len) > (n) ? (n) : (len))) #define TEST_MAIN +#define TEST_NAME "stpncpy" #include "test-string.h" char *simple_stpncpy (char *, const char *, size_t); diff --git a/string/test-strcasecmp.c b/string/test-strcasecmp.c index 7d1d110..261af13 100644 --- a/string/test-strcasecmp.c +++ b/string/test-strcasecmp.c @@ -20,6 +20,7 @@ #include #define TEST_MAIN +#define TEST_NAME "strcasecmp" #include "test-string.h" typedef int (*proto_t) (const char *, const char *); diff --git a/string/test-strcasestr.c b/string/test-strcasestr.c index edc41f3..9981c23 100644 --- a/string/test-strcasestr.c +++ b/string/test-strcasestr.c @@ -19,6 +19,7 @@ 02111-1307 USA. */ #define TEST_MAIN +#define TEST_NAME "strcasestr" #include "test-string.h" diff --git a/string/test-strcat.c b/string/test-strcat.c index 4437520..83b133a 100644 --- a/string/test-strcat.c +++ b/string/test-strcat.c @@ -19,6 +19,7 @@ 02111-1307 USA. */ #define TEST_MAIN +#define TEST_NAME "strcat" #include "test-string.h" typedef char *(*proto_t) (char *, const char *); diff --git a/string/test-strchr.c b/string/test-strchr.c index cf25b44..200327c 100644 --- a/string/test-strchr.c +++ b/string/test-strchr.c @@ -19,6 +19,7 @@ 02111-1307 USA. */ #define TEST_MAIN +#define TEST_NAME "strchr" #include "test-string.h" typedef char *(*proto_t) (const char *, int); diff --git a/string/test-strcmp.c b/string/test-strcmp.c index 769e982..71242e3 100644 --- a/string/test-strcmp.c +++ b/string/test-strcmp.c @@ -19,6 +19,7 @@ 02111-1307 USA. */ #define TEST_MAIN +#define TEST_NAME "strcmp" #include "test-string.h" typedef int (*proto_t) (const char *, const char *); diff --git a/string/test-strcpy.c b/string/test-strcpy.c index 6a2ea25..7a4e3be 100644 --- a/string/test-strcpy.c +++ b/string/test-strcpy.c @@ -21,6 +21,7 @@ #ifndef STRCPY_RESULT # define STRCPY_RESULT(dst, len) dst # define TEST_MAIN +# define TEST_NAME "strcpy" # include "test-string.h" char *simple_strcpy (char *, const char *); diff --git a/string/test-strcspn.c b/string/test-strcspn.c index b563179..403a2fd 100644 --- a/string/test-strcspn.c +++ b/string/test-strcspn.c @@ -21,6 +21,7 @@ #define STRPBRK_RESULT(s, pos) (pos) #define RES_TYPE size_t #define TEST_MAIN +#define TEST_NAME "strcspn" #include "test-string.h" typedef size_t (*proto_t) (const char *, const char *); diff --git a/string/test-string.h b/string/test-string.h index 1aea4c9..db7d02e 100644 --- a/string/test-string.h +++ b/string/test-string.h @@ -48,6 +48,7 @@ extern impl_t __start_impls[], __stop_impls[]; #include #include #include +#include #define GL(x) _##x #define GLRO(x) _##x #include @@ -105,7 +106,32 @@ size_t iterations = 100000; (* (proto_t) (impl)->fn) (__VA_ARGS__) #define FOR_EACH_IMPL(impl, notall) \ - for (impl_t *impl = __start_impls; impl < __stop_impls; ++impl) \ + impl_t *impl; \ + int count; \ + if (impl_count == -1) \ + { \ + const struct libc_func_test *p; \ + impl_count = 0; \ + for (impl = __start_impls; impl < __stop_impls; ++impl) \ + 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, ++a) \ + *a = *impl; \ + for (p = func_list; p && p->name; ++p, a++) \ + { \ + a->name = p->name; \ + a->fn = p->fn; \ + a->test = 1; \ + } \ + } \ + } \ + impl = impl_array; \ + for (count = 0; count < impl_count; ++count, ++impl) \ if (!notall || impl->test) #define HP_TIMING_BEST(best_time, start, end) \ @@ -122,9 +148,15 @@ size_t iterations = 100000; # define BUF1PAGES 1 #endif +static const struct libc_func_test *func_list; +static int impl_count = -1; +static impl_t *impl_array; + static void test_init (void) { + func_list = __libc_func (TEST_NAME); + page_size = 2 * getpagesize (); #ifdef MIN_PAGE_SIZE if (page_size < MIN_PAGE_SIZE) diff --git a/string/test-strlen.c b/string/test-strlen.c index e01befb..feb1c5d 100644 --- a/string/test-strlen.c +++ b/string/test-strlen.c @@ -19,6 +19,7 @@ 02111-1307 USA. */ #define TEST_MAIN +#define TEST_NAME "strlen" #include "test-string.h" typedef size_t (*proto_t) (const char *); diff --git a/string/test-strncasecmp.c b/string/test-strncasecmp.c index daff6ed..9ec8955 100644 --- a/string/test-strncasecmp.c +++ b/string/test-strncasecmp.c @@ -20,6 +20,7 @@ #include #define TEST_MAIN +#define TEST_NAME "strncasecmp" #include "test-string.h" typedef int (*proto_t) (const char *, const char *, size_t); diff --git a/string/test-strncmp.c b/string/test-strncmp.c index 3687879..891acb0 100644 --- a/string/test-strncmp.c +++ b/string/test-strncmp.c @@ -19,6 +19,7 @@ 02111-1307 USA. */ #define TEST_MAIN +#define TEST_NAME "strncmp" #include "test-string.h" typedef int (*proto_t) (const char *, const char *, size_t); diff --git a/string/test-strncpy.c b/string/test-strncpy.c index d7a714c..f89b27d 100644 --- a/string/test-strncpy.c +++ b/string/test-strncpy.c @@ -21,6 +21,7 @@ #ifndef STRNCPY_RESULT # define STRNCPY_RESULT(dst, len, n) dst # define TEST_MAIN +# define TEST_NAME "strncpy" # include "test-string.h" char *simple_strncpy (char *, const char *, size_t); diff --git a/string/test-strnlen.c b/string/test-strnlen.c index cb8c80f..d078729 100644 --- a/string/test-strnlen.c +++ b/string/test-strnlen.c @@ -19,6 +19,7 @@ 02111-1307 USA. */ #define TEST_MAIN +#define TEST_NAME "strnlen" #include "test-string.h" typedef size_t (*proto_t) (const char *, size_t); diff --git a/string/test-strpbrk.c b/string/test-strpbrk.c index f3ed208..76ac8c7 100644 --- a/string/test-strpbrk.c +++ b/string/test-strpbrk.c @@ -22,6 +22,7 @@ # define STRPBRK_RESULT(s, pos) ((s)[(pos)] ? (s) + (pos) : NULL) # define RES_TYPE char * # define TEST_MAIN +# define TEST_NAME "strpbrk" # include "test-string.h" typedef char *(*proto_t) (const char *, const char *); diff --git a/string/test-strrchr.c b/string/test-strrchr.c index 92e8ab1..64af621 100644 --- a/string/test-strrchr.c +++ b/string/test-strrchr.c @@ -19,6 +19,7 @@ 02111-1307 USA. */ #define TEST_MAIN +#define TEST_NAME "strrchr" #include "test-string.h" typedef char *(*proto_t) (const char *, int); diff --git a/string/test-strspn.c b/string/test-strspn.c index 15cf492..ad7b845 100644 --- a/string/test-strspn.c +++ b/string/test-strspn.c @@ -19,6 +19,7 @@ 02111-1307 USA. */ #define TEST_MAIN +#define TEST_NAME "strspn" #include "test-string.h" typedef size_t (*proto_t) (const char *, const char *); diff --git a/string/test-strstr.c b/string/test-strstr.c index c1da686..6116d70 100644 --- a/string/test-strstr.c +++ b/string/test-strstr.c @@ -19,6 +19,7 @@ 02111-1307 USA. */ #define TEST_MAIN +#define TEST_NAME "strstr" #include "test-string.h" diff --git a/sysdeps/generic/libc-test.c b/sysdeps/generic/libc-test.c new file mode 100644 index 0000000..672e1e4 --- /dev/null +++ b/sysdeps/generic/libc-test.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2010 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 +#include + +/* Return the NULL terminated array of functions. */ + +const struct libc_func_test * +__libc_func (const char *name __attribute__ ((unused))) +{ + return NULL; +} diff --git a/sysdeps/x86_64/multiarch/libc-test.c b/sysdeps/x86_64/multiarch/libc-test.c new file mode 100644 index 0000000..5975e0b --- /dev/null +++ b/sysdeps/x86_64/multiarch/libc-test.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2010 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 +#include +#include +#include "init-arch.h" + +#if defined SHARED && !defined NOT_IN_libc +extern void *__memcpy_sse2 (void *, const void *, size_t); +extern void *__memcpy_ssse3 (void *, const void *, size_t); +extern void *__memcpy_ssse3_back (void *, const void *, size_t); + +static const struct libc_func_test memcpy_list [] = +{ + { "__memcpy_ssse3_back", (void (*) (void)) __memcpy_ssse3_back }, + { "__memcpy_ssse3", (void (*) (void)) __memcpy_ssse3 }, + { "__memcpy_sse2", (void (*) (void)) __memcpy_sse2 }, + { NULL, NULL }, +}; + +static const struct libc_func_test * +find_memcpy (void) +{ + return memcpy_list + (HAS_SSSE3 ? 0 : 2); +} +#else +static const struct libc_func_test * +find_memcpy (void) +{ + return NULL; +} +#endif + +const struct libc_func_test * +__libc_func (const char *name) +{ + if (strcmp (name, "memcpy") == 0) + return find_memcpy (); + + return NULL; +} diff --git a/sysdeps/x86_64/multiarch/memcpy.S b/sysdeps/x86_64/multiarch/memcpy.S index 8e9fb19..a45ca9f 100644 --- a/sysdeps/x86_64/multiarch/memcpy.S +++ b/sysdeps/x86_64/multiarch/memcpy.S @@ -44,6 +44,8 @@ END(memcpy) # undef ENTRY # define ENTRY(name) \ .type __memcpy_sse2, @function; \ + .globl __memcpy_sse2; \ + .hidden __memcpy_sse2; \ .p2align 4; \ __memcpy_sse2: cfi_startproc; \ CALL_MCOUNT