Changeset 47acd58 in mainline for uspace/lib/libc/generic/string.c


Ignore:
Timestamp:
2008-12-23T16:04:23Z (15 years ago)
Author:
Jiri Svoboda <jirik.svoboda@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
6b080e54
Parents:
7c64e23
Message:

Rewrite memcpy() in C library. Now copies congruent blocks fast, not just aligned blocks.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/libc/generic/string.c

    r7c64e23 r47acd58  
    7575}
    7676
     77/** Copy memory block. */
    7778void *memcpy(void *dst, const void *src, size_t n)
    7879{
    79         int i, j;
    80 
    81         if (((long) dst & (sizeof(long) - 1)) ||
    82             ((long) src & (sizeof(long) - 1)))
     80        size_t i;
     81        size_t mod, fill;
     82        size_t word_size;
     83        size_t n_words;
     84
     85        const unsigned long *srcw;
     86        unsigned long *dstw;
     87        const uint8_t *srcb;
     88        uint8_t *dstb;
     89
     90        word_size = sizeof(unsigned long);
     91
     92        /*
     93         * Are source and destination addresses congruent modulo word_size?
     94         * If not, use unaligned_memcpy().
     95         */
     96
     97        if (((uintptr_t) dst & (word_size - 1)) !=
     98            ((uintptr_t) src & (word_size - 1)))
    8399                return unaligned_memcpy(dst, src, n);
    84100
    85         for (i = 0; i < n / sizeof(unsigned long); i++)
    86                 ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
    87                
    88         for (j = 0; j < n % sizeof(unsigned long); j++)
    89                 ((unsigned char *) (((unsigned long *) dst) + i))[j] =
    90                     ((unsigned char *) (((unsigned long *) src) + i))[j];
    91                
    92         return (char *) dst;
     101        /*
     102         * mod is the address modulo word size. fill is the length of the
     103         * initial buffer segment before the first word boundary.
     104         * If the buffer is very short, use unaligned_memcpy(), too.
     105         */
     106
     107        mod = (uintptr_t) dst & (word_size - 1);
     108        fill = word_size - mod;
     109        if (fill > n) fill = n;
     110
     111        /* Copy the initial segment. */
     112
     113        srcb = src;
     114        dstb = dst;
     115
     116        i = fill;
     117        while (i-- > 0)
     118                *dstb++ = *srcb++;
     119
     120        /* Compute remaining length. */
     121
     122        n -= fill;
     123        if (n == 0) return dst;
     124
     125        /* Pointers to aligned segment. */
     126
     127        dstw = (unsigned long *) dstb;
     128        srcw = (const unsigned long *) srcb;
     129
     130        n_words = n / word_size;        /* Number of whole words to copy. */
     131        n -= n_words * word_size;       /* Remaining bytes at the end. */
     132
     133        /* "Fast" copy. */
     134        i = n_words;
     135        while (i-- > 0)
     136                *dstw++ = *srcw++;
     137
     138        /*
     139         * Copy the rest.
     140         */
     141
     142        srcb = (const uint8_t *) srcw;
     143        dstb = (uint8_t *) dstw;
     144
     145        i = n;
     146        while (i-- > 0)
     147                *dstb++ = *srcb++;
     148
     149        return dst;
    93150}
    94151
Note: See TracChangeset for help on using the changeset viewer.