Port remaining string benchmarks
authorSiddhesh Poyarekar <siddhesh@redhat.com>
Tue, 11 Jun 2013 15:21:55 +0000 (20:51 +0530)
committerSiddhesh Poyarekar <siddhesh@redhat.com>
Tue, 11 Jun 2013 15:21:55 +0000 (20:51 +0530)
There were a few more string benchmarks (strcpy_chk and stpcpy_check)
in the debug directory that needed to be ported over.

ChangeLog
benchtests/Makefile
benchtests/bench-stpcpy_chk-ifunc.c [new file with mode: 0644]
benchtests/bench-stpcpy_chk.c [new file with mode: 0644]
benchtests/bench-strcpy_chk-ifunc.c [new file with mode: 0644]
benchtests/bench-strcpy_chk.c [new file with mode: 0644]
debug/test-strcpy_chk.c

index f2f9f7d..3a451b4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2013-06-11  Siddhesh Poyarekar  <siddhesh@redhat.com>
+
+       * benchtests/Makefile (string-bench): Add strcpy_chk and
+       stpcpy_chk.
+       * benchtests/bench-stpcpy_chk-ifunc.c: New file.
+       * benchtests/bench-stpcpy_chk.c: New file.
+       * benchtests/bench-strcpy_chk-ifunc.c: New file.
+       * benchtests/bench-strcpy_chk.c: New file.
+       * debug/test-strcpy_chk.c (do_one_test): Remove HP_TIMING
+       code.
+       (do_test): Likewise.
+
 2013-06-11  Ryan S. Arnold  <rsa@linux.vnet.ibm.com>
 
        * sysdeps/powerpc/dl-procinfo.c (_dl_powerpc_platforms): Add ppc405,
index 5023c7c..ba313d2 100644 (file)
@@ -27,7 +27,8 @@ bench := acos acosh asin asinh atan atanh cos cosh exp log modf pow rint sin \
 string-bench := bcopy bzero memccpy memchr memcmp memmem memmove mempcpy \
                memset rawmemchr stpcpy stpncpy strcasecmp strcasestr strcat \
                strchr strchrnul strcmp strcpy strcspn strlen strncasecmp \
-               strncat strncmp strncpy strnlen strpbrk strrchr strspn strstr
+               strncat strncmp strncpy strnlen strpbrk strrchr strspn strstr \
+               strcpy_chk stpcpy_chk
 string-bench-ifunc := $(addsuffix -ifunc, $(string-bench))
 string-bench-all := $(string-bench) $(string-bench-ifunc)
 
