Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 8 Feb 2010 22:30:04 GMT
From:      Maxim Zakharov <maxime@maxime.net.ru>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: kern/141682: [libc] [patch] Faster version of strncpy(3)
Message-ID:  <201002082230.o18MU4PX078694@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/141682; it has been noted by GNATS.

From: Maxim Zakharov <maxime@maxime.net.ru>
To: Jim White <spamchannel@gmail.com>
Cc: bug-followup@freebsd.org
Subject: Re: kern/141682: [libc] [patch] Faster version of strncpy(3)
Date: Tue, 9 Feb 2010 01:28:19 +0300

 Hello Jim,
 
 Thank you for pointing out the problem with padding by 0's. The
 version below has this issue fixed, but it's still faster than
 standard version if the code is compiled with optimization on modern
 processor.
 
 typedef long long word;  /* up to 32 bytes long */
 #define wsize sizeof(word)
 #define wmask (wsize - 1)
 
 inline void dps_minibzero(char *dst, size_t t) {
 	if (t) { dst[0] = '\0';
 	if (t > 1) { dst[1] = '\0';
 	if (t > 2) { dst[2] = '\0';
 	if (t > 3) { dst[3] = '\0';
 	if (t > 4) { dst[4] = '\0';
 	if (t > 5) { dst[5] = '\0';
 	if (t > 6) { dst[6] = '\0';
 	if (t > 7) { dst[7] = '\0';
 	if (t > 8) { dst[8] = '\0';
 	if (t > 9) { dst[9] = '\0';
 	if (t > 10) { dst[10] = '\0';
 	if (t > 11) { dst[11] = '\0';
 	if (t > 12) { dst[12] = '\0';
 	if (t > 13) { dst[13] = '\0';
 	if (t > 14) { dst[14] = '\0';
 	if (t > 15) { dst[15] = '\0';
 	if (t > 16) { dst[16] = '\0';
 	if (t > 17) { dst[17] = '\0';
 	if (t > 18) { dst[18] = '\0';
 	if (t > 19) { dst[19] = '\0';
 	if (t > 20) { dst[20] = '\0';
 	if (t > 21) { dst[21] = '\0';
 	if (t > 22) { dst[22] = '\0';
 	if (t > 23) { dst[23] = '\0';
 	if (t > 24) { dst[24] = '\0';
 	if (t > 25) { dst[25] = '\0';
 	if (t > 26) { dst[26] = '\0';
 	if (t > 27) { dst[27] = '\0';
 	if (t > 28) { dst[28] = '\0';
 	if (t > 29) { dst[29] = '\0';
 	if (t > 30) { dst[30] = '\0';
 	}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
 }
 
 
 void * dps_strncpy(char *dst0, char *src0, size_t length) {
   if (length) {
     register size_t n = length / 8;
     register size_t r = (length % 8);
     register char *dst = dst0, *src = src0;
     if (r == 0) r = 8; else n++;
     if (!(dst[0] = src[0])) { dst++; src++; goto dps_strncpy_second_pas; }
     if (r > 1) { if (!(dst[1] = src[1])) { dst += 2; src += 2; goto
 dps_strncpy_second_pas; }
     if (r > 2) { if (!(dst[2] = src[2])) { dst += 3; src += 3; goto
 dps_strncpy_second_pas; }
     if (r > 3) { if (!(dst[3] = src[3])) { dst += 4; src += 4; goto
 dps_strncpy_second_pas; }
     if (r > 4) { if (!(dst[4] = src[4])) { dst += 5; src += 5; goto
 dps_strncpy_second_pas; }
     if (r > 5) { if (!(dst[5] = src[5])) { dst += 6; src += 6; goto
 dps_strncpy_second_pas; }
     if (r > 6) { if (!(dst[6] = src[6])) { dst += 7; src += 7; goto
 dps_strncpy_second_pas; }
     if (r > 7) { if (!(dst[7] = src[7])) { dst += 8; src += 8; goto
 dps_strncpy_second_pas; }
     }}}}}}}
     src += r; dst += r;
     while (--n > 0) {
       if (!(dst[0] = src[0])) { dst++; src++; goto dps_strncpy_second_pas; }
       if (!(dst[1] = src[1])) { dst += 2; src += 2; goto
 dps_strncpy_second_pas; }
       if (!(dst[2] = src[2])) { dst += 3; src += 3; goto
 dps_strncpy_second_pas; }
       if (!(dst[3] = src[3])) { dst += 4; src += 4; goto
 dps_strncpy_second_pas; }
       if (!(dst[4] = src[4])) { dst += 5; src += 5; goto
 dps_strncpy_second_pas; }
       if (!(dst[5] = src[5])) { dst += 6; src += 6; goto
 dps_strncpy_second_pas; }
       if (!(dst[6] = src[6])) { dst += 7; src += 7; goto
 dps_strncpy_second_pas; }
       if (!(dst[7] = src[7])) { dst += 8; src += 8; goto
 dps_strncpy_second_pas; }
       src += 8; dst += 8;
     }
 dps_strncpy_second_pas:
     if (dst < dst0 + length) {
       size_t t, restlen = length + dst0 - dst;
       t = (unsigned int)dst & wmask;
       if (t) {
     	if (restlen < wsize) {
 		t = restlen;
     	} else {
 		t = wsize - t;
     	}
 	bzero(dst, t);
 	dps_minibzero(dst, t);
 	restlen -= t;
 	dst += t;
       }
       t = restlen / wsize;
       if (t) {
 	n = t / 8;
     	r = (t % 8);
 	register word *wdst = (word*)dst;
     	if (r == 0) r = 8; else n++;
     	wdst[0] = (word)0;
     	if (r > 1) { wdst[1] = (word)0;
     	if (r > 2) { wdst[2] = (word)0;
     	if (r > 3) { wdst[3] = (word)0;
     	if (r > 4) { wdst[4] = (word)0;
     	if (r > 5) { wdst[5] = (word)0;
     	if (r > 6) { wdst[6] = (word)0;
     	if (r > 7) { wdst[7] = (word)0;
 	}}}}}}}
     	wdst += r;
     	while (--n > 0) {
     		wdst[0] = (word)0;
     		wdst[1] = (word)0;
     		wdst[2] = (word)0;
     		wdst[3] = (word)0;
     		wdst[4] = (word)0;
     		wdst[5] = (word)0;
     		wdst[6] = (word)0;
     		wdst[7] = (word)0;
     		wdst += 8;
     	}
  	dst = (char*)wdst;
       }
       if ( (t = (restlen & wmask)) ) dps_minibzero(dst, t);
     }
   }
   return dst0;
 }
 
 
 On 2/8/10, Jim White <spamchannel@gmail.com> wrote:
 > The replacement strncpy you propose in PR 141682 (copied below), is not a
 > valid replacement for strncpy.  The strncpy function always writes exactly
 > length bytes to dst0 (padding with 0 bytes after the first 0 byte of src0 is
 > found).  The below function does not do this.  A quick example program to
 > demonstrate follows:
 >
 >
 > void * dps_strncpy(char *dst0, char *src0, size_t length) {
 > if (length) {
 > register size_t n = (length + 7) / 8;
 > register size_t r = (length % 8);
 > register char *dst = dst0, *src = src0;
 > if (r == 0) r = 8;
 > if (!(dst[0] = src[0])) return dst0;
 > if (r > 1) if (!(dst[1] = src[1])) return dst0;
 > if (r > 2) if (!(dst[2] = src[2])) return dst0;
 > if (r > 3) if (!(dst[3] = src[3])) return dst0;
 > if (r > 4) if (!(dst[4] = src[4])) return dst0;
 > if (r > 5) if (!(dst[5] = src[5])) return dst0;
 > if (r > 6) if (!(dst[6] = src[6])) return dst0;
 > if (r > 7) if (!(dst[7] = src[7])) return dst0;
 > src += r; dst += r;
 > while (--n > 0) {
 > if (!(dst[0] = src[0])) break;
 > if (!(dst[1] = src[1])) break;
 > if (!(dst[2] = src[2])) break;
 > if (!(dst[3] = src[3])) break;
 > if (!(dst[4] = src[4])) break;
 > if (!(dst[5] = src[5])) break;
 > if (!(dst[6] = src[6])) break;
 > if (!(dst[7] = src[7])) break;
 > src += 8; dst += 8;
 > }
 > }
 > return dst0;
 > }
 >
 > int main()
 > {
 > char buf[]="01234567890123456789012345678901234567890";
 > dps_strncpy(buf,"abcdef",sizeof buf);
 > fwrite(buf,1,sizeof buf,stdout);
 > strncpy(buf,"abcdef",sizeof buf);
 > puts("");
 > fwrite(buf,1,sizeof buf,stdout);
 > return 0;
 > }
 >
 >
 > The output of this is:
 >
 > ./a.out
 > abcdef7890123456789012345678901234567890
 > abcdef
 >
 
 
 -- 
 http://www.dataparksearch.org/



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201002082230.o18MU4PX078694>