GNU C Library master sources branch, master, updated. glibc-2.12-73-g24fb0f8

drepper@sourceware.org drepper@sourceware.org
Mon Jul 26 15:39:00 GMT 2010


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  24fb0f88ed29d21b6034559e9c55545f22556bc0 (commit)
      from  8e96b93aa7855683d0be3c65ce81e66d0786ba84 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sources.redhat.com/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=24fb0f88ed29d21b6034559e9c55545f22556bc0

commit 24fb0f88ed29d21b6034559e9c55545f22556bc0
Author: Ulrich Drepper <drepper@redhat.com>
Date:   Mon Jul 26 08:37:08 2010 -0700

    Add optimized x86-64 implementation of strnlen.
    
    While at it, beef up the test suite for strnlen and add performance
    tests for it, too.

diff --git a/ChangeLog b/ChangeLog
index 4a22a07..36b36fc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2010-07-26  Ulrich Drepper  <drepper@redhat.com>
+
+	* string/test-strnlen.c: New file.
+	* string/Makefile (strop-tests): Add strnlen.
+	* string/tester.c (test_strnlen): Add a few more test cases.
+	* string/tst-strlen.c: Better error reporting.
+
+	* sysdeps/x86_64/strnlen.S: New file.
+
 2010-07-24  Ulrich Drepper  <drepper@redhat.com>
 
 	* sysdeps/x86_64/multiarch/strstr.c (__m128i_strloadu_tolower): Use
diff --git a/string/Makefile b/string/Makefile
index 0267ea1..e8eb514 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -49,7 +49,7 @@ o-objects.ob	:= memcpy.o memset.o memchr.o
 strop-tests	:= memchr memcmp memcpy memmove mempcpy memset memccpy	\
 		   stpcpy stpncpy strcat strchr strcmp strcpy strcspn	\
 		   strlen strncmp strncpy strpbrk strrchr strspn memmem	\
-		   strstr strcasestr
+		   strstr strcasestr strnlen
 tests		:= tester inl-tester noinl-tester testcopy test-ffs	\
 		   tst-strlen stratcliff tst-svc tst-inlcall		\
 		   bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap	\
