浏览代码

introduce custom memcpy for realloc's

Ioannis Koutras 12 年之前
父节点
当前提交
149a7774e2
共有 8 个文件被更改,包括 432 次插入105 次删除
  1. 63 0
      contrib/memcpy/include/memcpy.h
  2. 348 0
      contrib/memcpy/src/memcpy.c
  3. 0 32
      private-include/memmove.h
  4. 16 2
      src/CMakeLists.txt
  5. 2 2
      src/bitmap/realloc.c
  6. 1 1
      src/freelist/realloc.c
  7. 0 67
      src/memmove.c
  8. 2 1
      src/realloc.c

+ 63 - 0
contrib/memcpy/include/memcpy.h

@@ -0,0 +1,63 @@
+/********************************************************************
+ ** File:     memcpy.h
+ **
+ ** Copyright (C) 2005 Daniel Vik
+ **
+ ** This software is provided 'as-is', without any express or implied
+ ** warranty. In no event will the authors be held liable for any
+ ** damages arising from the use of this software.
+ ** Permission is granted to anyone to use this software for any
+ ** purpose, including commercial applications, and to alter it and
+ ** redistribute it freely, subject to the following restrictions:
+ **
+ ** 1. The origin of this software must not be misrepresented; you
+ **    must not claim that you wrote the original software. If you
+ **    use this software in a product, an acknowledgment in the
+ **    use this software in a product, an acknowledgment in the
+ **    product documentation would be appreciated but is not
+ **    required.
+ **
+ ** 2. Altered source versions must be plainly marked as such, and
+ **    must not be misrepresented as being the original software.
+ **
+ ** 3. This notice may not be removed or altered from any source
+ **    distribution.
+ **
+ **
+ ** Description: Implementation of the standard library function memcpy.
+ **             This implementation of memcpy() is ANSI-C89 compatible.
+ **
+ *******************************************************************/
+
+
+/********************************************************************
+ ** Includes for size_t definition
+ *******************************************************************/
+
+#include <stddef.h>
+
+
+/********************************************************************
+ **
+ ** void *memcpy(void *dest, const void *src, size_t count)
+ **
+ ** Args:     dest    - pointer to destination buffer
+ **           src     - pointer to source buffer
+ **           count   - number of bytes to copy
+ **
+ ** Return:   A pointer to destination buffer
+ **
+ ** Purpose:  Copies count bytes from src to dest. No overlap check
+ **           is performed.
+ **
+ *******************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void *memcpy(void *dest, const void *src, size_t count);
+
+#ifdef __cplusplus
+}
+#endif

+ 348 - 0
contrib/memcpy/src/memcpy.c

@@ -0,0 +1,348 @@
+/********************************************************************
+ ** File:     memcpy.c
+ **
+ ** Copyright (C) 1999-2010 Daniel Vik
+ **
+ ** This software is provided 'as-is', without any express or implied
+ ** warranty. In no event will the authors be held liable for any
+ ** damages arising from the use of this software.
+ ** Permission is granted to anyone to use this software for any
+ ** purpose, including commercial applications, and to alter it and
+ ** redistribute it freely, subject to the following restrictions:
+ **
+ ** 1. The origin of this software must not be misrepresented; you
+ **    must not claim that you wrote the original software. If you
+ **    use this software in a product, an acknowledgment in the
+ **    use this software in a product, an acknowledgment in the
+ **    product documentation would be appreciated but is not
+ **    required.
+ **
+ ** 2. Altered source versions must be plainly marked as such, and
+ **    must not be misrepresented as being the original software.
+ **
+ ** 3. This notice may not be removed or altered from any source
+ **    distribution.
+ **
+ **
+ ** Description: Implementation of the standard library function memcpy.
+ **             This implementation of memcpy() is ANSI-C89 compatible.
+ **
+ **             The following configuration options can be set:
+ **
+ **           LITTLE_ENDIAN   - Uses processor with little endian
+ **                             addressing. Default is big endian.
+ **
+ **           PRE_INC_PTRS    - Use pre increment of pointers.
+ **                             Default is post increment of
+ **                             pointers.
+ **
+ **           INDEXED_COPY    - Copying data using array indexing.
+ **                             Using this option, disables the
+ **                             PRE_INC_PTRS option.
+ **
+ **           MEMCPY_64BIT    - Compiles memcpy for 64 bit 
+ **                             architectures
+ **
+ **
+ ** Best Settings:
+ **
+ ** Intel x86:  LITTLE_ENDIAN and INDEXED_COPY
+ **
+ *******************************************************************/
+
+
+
+/********************************************************************
+ ** Configuration definitions.
+ *******************************************************************/
+
+#define LITTLE_ENDIAN
+#define INDEXED_COPY
+
+
+/********************************************************************
+ ** Includes for size_t definition
+ *******************************************************************/
+
+#include <stddef.h>
+
+#include "memcpy.h"
+
+
+/********************************************************************
+ ** Typedefs
+ *******************************************************************/
+
+typedef unsigned char       UInt8;
+typedef unsigned short      UInt16;
+typedef unsigned int        UInt32;
+#ifdef _WIN32
+typedef unsigned __int64    UInt64;
+#else
+typedef unsigned long long  UInt64;
+#endif
+
+#ifdef MEMCPY_64BIT
+typedef UInt64              UIntN;
+#define TYPE_WIDTH          8L
+#else
+typedef UInt32              UIntN;
+#define TYPE_WIDTH          4L
+#endif
+
+
+/********************************************************************
+ ** Remove definitions when INDEXED_COPY is defined.
+ *******************************************************************/
+
+#if defined (INDEXED_COPY)
+#if defined (PRE_INC_PTRS)
+#undef PRE_INC_PTRS
+#endif /*PRE_INC_PTRS*/
+#endif /*INDEXED_COPY*/
+
+
+
+/********************************************************************
+ ** Definitions for pre and post increment of pointers.
+ *******************************************************************/
+
+#if defined (PRE_INC_PTRS)
+
+#define START_VAL(x)            (x)--
+#define INC_VAL(x)              *++(x)
+#define CAST_TO_U8(p, o)        ((UInt8*)p + o + TYPE_WIDTH)
+#define WHILE_DEST_BREAK        (TYPE_WIDTH - 1)
+#define PRE_LOOP_ADJUST         - (TYPE_WIDTH - 1)
+#define PRE_SWITCH_ADJUST       + 1
+
+#else /*PRE_INC_PTRS*/
+
+#define START_VAL(x)
+#define INC_VAL(x)              *(x)++
+#define CAST_TO_U8(p, o)        ((UInt8*)p + o)
+#define WHILE_DEST_BREAK        0
+#define PRE_LOOP_ADJUST
+#define PRE_SWITCH_ADJUST
+
+#endif /*PRE_INC_PTRS*/
+
+
+
+/********************************************************************
+ ** Definitions for endians
+ *******************************************************************/
+
+#if defined (LITTLE_ENDIAN)
+
+#define SHL >>
+#define SHR <<
+
+#else /* LITTLE_ENDIAN */
+
+#define SHL <<
+#define SHR >>
+
+#endif /* LITTLE_ENDIAN */
+
+
+
+/********************************************************************
+ ** Macros for copying words of  different alignment.
+ ** Uses incremening pointers.
+ *******************************************************************/
+
+#define CP_INCR() {                         \
+    INC_VAL(dstN) = INC_VAL(srcN);          \
+}
+
+#define CP_INCR_SH(shl, shr) {              \
+    dstWord   = srcWord SHL shl;            \
+    srcWord   = INC_VAL(srcN);              \
+    dstWord  |= srcWord SHR shr;            \
+    INC_VAL(dstN) = dstWord;                \
+}
+
+
+
+/********************************************************************
+ ** Macros for copying words of  different alignment.
+ ** Uses array indexes.
+ *******************************************************************/
+
+#define CP_INDEX(idx) {                     \
+    dstN[idx] = srcN[idx];                  \
+}
+
+#define CP_INDEX_SH(x, shl, shr) {          \
+    dstWord   = srcWord SHL shl;            \
+    srcWord   = srcN[x];                    \
+    dstWord  |= srcWord SHR shr;            \
+    dstN[x]  = dstWord;                     \
+}
+
+
+
+/********************************************************************
+ ** Macros for copying words of different alignment.
+ ** Uses incremening pointers or array indexes depending on
+ ** configuration.
+ *******************************************************************/
+
+#if defined (INDEXED_COPY)
+
+#define CP(idx)               CP_INDEX(idx)
+#define CP_SH(idx, shl, shr)  CP_INDEX_SH(idx, shl, shr)
+
+#define INC_INDEX(p, o)       ((p) += (o))
+
+#else /* INDEXED_COPY */
+
+#define CP(idx)               CP_INCR()
+#define CP_SH(idx, shl, shr)  CP_INCR_SH(shl, shr)
+
+#define INC_INDEX(p, o)
+
+#endif /* INDEXED_COPY */
+
+
+#define COPY_REMAINING(count) {                                     \
+    START_VAL(dst8);                                                \
+    START_VAL(src8);                                                \
+                                                                    \
+    switch (count) {                                                \
+    case 7: INC_VAL(dst8) = INC_VAL(src8);                          \
+    case 6: INC_VAL(dst8) = INC_VAL(src8);                          \
+    case 5: INC_VAL(dst8) = INC_VAL(src8);                          \
+    case 4: INC_VAL(dst8) = INC_VAL(src8);                          \
+    case 3: INC_VAL(dst8) = INC_VAL(src8);                          \
+    case 2: INC_VAL(dst8) = INC_VAL(src8);                          \
+    case 1: INC_VAL(dst8) = INC_VAL(src8);                          \
+    case 0:                                                         \
+    default: break;                                                 \
+    }                                                               \
+}
+
+#define COPY_NO_SHIFT() {                                           \
+    UIntN* dstN = (UIntN*)(dst8 PRE_LOOP_ADJUST);                   \
+    UIntN* srcN = (UIntN*)(src8 PRE_LOOP_ADJUST);                   \
+    size_t length = count / TYPE_WIDTH;                             \
+                                                                    \
+    while (length & 7) {                                            \
+        CP_INCR();                                                  \
+        length--;                                                   \
+    }                                                               \
+                                                                    \
+    length /= 8;                                                    \
+                                                                    \
+    while (length--) {                                              \
+        CP(0);                                                      \
+        CP(1);                                                      \
+        CP(2);                                                      \
+        CP(3);                                                      \
+        CP(4);                                                      \
+        CP(5);                                                      \
+        CP(6);                                                      \
+        CP(7);                                                      \
+                                                                    \
+        INC_INDEX(dstN, 8);                                         \
+        INC_INDEX(srcN, 8);                                         \
+    }                                                               \
+                                                                    \
+    src8 = CAST_TO_U8(srcN, 0);                                     \
+    dst8 = CAST_TO_U8(dstN, 0);                                     \
+                                                                    \
+    COPY_REMAINING(count & (TYPE_WIDTH - 1));                       \
+                                                                    \
+    return dest;                                                    \
+}
+
+
+
+#define COPY_SHIFT(shift) {                                         \
+    UIntN* dstN  = (UIntN*)((((UIntN)dst8) PRE_LOOP_ADJUST) &       \
+                             ~(TYPE_WIDTH - 1));                    \
+    UIntN* srcN  = (UIntN*)((((UIntN)src8) PRE_LOOP_ADJUST) &       \
+                             ~(TYPE_WIDTH - 1));                    \
+    size_t length  = count / TYPE_WIDTH;                            \
+    UIntN srcWord = INC_VAL(srcN);                                  \
+    UIntN dstWord;                                                  \
+                                                                    \
+    while (length & 7) {                                            \
+        CP_INCR_SH(8 * shift, 8 * (TYPE_WIDTH - shift));            \
+        length--;                                                   \
+    }                                                               \
+                                                                    \
+    length /= 8;                                                    \
+                                                                    \
+    while (length--) {                                              \
+        CP_SH(0, 8 * shift, 8 * (TYPE_WIDTH - shift));              \
+        CP_SH(1, 8 * shift, 8 * (TYPE_WIDTH - shift));              \
+        CP_SH(2, 8 * shift, 8 * (TYPE_WIDTH - shift));              \
+        CP_SH(3, 8 * shift, 8 * (TYPE_WIDTH - shift));              \
+        CP_SH(4, 8 * shift, 8 * (TYPE_WIDTH - shift));              \
+        CP_SH(5, 8 * shift, 8 * (TYPE_WIDTH - shift));              \
+        CP_SH(6, 8 * shift, 8 * (TYPE_WIDTH - shift));              \
+        CP_SH(7, 8 * shift, 8 * (TYPE_WIDTH - shift));              \
+                                                                    \
+        INC_INDEX(dstN, 8);                                         \
+        INC_INDEX(srcN, 8);                                         \
+    }                                                               \
+                                                                    \
+    src8 = CAST_TO_U8(srcN, (shift - TYPE_WIDTH));                  \
+    dst8 = CAST_TO_U8(dstN, 0);                                     \
+                                                                    \
+    COPY_REMAINING(count & (TYPE_WIDTH - 1));                       \
+                                                                    \
+    return dest;                                                    \
+}
+
+
+/********************************************************************
+ **
+ ** void *memcpy(void *dest, const void *src, size_t count)
+ **
+ ** Args:     dest        - pointer to destination buffer
+ **           src         - pointer to source buffer
+ **           count       - number of bytes to copy
+ **
+ ** Return:   A pointer to destination buffer
+ **
+ ** Purpose:  Copies count bytes from src to dest. 
+ **           No overlap check is performed.
+ **
+ *******************************************************************/
+
+void *memcpy(void *dest, const void *src, size_t count) 
+{
+    UInt8* dst8 = (UInt8*)dest;
+    UInt8* src8 = (UInt8*)src;
+
+    if (count < 8) {
+        COPY_REMAINING(count);
+        return dest;
+    }
+
+    START_VAL(dst8);
+    START_VAL(src8);
+
+    while (((UIntN)dst8 & (TYPE_WIDTH - 1)) != WHILE_DEST_BREAK) {
+        INC_VAL(dst8) = INC_VAL(src8);
+        count--;
+    }
+
+    switch ((((UIntN)src8) PRE_SWITCH_ADJUST) & (TYPE_WIDTH - 1)) {
+    case 0: COPY_NO_SHIFT(); break;
+    case 1: COPY_SHIFT(1);   break;
+    case 2: COPY_SHIFT(2);   break;
+    case 3: COPY_SHIFT(3);   break;
+#if TYPE_WIDTH > 4
+    case 4: COPY_SHIFT(4);   break;
+    case 5: COPY_SHIFT(5);   break;
+    case 6: COPY_SHIFT(6);   break;
+    case 7: COPY_SHIFT(7);   break;
+#endif
+    }
+
+    return dest;
+}

