|
@@ -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
|