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 <<memmove>>---move possibly overlapping memory 35 36 INDEX 37 memmove 38 39 ANSI_SYNOPSIS 40 #include <string.h> 41 void *memmove(void *<[dst]>, const void *<[src]>, size_t <[length]>); 42 43 TRAD_SYNOPSIS 44 #include <string.h> 45 void *memmove(<[dst]>, <[src]>, <[length]>) 46 void *<[dst]>; 47 void *<[src]>; 48 size_t <[length]>; 49 50 DESCRIPTION 51 This function moves <[length]> characters from the block of 52 memory starting at <<*<[src]>>> to the memory starting at 53 <<*<[dst]>>>. <<memmove>> reproduces the characters correctly 54 at <<*<[dst]>>> even if the two areas overlap. 55 56 RETURNS 57 The function returns <[dst]> as passed. 58 59 PORTABILITY 60 <<memmove>> is ANSI C. 61 62 <<memmove>> requires no supporting OS subroutines. 63 64 QUICKREF 65 memmove ansi pure 66 */ 67 68 #include <string.h> 69 #include "_ansi.h" 70 #include <stddef.h> 71 #include <limits.h> 72 73 /* Nonzero if either X or Y is not aligned on a "long" boundary. */ 74 #define UNALIGNED(X, Y) \ 75 (((long)X & (sizeof(long) - 1)) | ((long)Y & (sizeof(long) - 1))) 76 77 /* How many bytes are copied each iteration of the 4X unrolled loop. */ 78 #define BIGBLOCKSIZE (sizeof(long) << 2) 79 80 /* How many bytes are copied each iteration of the word copy loop. */ 81 #define LITTLEBLOCKSIZE (sizeof(long)) 82 83 /* Threshhold for punting to the byte copier. */ 84 #define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE) 85 86 /* SUPPRESS 20 */ 87 _PTR 88 _DEFUN(memmove, (dst_void, src_void, length), _PTR dst_void _AND _CONST _PTR 89 src_void _AND size_t length) 90 { 91 #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) 92 char *dst = dst_void; 93 _CONST char *src = src_void; 94 95 if (src < dst && dst < src + length) { 96 /* Have to copy backwards */ 97 src += length; 98 dst += length; 99 while (length--) 100 *--dst = *--src; 101 } else { 102 while (length--) 103 *dst++ = *src++; 104 } 105 106 return dst_void; 107 #else 108 char *dst = dst_void; 109 _CONST char *src = src_void; 110 long *aligned_dst; 111 _CONST long *aligned_src; 112 113 if (src < dst && dst < src + length) { 114 /* Destructive overlap...have to copy backwards */ 115 src += length; 116 dst += length; 117 while (length--) 118 *--dst = *--src; 119 } else { 120 /* 121 * Use optimizing algorithm for a non-destructive copy to 122 * closely match memcpy. If the size is small or either SRC or 123 * DST is unaligned, then punt into the byte copy loop. This 124 * should be rare. 125 */ 126 if (!TOO_SMALL(length) && !UNALIGNED(src, dst)) { 127 aligned_dst = (long *)dst; 128 aligned_src = (long *)src; 129 130 /* Copy 4X long words at a time if possible. */ 131 while (length >= BIGBLOCKSIZE) { 132 *aligned_dst++ = *aligned_src++; 133 *aligned_dst++ = *aligned_src++; 134 *aligned_dst++ = *aligned_src++; 135 *aligned_dst++ = *aligned_src++; 136 length -= BIGBLOCKSIZE; 137 } 138 139 /* Copy one long word at a time if possible. */ 140 while (length >= LITTLEBLOCKSIZE) { 141 *aligned_dst++ = *aligned_src++; 142 length -= LITTLEBLOCKSIZE; 143 } 144 145 /* Pick up any residual with a byte copier. */ 146 dst = (char *)aligned_dst; 147 src = (char *)aligned_src; 148 } 149 150 while (length--) 151 *dst++ = *src++; 152 } 153 154 return dst_void; 155 #endif /* not PREFER_SIZE_OVER_SPEED */ 156 } 157