+ 0 - 32
private-include/memmove.h

@@ -1,32 +0,0 @@
-/*
- *   Copyright Institute of Communication and Computer Systems (ICCS) 
- *
- *   Licensed under the Apache License, Version 2.0 (the "License");
- *   you may not use this file except in compliance with the License.
- *   You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- *   Unless required by applicable law or agreed to in writing, software
- *   distributed under the License is distributed on an "AS IS" BASIS,
- *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *   See the License for the specific language governing permissions and
- *   limitations under the License.
- *
- */
-
-/**
- * @file   memmove.h
- * @author Ioannis Koutras (joko@microlab.ntua.gr)
- * @date   October 2012
- * @brief  memmove function
- */
-
-#ifndef MEMMOVE_H
-#define MEMMOVE_H
-
-#include <stddef.h>
-
-void * memmove(void *destination, void *source, size_t count);
-
-#endif /* MEMMOVE_H */

+ 16 - 2
src/CMakeLists.txt

@@ -128,7 +128,7 @@ elseif(RAW_BLOCKS_TYPE STREQUAL "bitmap")
     )
 
   if(WITH_REALLOC)
-    set(dmmlib_SRCS ${dmmlib_SRCS} bitmap/realloc.c memmove.c)
+    set(dmmlib_SRCS ${dmmlib_SRCS} bitmap/realloc.c)
   endif(WITH_REALLOC)
 
   if(WITH_DEBUG)
