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 <<memcpy>>---copy memory regions 35 36 ANSI_SYNOPSIS 37 #include <string.h> 38 void* memcpy(void *<[out]>, const void *<[in]>, size_t <[n]>); 39 40 TRAD_SYNOPSIS 41 #include <string.h> 42 void *memcpy(<[out]>, <[in]>, <[n]> 43 void *<[out]>; 44 void *<[in]>; 45 size_t <[n]>; 46 47 DESCRIPTION 48 This function copies <[n]> bytes from the memory region 49 pointed to by <[in]> to the memory region pointed to by 50 <[out]>. 51 52 If the regions overlap, the behavior is undefined. 53 54 RETURNS 55 <<memcpy>> returns a pointer to the first byte of the <[out]> 56 region. 57 58 PORTABILITY 59 <<memcpy>> is ANSI C. 60 61 <<memcpy>> requires no supporting OS subroutines. 62 63 QUICKREF 64 memcpy ansi pure 65 */ 66 67 #include "_ansi.h" 68 #include <string.h> 69 70 /* Nonzero if either X or Y is not aligned on a "long" boundary. */ 71 #define UNALIGNED(X, Y) \ 72 (((long)X & (sizeof(long) - 1)) | ((long)Y & (sizeof(long) - 1))) 73 74 /* How many bytes are copied each iteration of the 4X unrolled loop. */ 75 #define BIGBLOCKSIZE (sizeof(long) << 2) 76 77 /* How many bytes are copied each iteration of the word copy loop. */ 78 #define LITTLEBLOCKSIZE (sizeof(long)) 79 80 /* Threshhold for punting to the byte copier. */ 81 #define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE) 82 83 _PTR 84 _DEFUN(memcpy, (dst0, src0, len0), _PTR dst0 _AND _CONST _PTR src0 _AND 85 size_t len0) 86 { 87 #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) 88 char *dst = (char *)dst0; 89 char *src = (char *)src0; 90 91 _PTR save = dst0; 92 93 while (len0--) 94 *dst++ = *src++; 95 96 return save; 97 #else 98 char *dst = dst0; 99 _CONST char *src = src0; 100 long *aligned_dst; 101 _CONST long *aligned_src; 102 103 /* If the size is small, or either SRC or DST is unaligned, 104 then punt into the byte copy loop. This should be rare. */ 105 if (!TOO_SMALL(len0) && !UNALIGNED(src, dst)) { 106 aligned_dst = (long *)dst; 107 aligned_src = (long *)src; 108 109 /* Copy 4X long words at a time if possible. */ 110 while (len0 >= BIGBLOCKSIZE) { 111 *aligned_dst++ = *aligned_src++; 112 *aligned_dst++ = *aligned_src++; 113 *aligned_dst++ = *aligned_src++; 114 *aligned_dst++ = *aligned_src++; 115 len0 -= BIGBLOCKSIZE; 116 } 117 118 /* Copy one long word at a time if possible. */ 119 while (len0 >= LITTLEBLOCKSIZE) { 120 *aligned_dst++ = *aligned_src++; 121 len0 -= LITTLEBLOCKSIZE; 122 } 123 124 /* Pick up any residual with a byte copier. */ 125 dst = (char *)aligned_dst; 126 src = (char *)aligned_src; 127 } 128 129 while (len0--) 130 *dst++ = *src++; 131 132 return dst0; 133 #endif /* not PREFER_SIZE_OVER_SPEED */ 134 } 135