1 #include <sys/cdefs.h>;
  2 #include <string.h>;
  3 
  4 /*
  5 * sizeof(word) MUST BE A POWER OF TWO
  6 * SO THAT wmask BELOW IS ALL ONES
  7 */
  8 typedef    int word;        /* "word" used for optimal copy speed */
  9 
 10 #define    wsize    sizeof(word)
 11 #define    wmask    (wsize - 1)
 12 
 13 /*
 14 * Copy a block of memory, handling overlap.
 15 * This is the routine that actually implements
 16 * (the portable versions of) bcopy, memcpy, and memmove. 
 17 * length 以Byte作为度量单位
 18 */
 19 #ifdef MEMCOPY
 20 void *
 21 memcpy(dst0, src0, length)
 22 #else
 23 #ifdef MEMMOVE
 24 void *
 25 memmove(dst0, src0, length)
 26 #else
 27 void
 28 bcopy(src0, dst0, length)
 29 #endif
 30 #endif
 31     void *dst0;
 32     const void *src0;
 33     register size_t length;
 34 {
 35     register char *dst = dst0;
 36     register const char *src = src0;
 37     register size_t t;
 38 
 39     if (length == 0 || dst == src)        /* nothing to do */
 40         goto done;
 41 
 42     /*
 43      * Macros: loop-t-times; and loop-t-times, t>;0
 44      */
 45 #define    TLOOP(s) if (t) TLOOP1(s)
 46 #define    TLOOP1(s) do { s; } while (--t)
 47 
 48     if ((unsigned long)dst < (unsigned long)src) {
 49         /*
 50          * Copy forward.
 51          */
 52         t = (int)src;    /* only need low bits */
 53                 /*这样做的目的是由于下面的TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize)拷贝用的是32位为一个单位
 54                  *所以 这是的指针所指向的地址是最后两位是00(这个想法我还没验证)所以在匹配之前一定要将DES 和 SRC指针对齐到最后两位为00才行
 55                  */
 56         if ((t | (int)dst) & wmask) {  // 如果源和目标地址的最后两位不是00的话
 57             /* 对齐操作数???   
 58              * Try to align operands.  This cannot be done
 59              * unless the low bits match.
 60              */
 61             if ((t ^ (int)dst) & wmask || length < wsize)   
 62                 t = length;               //如果目标和源的地址最后两位参差不齐如 11 10 只能以Byte为单位拷贝
 63             else
 64                 t = wsize - (t & wmask);  //如果目标和源的地址最后两位如 10 10相等的话 把他们同时移到00来做 
 65             length -= t;
 66             TLOOP1(*dst++ = *src++);
 67         }
 68         /*
 69          * Copy whole words, then mop up any trailing bytes.
 70          */
 71         t = length / wsize;
 72         TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
 73         t = length & wmask;
 74         TLOOP(*dst++ = *src++);
 75     } else {
 76         /*
 77          * Copy backwards.  Otherwise essentially the same.
 78          * Alignment works as before, except that it takes
 79          * (t&wmask) bytes to align, not wsize-(t&wmask).
 80          */
 81         src += length;
 82         dst += length;
 83         t = (int)src;
 84         if ((t | (int)dst) & wmask) {
 85             if ((t ^ (int)dst) & wmask || length <= wsize)
 86                 t = length;
 87             else
 88                 t &= wmask;
 89             length -= t;
 90             TLOOP1(*--dst = *--src);
 91         }
 92         t = length / wsize;
 93         TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
 94         t = length & wmask;
 95         TLOOP(*--dst = *--src);
 96     }
 97 done:
 98 #if defined(MEMCOPY) || defined(MEMMOVE)
 99     return (dst0);
100 #else
101     return;
102 #endif
103 }

BSD的memcpy是经过优化的代码,主要是从SRC到DES的赋值操作时,使用了WORD(也就是INT)型指针,每次拷贝32位。他正好符合CACHE中32位的原则,效率比较高。大概是8位赋值的效率的好几倍。
   但是计算机架构中,数据项只能存在于于地址是数据项的大小的整数倍上,如DOUBLE型只能存在于8的整数倍如8008而不能存在于1006的地址上,如果跨界存取就有可能使原子数据项跨越一个页或CACHE的边界,不但会影响拷贝性能,严重时还会产生BUS ERROR(core dumped)的错误,所以在使用WORD指针前一定要将DES和SRC指针对齐到被4(sizeof(int) = 4 对于32位系统而言) 整除的位置。但如果DES和SRC的最后两位不相等的话,不管怎么移都不可能保证DES和SRC指针移动相等的长度后都可以被4整除,所以这时只能采用每8位拷贝一次,只能采用CHAR 型指针。
posted on 2009-07-01 10:41 newstar 阅读(692) 评论(0)  编辑 收藏 引用
只有注册用户登录后才能发表评论。