Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2. FUNCTION
  3.         <<memset>>---set an area of memory
  4.  
  5. INDEX
  6.         memset
  7.  
  8. ANSI_SYNOPSIS
  9.         #include <string.h>
  10.         void *memset(void *<[dst]>, int <[c]>, size_t <[length]>);
  11.  
  12. TRAD_SYNOPSIS
  13.         #include <string.h>
  14.         void *memset(<[dst]>, <[c]>, <[length]>)
  15.         void *<[dst]>;
  16.         int <[c]>;
  17.         size_t <[length]>;
  18.  
  19. DESCRIPTION
  20.         This function converts the argument <[c]> into an unsigned
  21.         char and fills the first <[length]> characters of the array
  22.         pointed to by <[dst]> to the value.
  23.  
  24. RETURNS
  25.         <<memset>> returns the value of <[dst]>.
  26.  
  27. PORTABILITY
  28. <<memset>> is ANSI C.
  29.  
  30.     <<memset>> requires no supporting OS subroutines.
  31.  
  32. QUICKREF
  33.         memset ansi pure
  34. */
  35.  
  36. #include <string.h>
  37. #include "local.h"
  38.  
  39. #define LBLOCKSIZE (sizeof(long))
  40. #define UNALIGNED(X)   ((long)X & (LBLOCKSIZE - 1))
  41. #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
  42.  
  43. _PTR
  44. __inhibit_loop_to_libcall
  45. _DEFUN (memset, (m, c, n),
  46.         _PTR m _AND
  47.         int c _AND
  48.         size_t n)
  49. {
  50.   char *s = (char *) m;
  51.  
  52. #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
  53.   int i;
  54.   unsigned long buffer;
  55.   unsigned long *aligned_addr;
  56.   unsigned int d = c & 0xff;    /* To avoid sign extension, copy C to an
  57.                                    unsigned variable.  */
  58.  
  59.   while (UNALIGNED (s))
  60.     {
  61.       if (n--)
  62.         *s++ = (char) c;
  63.       else
  64.         return m;
  65.     }
  66.  
  67.   if (!TOO_SMALL (n))
  68.     {
  69.       /* If we get this far, we know that n is large and s is word-aligned. */
  70.       aligned_addr = (unsigned long *) s;
  71.  
  72.       /* Store D into each char sized location in BUFFER so that
  73.          we can set large blocks quickly.  */
  74.       buffer = (d << 8) | d;
  75.       buffer |= (buffer << 16);
  76.       for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
  77.         buffer = (buffer << i) | buffer;
  78.  
  79.       /* Unroll the loop.  */
  80.       while (n >= LBLOCKSIZE*4)
  81.         {
  82.           *aligned_addr++ = buffer;
  83.           *aligned_addr++ = buffer;
  84.           *aligned_addr++ = buffer;
  85.           *aligned_addr++ = buffer;
  86.           n -= 4*LBLOCKSIZE;
  87.         }
  88.  
  89.       while (n >= LBLOCKSIZE)
  90.         {
  91.           *aligned_addr++ = buffer;
  92.           n -= LBLOCKSIZE;
  93.         }
  94.       /* Pick up the remainder with a bytewise loop.  */
  95.       s = (char*)aligned_addr;
  96.     }
  97.  
  98. #endif /* not PREFER_SIZE_OVER_SPEED */
  99.  
  100.   while (n--)
  101.     *s++ = (char) c;
  102.  
  103.   return m;
  104. }
  105.