1 /* 2 * Copyright (c) 1994-2009 Red Hat, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its 16 * contributors may be used to endorse or promote products derived from this 17 * software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 FUNCTION 34 <<memset>>---set an area of memory 35 36 INDEX 37 memset 38 39 ANSI_SYNOPSIS 40 #include <string.h> 41 void *memset(void *<[dst]>, int <[c]>, size_t <[length]>); 42 43 TRAD_SYNOPSIS 44 #include <string.h> 45 void *memset(<[dst]>, <[c]>, <[length]>) 46 void *<[dst]>; 47 int <[c]>; 48 size_t <[length]>; 49 50 DESCRIPTION 51 This function converts the argument <[c]> into an unsigned 52 char and fills the first <[length]> characters of the array 53 pointed to by <[dst]> to the value. 54 55 RETURNS 56 <<memset>> returns the value of <[dst]>. 57 58 PORTABILITY 59 <<memset>> is ANSI C. 60 61 <<memset>> requires no supporting OS subroutines. 62 63 QUICKREF 64 memset ansi pure 65 */ 66 67 #include "_ansi.h" 68 #include <string.h> 69 70 #define LBLOCKSIZE (sizeof(long)) 71 #define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) 72 #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) 73 74 _PTR _DEFUN(memset, (m, c, n), _PTR m _AND int c _AND size_t n) 75 { 76 char *s = (char *)m; 77 78 #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) 79 int i; 80 unsigned long buffer; 81 unsigned long *aligned_addr; 82 unsigned int d = c & 0xff; /* To avoid sign extension, copy C to an 83 unsigned variable. */ 84 85 while (UNALIGNED(s)) { 86 if (n--) 87 *s++ = (char)c; 88 else 89 return m; 90 } 91 92 if (!TOO_SMALL(n)) { 93 /* 94 * If we get this far, we know that n is large and s is 95 * word-aligned. 96 */ 97 aligned_addr = (unsigned long *)s; 98 99 /* Store D into each char sized location in BUFFER so that 100 we can set large blocks quickly. */ 101 buffer = (d << 8) | d; 102 buffer |= (buffer << 16); 103 for (i = 32; i < LBLOCKSIZE * 8; i <<= 1) 104 buffer = (buffer << i) | buffer; 105 106 /* Unroll the loop. */ 107 while (n >= LBLOCKSIZE * 4) { 108 *aligned_addr++ = buffer; 109 *aligned_addr++ = buffer; 110 *aligned_addr++ = buffer; 111 *aligned_addr++ = buffer; 112 n -= 4 * LBLOCKSIZE; 113 } 114 115 while (n >= LBLOCKSIZE) { 116 *aligned_addr++ = buffer; 117 n -= LBLOCKSIZE; 118 } 119 /* Pick up the remainder with a bytewise loop. */ 120 s = (char *)aligned_addr; 121 } 122 #endif /* not PREFER_SIZE_OVER_SPEED */ 123 124 while (n--) 125 *s++ = (char)c; 126 127 return m; 128 } 129