diff --git a/string/test-strnlen.c b/string/test-strnlen.c
new file mode 100644
index 0000000..cb8c80f
--- /dev/null
+++ b/string/test-strnlen.c
@@ -0,0 +1,197 @@
+/* Test and measure strlen functions.
+   Copyright (C) 1999, 2002, 2003, 2005, 2010 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+   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.  */
+
+#define TEST_MAIN
+#include "test-string.h"
+
+typedef size_t (*proto_t) (const char *, size_t);
+size_t simple_strnlen (const char *, size_t);
+
+IMPL (simple_strnlen, 0)
+IMPL (strnlen, 1)
+
+size_t
+simple_strnlen (const char *s, size_t maxlen)
+{
+  size_t i;
+
+  for (i = 0; i < maxlen && s[i]; ++i);
+  return i;
+}
+
+static void
+do_one_test (impl_t *impl, const char *s, size_t maxlen, size_t exp_len)
+{
+  size_t len = CALL (impl, s, maxlen);
+  if (len != exp_len)
+    {
+      error (0, 0, "Wrong result in function %s %zd %zd", impl->name,
+	     len, exp_len);
+      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, s, maxlen);
+	  HP_TIMING_NOW (stop);
+	  HP_TIMING_BEST (best_time, start, stop);
+	}
+
+      printf ("\t%zd", (size_t) best_time);
+    }
+}
+
+static void
+do_test (size_t align, size_t len, size_t maxlen, int max_char)
+{
+  size_t i;
+
+  align &= 7;
+  if (align + len >= page_size)
+    return;
+
+  for (i = 0; i < len; ++i)
+    buf1[align + i] = 1 + 7 * i % max_char;
+  buf1[align + len] = 0;
+
+  if (HP_TIMING_AVAIL)
+    printf ("Length %4zd, alignment %2zd:", len, align);
+
+  FOR_EACH_IMPL (impl, 0)
+    do_one_test (impl, (char *) (buf1 + align), maxlen, MIN (len, maxlen));
+
+  if (HP_TIMING_AVAIL)
+    putchar ('\n');
+}
+
+static void
+do_random_tests (void)
+{
+  size_t i, j, n, align, len;
+  unsigned char *p = buf1 + page_size - 512;
+
+  for (n = 0; n < ITERATIONS; n++)
+    {
+      align = random () & 15;
+      len = random () & 511;
+      if (len + align > 510)
+	len = 511 - align - (random () & 7);
+      j = len + align + 64;
+      if (j > 512)
+	j = 512;
+
+      for (i = 0; i < j; i++)
+	{
+	  if (i == len + align)
+	    p[i] = 0;
+	  else
+	    {
+	      p[i] = random () & 255;
+	      if (i >= align && i < len + align && !p[i])
+		p[i] = (random () & 127) + 1;
+	    }
+	}
+
+      FOR_EACH_IMPL (impl, 1)
+	{
+	  if (len > 0
+	      && CALL (impl, (char *) (p + align), len - 1) != len - 1)
+	    {
+	      error (0, 0, "Iteration %zd (limited) - wrong result in function %s (%zd) %zd != %zd, p %p",
+		     n, impl->name, align,
+		     CALL (impl, (char *) (p + align), len - 1), len - 1, p);
+	      ret = 1;
+	    }
+	  if (CALL (impl, (char *) (p + align), len) != len)
+	    {
+	      error (0, 0, "Iteration %zd (exact) - wrong result in function %s (%zd) %zd != %zd, p %p",
+		     n, impl->name, align,
+		     CALL (impl, (char *) (p + align), len), len, p);
+	      ret = 1;
+	    }
+	  if (CALL (impl, (char *) (p + align), len + 1) != len)
+	    {
+	      error (0, 0, "Iteration %zd (long) - wrong result in function %s (%zd) %zd != %zd, p %p",
+		     n, impl->name, align,
+		     CALL (impl, (char *) (p + align), len + 1), len, p);
+	      ret = 1;
+	    }
+	}
+    }
+}
+
+int
+test_main (void)
+{
+  size_t i;
+
+  test_init ();
+
+  printf ("%20s", "");
+  FOR_EACH_IMPL (impl, 0)
+    printf ("\t%s", impl->name);
+  putchar ('\n');
+
+  for (i = 1; i < 8; ++i)
+    {
+      do_test (0, i, i - 1, 127);
+      do_test (0, i, i, 127);
+      do_test (0, i, i + 1, 127);
+    }
+
+  for (i = 1; i < 8; ++i)
+    {
+      do_test (i, i, i - 1, 127);
+      do_test (i, i, i, 127);
+      do_test (i, i, i + 1, 127);
+    }
+
+  for (i = 2; i <= 10; ++i)
+    {
+      do_test (0, 1 << i, 5000, 127);
+      do_test (1, 1 << i, 5000, 127);
+    }
+
+  for (i = 1; i < 8; ++i)
+    do_test (0, i, 5000, 255);
+
+  for (i = 1; i < 8; ++i)
+    do_test (i, i, 5000, 255);
+
+  for (i = 2; i <= 10; ++i)
+    {
+      do_test (0, 1 << i, 5000, 255);
+      do_test (1, 1 << i, 5000, 255);
+    }
+
+  do_random_tests ();
+  return ret;
+}
+
+#include "../test-skeleton.c"
diff --git a/string/tester.c b/string/tester.c
index 773e969..01da046 100644
--- a/string/tester.c
+++ b/string/tester.c
@@ -1,5 +1,5 @@
 /* Tester for string functions.
-   Copyright (C) 1995-2001, 2003, 2005, 2008 Free Software Foundation, Inc.
+   Copyright (C) 1995-2001, 2003, 2005, 2008, 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
@@ -441,20 +441,21 @@ test_strnlen (void)
   check (strnlen ("", 10) == 0, 1);		/* Empty. */
   check (strnlen ("a", 10) == 1, 2);		/* Single char. */
   check (strnlen ("abcd", 10) == 4, 3);		/* Multiple chars. */
-  check (strnlen ("foo", (size_t)-1) == 3, 4);	/* limits of n. */
-
-  {
-    char buf[4096];
-    int i;
-    char *p;
-    for (i=0; i < 0x100; i++)
-      {
-	p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
-	strcpy (p, "OK");
-	strcpy (p+3, "BAD/WRONG");
-	check (strnlen (p, 100) == 2, 5+i);
-      }
-   }
+  check (strnlen ("foo", (size_t) -1) == 3, 4);	/* limits of n. */
+  check (strnlen ("abcd", 0) == 0, 5);		/* Restricted. */
+  check (strnlen ("abcd", 1) == 1, 6);		/* Restricted. */
+  check (strnlen ("abcd", 2) == 2, 7);		/* Restricted. */
+  check (strnlen ("abcd", 3) == 3, 8);		/* Restricted. */
+  check (strnlen ("abcd", 4) == 4, 9);		/* Restricted. */
+
+  char buf[4096];
+  for (int i = 0; i < 0x100; ++i)
+    {
+      char *p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
+      strcpy (p, "OK");
+      strcpy (p + 3, "BAD/WRONG");
+      check (strnlen (p, 100) == 2, 10 + i);
+    }
 }
 
 static void
