custom_realloc.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. * Copyright 2011 Institute of Communication and Computer Systems (ICCS)
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. /**
  18. * \file custom_realloc.c
  19. * \author Ioannis Koutras (joko@microlab.ntua.gr)
  20. * \date January, 2012
  21. *
  22. * \brief Implementation of a function to change the size of an allocated
  23. * block.
  24. */
  25. #include <dmmlib/custom_realloc.h>
  26. #include <dmmlib/initialize_allocator.h>
  27. #include "block_header.h"
  28. #ifndef WITH_MEMORY_SPACE_AWARENESS
  29. #include "other.h"
  30. #endif /* WITH_MEMORY_SPACE_AWARENESS */
  31. #if defined (SPLITTING_FIXED) || defined (SPLITTING_VARIABLE)
  32. #include "split.h"
  33. #endif /* SPLITTING_FIXED || SPLITTING_VARIABLE */
  34. /**
  35. * Allocates a new block and copies the contents of the old block to the new
  36. * block. No check is done if there is an old block!
  37. */
  38. void * clean_realloc(allocator_t *allocator, heap_t *heap, void *ptr,
  39. size_t size);
  40. /**
  41. * Copy a memory area
  42. */
  43. static void custom_memcpy(void* dest, const void* src, size_t n) {
  44. char *dst8, *src8;
  45. dst8 = (char *) dest + HEADER_SIZE;
  46. src8 = (char *) src + HEADER_SIZE;
  47. while(n--) {
  48. *dst8++ = *src8++;
  49. }
  50. }
  51. void * clean_realloc(allocator_t *allocator, heap_t *heap, void *ptr,
  52. size_t size) {
  53. size_t old_size;
  54. void *new_ptr;
  55. old_size = get_size(ptr);
  56. new_ptr = custom_ahmalloc(allocator, heap, size);
  57. custom_memcpy(new_ptr, ptr, old_size);
  58. custom_ahfree(allocator, heap, ptr);
  59. return new_ptr;
  60. }
  61. /**
  62. * \details The realloc() function tries to change the size of the allocation
  63. * pointed to by ptr to size, and returns ptr. realloc() creates a new
  64. * allocation, copies as much of the old data pointed to by ptr as will fit to
  65. * the new allocation, frees the old allocation and returns a pointer to the
  66. * allocated memory. If ptr is NULL, realloc() is identical to a call to
  67. * malloc() for size bytes.
  68. */
  69. void * custom_ahrealloc(allocator_t *allocator, heap_t *heap, void *ptr, size_t size) {
  70. void *next_block;
  71. size_t old_size;
  72. #if defined (SPLITTING_FIXED) || defined (SPLITTING_VARIABLE)
  73. size_t min_split_size;
  74. #endif /* (SPLITTING_FIXED) || (SPLITTING_VARIABLE) */
  75. #ifndef WITH_MEMORY_SPACE_AWARENESS
  76. int heap_id;
  77. /* Go to the system allocator if none was given */
  78. if(allocator == NULL) {
  79. allocator = &systemallocator;
  80. if(allocator->initialized != true) {
  81. initialize_allocator(allocator);
  82. }
  83. }
  84. if(heap == NULL) {
  85. heap_id = map_thread_heap();
  86. heap = &allocator->heaps[heap_id];
  87. }
  88. #endif /* WITH_MEMORY_SPACE_AWARENESS */
  89. if(ptr != NULL) {
  90. old_size = get_size(ptr);
  91. if(old_size > size) {
  92. /* The old size is bigger than the new, use the old block */
  93. /* Try to split the currently allocated block */
  94. #if defined (SPLITTING_FIXED) || defined (SPLITTING_VARIABLE)
  95. #ifdef SPLITTING_FIXED
  96. min_split_size = MIN_SPLITTING_SIZE;
  97. #endif /* SPLITTING_FIXED */
  98. #ifdef SPLITTING_VARIABLE
  99. min_split_size = heap->dmm_knobs.min_split_size;
  100. #endif /* SPLITTING_VARIABLE */
  101. if(old_size - size - HEADER_SIZE >= min_split_size) {
  102. split(allocator, heap, ptr, size);
  103. }
  104. #endif /* (SPLITTING_FIXED) || (SPLITTING_VARIABLE) */
  105. return ptr;
  106. } else {
  107. /* The new size can't fit in the old box */
  108. /* Check if the block next to the original as in the data layout
  109. * can be used.
  110. */
  111. next_block = get_dlnext(allocator, ptr);
  112. if(next_block != NULL) {
  113. #ifndef WITH_OWNERSHIP
  114. if(is_free(next_block) == true) {
  115. #else /* WITH_OWNERSHIP */
  116. if(is_free(next_block) == true
  117. && get_owner(next_block) == get_owner(ptr)) {
  118. #endif /* WITH_OWNERSHIP */
  119. if(size < old_size + get_size(next_block) + HEADER_SIZE) {
  120. remove_block_from_lists(&next_block, heap);
  121. if(allocator->border_ptr == next_block) {
  122. allocator->border_ptr = ptr;
  123. }
  124. set_size_and_used(allocator,
  125. ptr,
  126. old_size + get_size(next_block) + HEADER_SIZE);
  127. #if defined (SPLITTING_FIXED) || defined (SPLITTING_VARIABLE)
  128. #ifdef SPLITTING_FIXED
  129. min_split_size = MIN_SPLITTING_SIZE;
  130. #endif /* SPLITTING_FIXED */
  131. #ifdef SPLITTING_VARIABLE
  132. min_split_size = heap->dmm_knobs.min_split_size;
  133. #endif /* SPLITTING_VARIABLE */
  134. if(get_size(ptr) - size >= min_split_size) {
  135. split(allocator, heap, ptr, size);
  136. }
  137. #endif /* (SPLITTING_FIXED) || (SPLITTING_VARIABLE) */
  138. return ptr;
  139. } else {
  140. return clean_realloc(allocator, heap, ptr, size);
  141. }
  142. } else {
  143. return clean_realloc(allocator, heap, ptr, size);
  144. }
  145. } else {
  146. return clean_realloc(allocator, heap, ptr, size);
  147. }
  148. }
  149. } else {
  150. /* ptr is NULL, call malloc() */
  151. return custom_ahmalloc(allocator, heap, size);
  152. }
  153. }
  154. #ifndef WITH_MEMORY_SPACE_AWARENESS
  155. void * custom_realloc(void *ptr, size_t size) {
  156. return custom_ahrealloc(NULL, NULL, ptr, size);
  157. }
  158. #endif /* WITH_MEMORY_SPACE_AWARENESS */