@@ -177,7 +177,21 @@ if(NOT STATS STREQUAL "none")
 endif(NOT STATS STREQUAL "none")
 
 if(WITH_REALLOC)
-  set(dmmlib_SRCS ${dmmlib_SRCS} realloc.c)
+  set(DMMLIB_PRIVATE_INCLUDE_DIRS
+    ${DMMLIB_PRIVATE_INCLUDE_DIRS}
+    ${CMAKE_SOURCE_DIR}/contrib/memcpy/include
+  )
+
+  # memcpy needs the following define flag on 64-bit architectures
+  if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+    add_definitions(-DMEMCPY_64BIT)
+  endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
+
+  set(dmmlib_SRCS
+    ${dmmlib_SRCS}
+    realloc.c
+    ${CMAKE_SOURCE_DIR}/contrib/memcpy/src/memcpy.c
+  )
 endif(WITH_REALLOC)
 
 if(WITH_CALLOC)

+ 2 - 2
src/bitmap/realloc.c

@@ -25,7 +25,7 @@
 #include "bitmap/bitmap.h"
 #include "dmmlib/dmmlib.h"
 
-#include "memmove.h"
+#include "memcpy.h"
 
 #include "locks.h"
 
@@ -70,7 +70,7 @@ void * bitmap_realloc(bitmap_rb_t *raw_block, void * ptr,
         }
 
         if(ret != NULL) {
-            memmove(ret, ptr, old_size);
+            memcpy(ret, ptr, old_size);
             lock_raw_block(rb);
             bitmap_free(raw_block, ptr);
             unlock_raw_block(rb);

+ 1 - 1
src/freelist/realloc.c

@@ -25,7 +25,7 @@
 #include "dmmlib/freelist/freelist.h"
 #include "dmmlib/freelist/block_header.h"
 
-#include <string.h>
+#include "memcpy.h"
 
 #ifdef HAVE_LOCKS
 #include "dmmlib/raw_block.h"

+ 0 - 67
src/memmove.c

@@ -1,67 +0,0 @@
-/*
- *   Copyright Institute of Communication and Computer Systems (ICCS) 
- *
- *   Licensed under the Apache License, Version 2.0 (the "License");
- *   you may not use this file except in compliance with the License.
- *   You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- *   Unless required by applicable law or agreed to in writing, software
- *   distributed under the License is distributed on an "AS IS" BASIS,
- *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *   See the License for the specific language governing permissions and
- *   limitations under the License.
- *
- */
-
-/**
- * @file   memmove.c
- * @author Ioannis Koutras
- * @date   October 2012
- * @brief  memmove() implementation
- */
-
-#include "memmove.h"
-
-/** Copies n bytes from string s2 to string s1. The two strings may overlap; the
- * copy is always done in a non-destructive manner.
- * 
- * Original code at:
- * http://discuss.joelonsoftware.com/default.asp?interview.11.437419.13
- */
-void * memmove(void *destination, void *source, size_t count) {
-    size_t i = 0;
-
-    char *src = (char *)source;
-    char *dest = (char *)destination;
-    void * ptr = dest;
-
-    char * src_beg = src;
-    char * src_end = src_beg + count;
-
-    char * dest_beg = dest;
-    char * dest_end = dest_beg + count;
-    if(src == dest) {
-        return ptr;
-    }
-
-    if((dest_beg >= src_beg && dest_beg <= src_end) || (dest_end >= src_beg && dest_end <= src_end)) {
-
-        //Copy from higher addresses to lower addresses
-        for( i = count ; i > 0 ; i--)
-        {
-            *(dest + i) = *(src + i);
-        }
-
-        return ptr;
-    }
-
-    //No overlap, copy from lower addresses to higher addresses
-    for( i = 0 ; i < count ; i++)
-    {
-        *(dest + i) = *(src + i);
-    }
-
-    return ptr;
-}

+ 2 - 1
src/realloc.c

@@ -31,9 +31,10 @@
 
 #include "release_memory.h"
 #include <sys/mman.h>
-#include <string.h>
 #include <inttypes.h>
 
+#include "memcpy.h"
+
 #ifdef WITH_DEBUG
 #include "debug.h"
 #endif /* WITH_DEBUG */