diff --git a/benchtests/bench-stpcpy_chk-ifunc.c b/benchtests/bench-stpcpy_chk-ifunc.c
new file mode 100644 (file)
index 0000000..3449615
--- /dev/null
@@ -0,0 +1,20 @@
+/* Measure IFUNC implementations of stpcpy checking function.
+   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/>.  */
+
+#define TEST_IFUNC 1
+#include "bench-stpcpy_chk.c"
diff --git a/benchtests/bench-stpcpy_chk.c b/benchtests/bench-stpcpy_chk.c
new file mode 100644 (file)
index 0000000..964ca5e
--- /dev/null
@@ -0,0 +1,45 @@
+/* Measure stpcpy checking functions.
+   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/>.  */
+
+#define STRCPY_RESULT(dst, len) ((dst) + (len))
+#define TEST_MAIN
+#define TEST_NAME "stpcpy_chk"
+#include "bench-string.h"
+
+extern void __attribute__ ((noreturn)) __chk_fail (void);
+char *simple_stpcpy_chk (char *, const char *, size_t);
+extern char *normal_stpcpy (char *, const char *, size_t)
+  __asm ("stpcpy");
+extern char *__stpcpy_chk (char *, const char *, size_t);
+
+IMPL (simple_stpcpy_chk, 0)
+IMPL (normal_stpcpy, 1)
+IMPL (__stpcpy_chk, 2)
+
+char *
+simple_stpcpy_chk (char *dst, const char *src, size_t len)
+{
+  if (! len)
+    __chk_fail ();
+  while ((*dst++ = *src++) != '\0')
+    if (--len == 0)
+      __chk_fail ();
+  return dst - 1;
+}
+
+#include "bench-strcpy_chk.c"
diff --git a/benchtests/bench-strcpy_chk-ifunc.c b/benchtests/bench-strcpy_chk-ifunc.c
new file mode 100644 (file)
index 0000000..2dd2aa3
--- /dev/null
@@ -0,0 +1,20 @@
+/* Measure IFUNC implementations of strcpy checking function.
+   Copyright (C) 2012-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/>.  */
+
+#define TEST_IFUNC 1
+#include "bench-strcpy_chk.c"
diff --git a/benchtests/bench-strcpy_chk.c b/benchtests/bench-strcpy_chk.c
new file mode 100644 (file)
index 0000000..29e5728
--- /dev/null
@@ -0,0 +1,262 @@
+/* Measure __strcpy_chk functions.
+   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/>.  */
+
+#ifndef STRCPY_RESULT
+# define STRCPY_RESULT(dst, len) dst
+# define TEST_MAIN
+# define TEST_NAME "strcpy_chk"
+# include "bench-string.h"
+
+/* This test case implicitly tests the availability of the __chk_fail
+   symbol, which is part of the public ABI and may be used
+   externally. */
+extern void __attribute__ ((noreturn)) __chk_fail (void);
+char *simple_strcpy_chk (char *, const char *, size_t);
+extern char *normal_strcpy (char *, const char *, size_t)
+  __asm ("strcpy");
+extern char *__strcpy_chk (char *, const char *, size_t);
+
+IMPL (simple_strcpy_chk, 0)
+IMPL (normal_strcpy, 1)
+IMPL (__strcpy_chk, 2)
+
+char *
+simple_strcpy_chk (char *dst, const char *src, size_t len)
+{
+  char *ret = dst;
+  if (! len)
+    __chk_fail ();
+  while ((*dst++ = *src++) != '\0')
+    if (--len == 0)
+      __chk_fail ();
+  return ret;
+}
+#endif
+
+#include <fcntl.h>
+#include <paths.h>
+#include <setjmp.h>
+#include <signal.h>
+
+volatile int chk_fail_ok;
+jmp_buf chk_fail_buf;
+
+static void
+handler (int sig)
+{
+  if (chk_fail_ok)
+    {
+      chk_fail_ok = 0;
+      longjmp (chk_fail_buf, 1);
+    }
+  else
+    _exit (127);
+}
+
+typedef char *(*proto_t) (char *, const char *, size_t);
+
+static void
+do_one_test (impl_t *impl, char *dst, const char *src,
+            size_t len, size_t dlen)
+{
+  char *res;
+  if (dlen <= len)
+    {
+      if (impl->test == 1)
+       return;
+
+      chk_fail_ok = 1;
+      if (setjmp (chk_fail_buf) == 0)
+       {
+         res = CALL (impl, dst, src, dlen);
+         printf ("*** Function %s (%zd; %zd) did not __chk_fail\n",
+                 impl->name, len, dlen);
+         chk_fail_ok = 0;
+         ret = 1;
+       }
+      return;
+    }
+  else
+    res = CALL (impl, dst, src, dlen);
+
+  if (res != STRCPY_RESULT (dst, len))
+    {
+      printf ("Wrong result in function %s %p %p\n", impl->name,
+             res, STRCPY_RESULT (dst, len));
+      ret = 1;
+      return;
+    }
+
+  if (strcmp (dst, src) != 0)
+    {
+      printf ("Wrong result in function %s dst \"%s\" src \"%s\"\n",
+             impl->name, dst, src);
+      ret = 1;
+      return;
+    }
+
+  if (HP_TIMING_AVAIL)
+    {
+      hp_timing_t start __attribute ((unused));
+      hp_timing_t stop __attribute ((unused));;
+      hp_timing_t best_time = ~ (hp_timing_t) 0;
+      size_t i;
+
+      for (i = 0; i < 32; ++i)
+       {
+         HP_TIMING_NOW (start);
+         CALL (impl, dst, src, dlen);
+         HP_TIMING_NOW (stop);
+         HP_TIMING_BEST (best_time, start, stop);
+       }
+
+      printf ("\t%zd", (size_t) best_time);
+    }
+}
+
+static void
+do_test (size_t align1, size_t align2, size_t len, size_t dlen, int max_char)
+{
+  size_t i;
+  char *s1, *s2;
+
+  align1 &= 7;
+  if (align1 + len >= page_size)
+    return;
+
+  align2 &= 7;
+  if (align2 + len >= page_size)
+    return;
+
+  s1 = (char *) buf1 + align1;
+  s2 = (char *) buf2 + align2;
+
+  for (i = 0; i < len; i++)
+    s1[i] = 32 + 23 * i % (max_char - 32);
+  s1[len] = 0;
+
+  if (HP_TIMING_AVAIL && dlen > len)
+    printf ("Length %4zd, alignment %2zd/%2zd:", len, align1, align2);
+
+  FOR_EACH_IMPL (impl, 0)
+    do_one_test (impl, s2, s1, len, dlen);
+
+  if (HP_TIMING_AVAIL && dlen > len)
+    putchar ('\n');
+}
+
+int
+test_main (void)
+{
+  size_t i;
+
+  struct sigaction sa;
+  sa.sa_handler = handler;
+  sa.sa_flags = 0;
+  sigemptyset (&sa.sa_mask);
+
+  sigaction (SIGABRT, &sa, NULL);
+
+  /* Avoid all the buffer overflow messages on stderr.  */
+  int fd = open (_PATH_DEVNULL, O_WRONLY);
+  if (fd == -1)
+    close (STDERR_FILENO);
+  else
+    {
+      dup2 (fd, STDERR_FILENO);
+      close (fd);
+    }
+  setenv ("LIBC_FATAL_STDERR_", "1", 1);
+
+  test_init ();
+
+  printf ("%23s", "");
+  FOR_EACH_IMPL (impl, 0)
+    printf ("\t%s", impl->name);
+  putchar ('\n');
+
+  for (i = 0; i < 16; ++i)
+    {
+      do_test (0, 0, i, i + 1, 127);
+      do_test (0, 0, i, i + 1, 255);
+      do_test (0, i, i, i + 1, 127);
+      do_test (i, 0, i, i + 1, 255);
+    }
+
+  for (i = 1; i < 8; ++i)
+    {
+      do_test (0, 0, 8 << i, (8 << i) + 1, 127);
+      do_test (8 - i, 2 * i, (8 << i), (8 << i) + 1, 127);
+    }
+
+  for (i = 1; i < 8; ++i)
+    {
+      do_test (i, 2 * i, (8 << i), (8 << i) + 1, 127);
+      do_test (2 * i, i, (8 << i), (8 << i) + 1, 255);
+      do_test (i, i, (8 << i), (8 << i) + 1, 127);
+      do_test (i, i, (8 << i), (8 << i) + 1, 255);
+    }
+
+  for (i = 0; i < 16; ++i)
+    {
+      do_test (0, 0, i, i + 256, 127);
+      do_test (0, 0, i, i + 256, 255);
+      do_test (0, i, i, i + 256, 127);
+      do_test (i, 0, i, i + 256, 255);
+    }
+
+  for (i = 1; i < 8; ++i)
+    {
+      do_test (0, 0, 8 << i, (8 << i) + 256, 127);
+      do_test (8 - i, 2 * i, (8 << i), (8 << i) + 256, 127);
+    }
+
+  for (i = 1; i < 8; ++i)
+    {
+      do_test (i, 2 * i, (8 << i), (8 << i) + 256, 127);
+      do_test (2 * i, i, (8 << i), (8 << i) + 256, 255);
+      do_test (i, i, (8 << i), (8 << i) + 256, 127);
+      do_test (i, i, (8 << i), (8 << i) + 256, 255);
+    }
+
+  for (i = 0; i < 16; ++i)
+    {
+      do_test (0, 0, i, i, 127);
+      do_test (0, 0, i, i + 2, 255);
+      do_test (0, i, i, i + 3, 127);
+      do_test (i, 0, i, i + 4, 255);
+    }
+
+  for (i = 1; i < 8; ++i)
+    {
+      do_test (0, 0, 8 << i, (8 << i) - 15, 127);
+      do_test (8 - i, 2 * i, (8 << i), (8 << i) + 5, 127);
+    }
+
+  for (i = 1; i < 8; ++i)
+    {
+      do_test (i, 2 * i, (8 << i), (8 << i) + i, 127);
+      do_test (2 * i, i, (8 << i), (8 << i) + (i - 1), 255);
+      do_test (i, i, (8 << i), (8 << i) + i + 2, 127);
+      do_test (i, i, (8 << i), (8 << i) + i + 3, 255);
+    }
+
+  return 0;
+}
+
+#include "../test-skeleton.c"
index 1c64c60..736ef3c 100644 (file)
@@ -110,24 +110,6 @@ do_one_test (impl_t *impl, char *dst, const char *src,
       ret = 1;
       return;
     }
-
-  if (HP_TIMING_AVAIL)
-    {
-      hp_timing_t start __attribute ((unused));
-      hp_timing_t stop __attribute ((unused));;
-      hp_timing_t best_time = ~ (hp_timing_t) 0;
-      size_t i;
-
-      for (i = 0; i < 32; ++i)
-       {
-         HP_TIMING_NOW (start);
-         CALL (impl, dst, src, dlen);
-         HP_TIMING_NOW (stop);
-         HP_TIMING_BEST (best_time, start, stop);
-       }
-
-      printf ("\t%zd", (size_t) best_time);
-    }
 }
 
 static void
@@ -151,14 +133,8 @@ do_test (size_t align1, size_t align2, size_t len, size_t dlen, int max_char)
     s1[i] = 32 + 23 * i % (max_char - 32);
   s1[len] = 0;
 
-  if (HP_TIMING_AVAIL && dlen > len)
-    printf ("Length %4zd, alignment %2zd/%2zd:", len, align1, align2);
-
   FOR_EACH_IMPL (impl, 0)
     do_one_test (impl, s2, s1, len, dlen);
-
-  if (HP_TIMING_AVAIL && dlen > len)
-    putchar ('\n');
 }
 
 static void