123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- /*
- * Copyright 2011 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 custom_realloc.c
- * \author Ioannis Koutras (joko@microlab.ntua.gr)
- * \date January, 2012
- *
- * \brief Implementation of a function to change the size of an allocated
- * block.
- */
- #include <dmmlib/custom_realloc.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) {
- char *dst8, *src8;
-
- dst8 = (char *) dest + HEADER_SIZE;
- src8 = (char *) src + HEADER_SIZE;
-
- while(n--) {
- *dst8++ = *src8++;
- }
- }
- 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);
- custom_memcpy(new_ptr, 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
- * allocation, copies as much of the old data pointed to by ptr as will fit to
- * the new allocation, frees the old allocation and returns a pointer to the
- * allocated memory. If ptr is NULL, realloc() is identical to a call to
- * malloc() for size bytes.
- */
- void * custom_ahrealloc(allocator_t *allocator, heap_t *heap, void *ptr, size_t size) {
- 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;
- /* Go to the system allocator if none was given */
- if(allocator == NULL) {
- allocator = &systemallocator;
- if(allocator->initialized != true) {
- initialize_allocator(allocator);
- }
- }
- if(heap == NULL) {
- heap_id = map_thread_heap();
- heap = &allocator->heaps[heap_id];
- }
- #endif /* WITH_MEMORY_SPACE_AWARENESS */
- if(ptr != NULL) {
- old_size = get_size(ptr);
- 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 {
- /* The new size can't fit in the old box */
- /* 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,
- old_size + get_size(next_block) + HEADER_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(get_size(ptr) - 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
- void * custom_realloc(void *ptr, size_t size) {
- return custom_ahrealloc(NULL, NULL, ptr, size);
- }
- #endif /* WITH_MEMORY_SPACE_AWARENESS */
|