Re: [PATCH] strlen

Brad Proctor (fredlie@sprynet.com)
Thu, 28 Oct 1999 18:23:36 -0400


This is a multi-part message in MIME format.
--------------9586618D2202BD3C9555435E
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Alan Cox wrote:
>
> > This, I think, is a problem on i386. You _cannot_ read beyond the
> > end of the string (might be on an other, unmapped page), but you
> > don't know that until you do, when doing 4 bytes at a time. I
> > mean: You can only know that you went to far...
>
> If you do the start then do aligned loads (always a good idea) on 4
> byte boundaries you wont cross a page by suprise.

Here is a simple fix for it. I'm not sure how to do the start though,
but I'll work on it. I'm not very good with inline assembly. %ebx, and
%ecx could be replaced with "r" in the input section but they don't need
to be initialized to any specific value, so I didn't know how to code
it.

Brad Proctor
--------------9586618D2202BD3C9555435E
Content-Type: text/plain; charset=us-ascii;
name="strlen.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="strlen.diff"

--- linux-2.3.24/include/asm-i386/string-486.h Thu Oct 28 15:00:30 1999
+++ linux/include/asm-i386/string-486.h Thu Oct 28 18:00:17 1999
@@ -325,22 +325,53 @@
#define __HAVE_ARCH_STRLEN
extern inline size_t strlen(const char * s)
{
+ if (s & 3) {
/*
* slightly slower on a 486, but with better chances of
* register allocation
*/
-register char dummy, *tmp= (char *)s;
-__asm__ __volatile__(
- "\n1:\t"
- "movb\t(%0),%1\n\t"
- "incl\t%0\n\t"
- "testb\t%1,%1\n\t"
- "jne\t1b"
- :"=r" (tmp),"=q" (dummy)
- :"0" (s)
- : "memory" );
-return (tmp-s-1);
+ register char dummy, *tmp= (char *)s;
+ __asm__ __volatile__(
+ "\n1:\t"
+ "movb\t(%0),%1\n\t"
+ "incl\t%0\n\t"
+ "testb\t%1,%1\n\t"
+ "jne\t1b"
+ :"=r" (tmp),"=q" (dummy)
+ :"0" (s)
+ : "memory" );
+ return (tmp-s-1);
+ } else {
+ /*
+ * This function works by testing 4 bytes at a time
+ * and averages 1.8 clock cycles per byte.
+ */
+ register int __res;
+ __asm__ __volatile__ (
+ "addl %0,%2\n\t"
+ "movl (%0),%%ebx\n\t"
+ "addl $4,%0\n\t"
+ ".align 2\n\t"
+ "1:leal -0x1010101(%%ebx),%%ecx\n\t"
+ "xorl $-1,%%ebx\n\t"
+ "andl %%ebx,%%ecx\n\t"
+ "movl (%0),%%ebx\n\t"
+ "addl $4,%0\n\t"
+ "andl $0x80808080,%%ecx\n\t"
+ "jz 1b\n\t"
+ "testl $0x8080,%%ecx\n\t"
+ "jnz 1f\n\t"
+ "shrl $16,%%ecx\n\t"
+ "addl $2,%0\n\t"
+ "1:shlb $1,%%cl\n\t"
+ "sbbl %2,%0\n\t"
+ : "=r" (__res)
+ : "0" (s), "r" (7)
+ : "ebx", "ecx");
+ return (__res);
+ }
}
+

/* Added by Gertjan van Wingerde to make minix and sysv module work */
#define __HAVE_ARCH_STRNLEN

--------------9586618D2202BD3C9555435E--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/