@@ -988,7 +989,7 @@ test_memcmp (void)
   int cnt = 1;
   char one[21];
   char two[21];
-  
+
   it = "memcmp";
   check(memcmp("a", "a", 1) == 0, cnt++);	/* Identity. */
   check(memcmp("abc", "abc", 3) == 0, cnt++);	/* Multicharacter. */
diff --git a/string/tst-strlen.c b/string/tst-strlen.c
index a1e1159..8cbe441 100644
--- a/string/tst-strlen.c
+++ b/string/tst-strlen.c
@@ -31,11 +31,21 @@ main(int argc, char *argv[])
 	      buf[words * 4 + 3] = (last & 8) != 0 ? 'e' : '\0';
 	      buf[words * 4 + 4] = '\0';
 
-	      if (strlen (buf) != words * 4 + lens[last]
-		  || strnlen (buf, -1) != words * 4 + lens[last])
+	      if (strlen (buf) != words * 4 + lens[last])
 		{
-		  printf ("failed for base=%Zu, words=%Zu, and last=%Zu\n",
-			  base, words, last);
+		  printf ("\
+strlen failed for base=%Zu, words=%Zu, and last=%Zu (is %zd, expected %zd)\n",
+			  base, words, last,
+			  strlen (buf), words * 4 + lens[last]);
+		  return 1;
+		}
+
+	      if (strnlen (buf, -1) != words * 4 + lens[last])
+		{
+		  printf ("\
+strnlen failed for base=%Zu, words=%Zu, and last=%Zu (is %zd, expected %zd)\n",
+			  base, words, last,
+			  strnlen (buf, -1), words * 4 + lens[last]);
 		  return 1;
 		}
 	    }
diff --git a/sysdeps/x86_64/strnlen.S b/sysdeps/x86_64/strnlen.S
new file mode 100644
index 0000000..939782d
--- /dev/null
+++ b/sysdeps/x86_64/strnlen.S
@@ -0,0 +1,64 @@
+/* strnlen(str,maxlen) -- determine the length of the string STR up to MAXLEN.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper <drepper@redhat.com>.
+   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 <sysdep.h>
+
+
+	.text
+ENTRY(__strnlen)
+	movq	%rsi, %rax
+	testq	%rsi, %rsi
+	jz	3f
+	pxor	%xmm2, %xmm2
+	movq	%rdi, %rcx
+	movq	%rdi, %r8
+	movq	$16, %r9
+	andq	$~15, %rdi
+	movdqa	%xmm2, %xmm1
+	pcmpeqb	(%rdi), %xmm2
+	orl	$0xffffffff, %r10d
+	subq	%rdi, %rcx
+	shll	%cl, %r10d
+	subq	%rcx, %r9
+	pmovmskb %xmm2, %edx
+	andl	%r10d, %edx
+	jnz	1f
+	subq	%r9, %rsi
+	jbe	3f
+
+2:	movdqa	16(%rdi), %xmm0
+	leaq	16(%rdi), %rdi
+	pcmpeqb	%xmm1, %xmm0
+	pmovmskb %xmm0, %edx
+	testl	%edx, %edx
+	jnz	1f
+	subq	$16, %rsi
+	jnbe	2b
+3:	ret
+
+1:	subq	%r8, %rdi
+	bsfl	%edx, %edx
+	addq	%rdi, %rdx
+	cmpq	%rdx, %rax
+	cmovnbq	%rdx, %rax
+	ret
+END(__strnlen)
+weak_alias (__strnlen, strnlen)
+libc_hidden_def (strnlen)

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                                |    9 +++
 string/Makefile                          |    2 +-
 string/{test-strlen.c => test-strnlen.c} |   91 ++++++++++++++++++------------
 string/tester.c                          |   33 ++++++-----
 string/tst-strlen.c                      |   18 +++++-
 sysdeps/x86_64/{strlen.S => strnlen.S}   |   35 ++++++++----
 6 files changed, 119 insertions(+), 69 deletions(-)
 copy string/{test-strlen.c => test-strnlen.c} (60%)
 copy sysdeps/x86_64/{strlen.S => strnlen.S} (70%)


hooks/post-receive
-- 
GNU C Library master sources



More information about the Glibc-cvs mailing list