Subversion Repositories HelenOS

Rev

Rev 3732 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2005 Martin Decky
  3.  * Copyright (c) 2008 Jiri Svoboda
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  *
  10.  * - Redistributions of source code must retain the above copyright
  11.  *   notice, this list of conditions and the following disclaimer.
  12.  * - Redistributions in binary form must reproduce the above copyright
  13.  *   notice, this list of conditions and the following disclaimer in the
  14.  *   documentation and/or other materials provided with the distribution.
  15.  * - The name of the author may not be used to endorse or promote products
  16.  *   derived from this software without specific prior written permission.
  17.  *
  18.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  19.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  20.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  21.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  22.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  23.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28.  */
  29.  
  30. /** @addtogroup libc
  31.  * @{
  32.  */
  33. /** @file
  34.  */
  35.  
  36. #include <mem.h>
  37. #include <stdlib.h>
  38. #include <sys/types.h>
  39.  
  40. /** Fill memory block with a constant value. */
  41. void *memset(void *dest, int b, size_t n)
  42. {
  43.     char *pb;
  44.     unsigned long *pw;
  45.     size_t word_size;
  46.     size_t n_words;
  47.  
  48.     unsigned long pattern;
  49.     size_t i;
  50.     size_t fill;
  51.  
  52.     /* Fill initial segment. */
  53.     word_size = sizeof(unsigned long);
  54.     fill = word_size - ((uintptr_t) dest & (word_size - 1));
  55.     if (fill > n) fill = n;
  56.  
  57.     pb = dest;
  58.  
  59.     i = fill;
  60.     while (i-- != 0)
  61.         *pb++ = b;
  62.  
  63.     /* Compute remaining size. */
  64.     n -= fill;
  65.     if (n == 0) return dest;
  66.  
  67.     n_words = n / word_size;
  68.     n = n % word_size;
  69.     pw = (unsigned long *) pb;
  70.  
  71.     /* Create word-sized pattern for aligned segment. */
  72.     pattern = 0;
  73.     i = word_size;
  74.     while (i-- != 0)
  75.         pattern = (pattern << 8) | (uint8_t) b;
  76.  
  77.     /* Fill aligned segment. */
  78.     i = n_words;
  79.     while (i-- != 0)
  80.         *pw++ = pattern;
  81.  
  82.     pb = (char *) pw;
  83.  
  84.     /* Fill final segment. */
  85.     i = n;
  86.     while (i-- != 0)
  87.         *pb++ = b;
  88.  
  89.     return dest;
  90. }
  91.  
  92. struct along {
  93.     unsigned long n;
  94. } __attribute__ ((packed));
  95.  
  96. static void *unaligned_memcpy(void *dst, const void *src, size_t n)
  97. {
  98.     unsigned int i, j;
  99.     struct along *adst = dst;
  100.     const struct along *asrc = src;
  101.  
  102.     for (i = 0; i < n / sizeof(unsigned long); i++)
  103.         adst[i].n = asrc[i].n;
  104.        
  105.     for (j = 0; j < n % sizeof(unsigned long); j++)
  106.         ((unsigned char *) (((unsigned long *) dst) + i))[j] =
  107.             ((unsigned char *) (((unsigned long *) src) + i))[j];
  108.        
  109.     return (char *) dst;
  110. }
  111.  
  112. /** Copy memory block. */
  113. void *memcpy(void *dst, const void *src, size_t n)
  114. {
  115.     size_t i;
  116.     size_t mod, fill;
  117.     size_t word_size;
  118.     size_t n_words;
  119.  
  120.     const unsigned long *srcw;
  121.     unsigned long *dstw;
  122.     const uint8_t *srcb;
  123.     uint8_t *dstb;
  124.  
  125.     word_size = sizeof(unsigned long);
  126.  
  127.     /*
  128.      * Are source and destination addresses congruent modulo word_size?
  129.      * If not, use unaligned_memcpy().
  130.      */
  131.  
  132.     if (((uintptr_t) dst & (word_size - 1)) !=
  133.         ((uintptr_t) src & (word_size - 1)))
  134.         return unaligned_memcpy(dst, src, n);
  135.  
  136.     /*
  137.      * mod is the address modulo word size. fill is the length of the
  138.      * initial buffer segment before the first word boundary.
  139.      * If the buffer is very short, use unaligned_memcpy(), too.
  140.      */
  141.  
  142.     mod = (uintptr_t) dst & (word_size - 1);
  143.     fill = word_size - mod;
  144.     if (fill > n) fill = n;
  145.  
  146.     /* Copy the initial segment. */
  147.  
  148.     srcb = src;
  149.     dstb = dst;
  150.  
  151.     i = fill;
  152.     while (i-- != 0)
  153.         *dstb++ = *srcb++;
  154.  
  155.     /* Compute remaining length. */
  156.  
  157.     n -= fill;
  158.     if (n == 0) return dst;
  159.  
  160.     /* Pointers to aligned segment. */
  161.  
  162.     dstw = (unsigned long *) dstb;
  163.     srcw = (const unsigned long *) srcb;
  164.  
  165.     n_words = n / word_size;    /* Number of whole words to copy. */
  166.     n -= n_words * word_size;   /* Remaining bytes at the end. */
  167.  
  168.     /* "Fast" copy. */
  169.     i = n_words;
  170.     while (i-- != 0)
  171.         *dstw++ = *srcw++;
  172.  
  173.     /*
  174.      * Copy the rest.
  175.      */
  176.  
  177.     srcb = (const uint8_t *) srcw;
  178.     dstb = (uint8_t *) dstw;
  179.  
  180.     i = n;
  181.     while (i-- != 0)
  182.         *dstb++ = *srcb++;
  183.  
  184.     return dst;
  185. }
  186.  
  187. /** Move memory block with possible overlapping. */
  188. void *memmove(void *dst, const void *src, size_t n)
  189. {
  190.     const uint8_t *sp;
  191.     uint8_t *dp;
  192.  
  193.     /* Nothing to do? */
  194.     if (src == dst)
  195.         return dst;
  196.  
  197.     /* Non-overlapping? */
  198.     if (dst >= src + n || src >= dst + n) {
  199.         return memcpy(dst, src, n);
  200.     }
  201.  
  202.     /* Which direction? */
  203.     if (src > dst) {
  204.         /* Forwards. */
  205.         sp = src;
  206.         dp = dst;
  207.  
  208.         while (n-- != 0)
  209.             *dp++ = *sp++;
  210.     } else {
  211.         /* Backwards. */
  212.         sp = src + (n - 1);
  213.         dp = dst + (n - 1);
  214.  
  215.         while (n-- != 0)
  216.             *dp-- = *sp--;
  217.     }
  218.  
  219.     return dst;
  220. }
  221.  
  222. /** Compare two memory areas.
  223.  *
  224.  * @param s1        Pointer to the first area to compare.
  225.  * @param s2        Pointer to the second area to compare.
  226.  * @param len       Size of the first area in bytes. Both areas must have
  227.  *          the same length.
  228.  * @return      If len is 0, return zero. If the areas match, return
  229.  *          zero. Otherwise return non-zero.
  230.  */
  231. int bcmp(const char *s1, const char *s2, size_t len)
  232. {
  233.     for (; len && *s1++ == *s2++; len--)
  234.         ;
  235.     return len;
  236. }
  237.  
  238. /** @}
  239.  */
  240.