Forráskód Böngészése

Major rewriting of realloc() in order to be more versatile.

Ioannis Koutras 13 éve
szülő
commit
5029d1e625
1 módosított fájl, 92 hozzáadás és 12 törlés
  1. 92 12
      src/custom_realloc.c

+ 92 - 12
src/custom_realloc.c

@@ -18,21 +18,29 @@
 /**
  * \file    custom_realloc.c
  * \author  Ioannis Koutras (joko@microlab.ntua.gr)
- * \date    November, 2011
+ * \date    January, 2012
  *
  * \brief   Implementation of a function to change the size of an allocated
  * block.
  */
 
 #include <dmmlib/custom_realloc.h>
-#include <dmmlib/dmmlib.h>
 #include <dmmlib/initialize_allocator.h>
 #include "block_header.h"
 #ifndef WITH_MEMORY_SPACE_AWARENESS
 #include "other.h"
 #endif /* WITH_MEMORY_SPACE_AWARENESS */
+#if defined (SPLITTING_FIXED) || defined (SPLITTING_VARIABLE)
+#include "split.h"
+#endif /* SPLITTING_FIXED || SPLITTING_VARIABLE */
 
 /**
+ * Allocates a new block and copies the contents of the old block to the new
+ * block. No check is done if there is an old block!
+ */
+void * clean_realloc(allocator_t *allocator, heap_t *heap, void *ptr,
+        size_t size);
+/**
  * Copy a memory area
  */
 static void * custom_memcpy(void* dest, const void* src, size_t n) {
@@ -48,6 +56,19 @@ static void * custom_memcpy(void* dest, const void* src, size_t n) {
     return dest;
 }
 
+void * clean_realloc(allocator_t *allocator, heap_t *heap, void *ptr, 
+        size_t size) {
+    size_t old_size;
+    void *new_ptr;
+
+    old_size = get_size(ptr);
+    new_ptr = custom_ahmalloc(allocator, heap, size);
+    new_ptr = custom_memcpy(allocator, ptr, old_size);
+    custom_ahfree(allocator, heap, ptr);
+
+    return new_ptr;
+}
+
 /**
  * \details The realloc() function tries to change the size of the allocation
  * pointed to by ptr to size, and returns ptr. realloc() creates a new
@@ -57,9 +78,13 @@ static void * custom_memcpy(void* dest, const void* src, size_t n) {
  * malloc() for size bytes.
  */
 void * custom_ahrealloc(allocator_t *allocator, heap_t *heap, void *ptr, size_t size) {
-    void *new_ptr;
+    void *next_block;
     size_t old_size;
 
+#if defined (SPLITTING_FIXED) || defined (SPLITTING_VARIABLE)
+    size_t min_split_size;
+#endif /* (SPLITTING_FIXED) || (SPLITTING_VARIABLE) */
+
 #ifndef WITH_MEMORY_SPACE_AWARENESS
     int heap_id;
 
@@ -78,20 +103,75 @@ void * custom_ahrealloc(allocator_t *allocator, heap_t *heap, void *ptr, size_t
 
 #endif /* WITH_MEMORY_SPACE_AWARENESS */
 
-    new_ptr = custom_ahmalloc(allocator, heap, size);
-
     if(ptr != NULL) {
         old_size = get_size(ptr);
-        if(old_size < size) {
-            new_ptr = custom_memcpy(new_ptr, ptr, old_size);
+        if(old_size > size) {
+            /* The old size is bigger than the new, use the old block */
+
+            /* Try to split the currently allocated block */
+#if defined (SPLITTING_FIXED) || defined (SPLITTING_VARIABLE)
+#ifdef SPLITTING_FIXED
+            min_split_size = MIN_SPLITTING_SIZE;
+#endif /* SPLITTING_FIXED */
+#ifdef SPLITTING_VARIABLE
+            min_split_size = heap->dmm_knobs.min_split_size;
+#endif /* SPLITTING_VARIABLE */
+
+            if(old_size - size - HEADER_SIZE >= min_split_size) {
+                split(allocator, heap, ptr, size);
+            }
+#endif /* (SPLITTING_FIXED) || (SPLITTING_VARIABLE) */
+            return ptr;
         } else {
-            new_ptr = custom_memcpy(new_ptr, ptr, size);
-        }
-        custom_ahfree(allocator, heap, ptr);
-    }
+            /* The new size can't fit in the old box */
 
-    return new_ptr;
+            /* Check if the block next to the original as in the data layout
+             * can be used.
+             */
+            next_block = get_dlnext(allocator, ptr);
+            if(next_block != NULL) {
+#ifndef WITH_OWNERSHIP
+                if(is_free(next_block) == true) {
+#else /* WITH_OWNERSHIP */
+                if(is_free(next_block) == true
+                        && get_owner(next_block) == get_owner(ptr)) {
+#endif /* WITH_OWNERSHIP */
+                    if(size < old_size + get_size(next_block) + HEADER_SIZE) {
+                        remove_block_from_lists(&next_block, heap);
+                        if(allocator->border_ptr == next_block) {
+                            allocator->border_ptr = ptr;
+                        }
+                        set_size_and_used(allocator, ptr, size);
+
+#if defined (SPLITTING_FIXED) || defined (SPLITTING_VARIABLE)
+#ifdef SPLITTING_FIXED
+                        min_split_size = MIN_SPLITTING_SIZE;
+#endif /* SPLITTING_FIXED */
+#ifdef SPLITTING_VARIABLE
+                        min_split_size = heap->dmm_knobs.min_split_size;
+#endif /* SPLITTING_VARIABLE */
+
+                        if(old_size + get_size(next_block) - size >=
+                                min_split_size) {
+                            split(allocator, heap, ptr, size);
+                        }
+#endif /* (SPLITTING_FIXED) || (SPLITTING_VARIABLE) */
 
+                        return ptr;
+                    } else {
+                        return clean_realloc(allocator, heap, ptr, size);
+                    }
+                } else {
+                    return clean_realloc(allocator, heap, ptr, size);
+                }
+            } else {
+                return clean_realloc(allocator, heap, ptr, size);
+            }
+        }
+    } else {
+        /* ptr is NULL, call malloc() */
+        return custom_ahmalloc(allocator, heap, size);
+    }
 }
 
 #ifndef WITH_MEMORY_SPACE_AWARENESS