Browse Source

realloc() implementation for big blocks

Ioannis Koutras 13 years ago
parent
commit
1aa71b9a42
1 changed files with 79 additions and 2 deletions
  1. 79 2
      src/realloc.c

+ 79 - 2
src/realloc.c

@@ -38,6 +38,11 @@
 #endif /* FL_RB_ONLY */
 
 #include "release_memory.h"
+#include <sys/mman.h>
+
+#include <string.h>
+
+#include "trace.h"
 
 void * realloc(void *ptr, size_t size) {
     raw_block_header_t *current_raw_block;
@@ -83,7 +88,79 @@ void * realloc(void *ptr, size_t size) {
                 ((char *)current_raw_block + sizeof(raw_block_header_t));
         
         return dmmlib_realloc(encapsulated_rb, ptr, size);
-    } else {
-        return NULL; // FIXME what about big blocks?
+
+    } else { /* This has to be a big block */
+
+        // The new size is checked and if it is smaller than the one from the
+        // original request, the remaining memory is simply released. If it is
+        // greater, a new big block is initialized, data is copied there and the
+        // old big block gets de-allocated.
+
+        current_raw_block = (raw_block_header_t *)((char *)ptr -
+                sizeof(raw_block_header_t));
+
+        size_t full_size = sizeof(raw_block_header_t) + size;
+
+        if(full_size <= current_raw_block->size) {
+
+            size_t remaining_size = current_raw_block->size - full_size;
+            current_raw_block->size = full_size;
+
+            // FIXME This is mmap-specific
+            munmap((void *)((char *)current_raw_block +
+                        current_raw_block->size), remaining_size);
+
+#ifdef WITH_ALLOCATOR_STATS
+            systemallocator.dmm_stats.total_mem_allocated -=
+                remaining_size;
+            TRACE_1("dmmlib - global allocated memory: %zu bytes\n",
+                    systemallocator.dmm_stats.total_mem_allocated);
+#ifdef REQUEST_SIZE_INFO
+            systemallocator.dmm_stats.total_mem_requested -=
+                remaining_size;
+            TRACE_1("dmmlib - global requested memory: %zu bytes\n",
+                    systemallocator.dmm_stats.total_mem_requested);
+#endif /* REQUEST_SIZE_INFO */
+            systemallocator.dmm_stats.num_realloc++;
+#endif /* WITH_ALLOCATOR_STATS */
+
+            return ptr;
+
+        } else {
+
+            size_t size_diff = full_size - current_raw_block->size;
+
+            raw_block_header_t *new_block = create_raw_block(full_size,
+                    BIGBLOCK);
+
+            if(new_block == NULL) {
+
+                return NULL;
+
+            } else {
+
+                memcpy((void *)((char *)new_block +
+                            sizeof(raw_block_header_t)), ptr,
+                        current_raw_block->size - sizeof(raw_block_header_t));
+
+                release_memory(current_raw_block);
+
+#ifdef WITH_ALLOCATOR_STATS
+                systemallocator.dmm_stats.total_mem_allocated +=
+                    size_diff;
+                TRACE_1("dmmlib - global allocated memory: %zu bytes\n",
+                        systemallocator.dmm_stats.total_mem_allocated);
+#ifdef REQUEST_SIZE_INFO
+                systemallocator.dmm_stats.total_mem_requested +=
+                    size_diff;
+                TRACE_1("dmmlib - global requested memory: %zu bytes\n",
+                        systemallocator.dmm_stats.total_mem_requested);
+#endif /* REQUEST_SIZE_INFO */
+                systemallocator.dmm_stats.num_realloc++;
+#endif /* WITH_ALLOCATOR_STATS */
+
+                return (void *)((char *)new_block + sizeof(raw_block_header_t));
+            }
+        }
     }
 }