/* * 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. * */ #include #include "dmm_config.h" #ifdef HAVE_LOCKS #include "posix_lock.h" #endif /* HAVE_LOCKS */ #if defined (SPLITTING_FIXED) || defined (SPLITTING_VARIABLE) #include "split.h" #endif /* SPLITTING_FIXED || SPLITTING_VARIABLE */ #include "other.h" #include "linked_lists/linked_lists.h" #include "linked_lists/search_algorithms.h" #include "sys_alloc.h" #include "block_header.h" #ifdef WITH_ADAPTIVITY #include "dmm_adaptor.h" #endif /* WITH_ADAPTIVITY */ #if defined (BEST_FIT) #define search_on_free(size) best_fit_on_freelist(heap, size) #elif defined (GOOD_FIT) #define search_on_free(size) good_fit_on_freelist(heap, size) #elif defined (EXACT_FIT) #define search_on_free(size) exact_fit_on_freelist(heap, size) #elif defined (FIRST_FIT) #define search_on_free(size) first_fit_on_freelist(heap, size) #endif /* BEST_FIT */ void * custom_ahmalloc(allocator_t* allocator, heap_t* heap, size_t size) { void *ptr; #if defined (SPLITTING_FIXED) || defined (SPLITTING_VARIABLE) size_t new_size; size_t min_split_size; #endif /* (SPLITTING_FIXED) || (SPLITTING_VARIABLE) */ ptr = NULL; #ifdef HAVE_LOCKS posix_lock(heap); #endif /* HAVE_LOCKS */ #ifdef COUNT_HOPS /* Initialize the hops counter */ heap->dmm_stats.total_hops = 0; #endif /* COUNT_HOPS */ #ifdef WITH_FIXED_LISTS ptr = search_on_fixed(heap, req_padding(size)); if(ptr == NULL) { #endif /* WITH_FIXED_LISTS */ #ifdef ALLOC_VAR_FIT ptr = (*allocator->search_policy)(heap, req_padding(size)); #elif defined (HEAP_VAR_FIT) ptr = (*heap->dmm_knobs.search_policy)(heap, req_padding(size)); #else /* ALLOC_VAR_FIT */ ptr = search_on_free(size); #endif /* ALLOC_VAR_FIT */ #ifdef WITH_FIXED_LISTS } #endif /* WITH_FIXED_LISTS */ if(ptr != NULL) { #ifdef REQUEST_SIZE_INFO set_requested_size(ptr, size); #endif /* REQUEST_SIZE_INFO */ /* Try to split */ #if defined (SPLITTING_FIXED) || defined (SPLITTING_VARIABLE) /* Check what would be the size of the new block if we split the current * one. * Note: new_size is a size_t, so compare first in order to prevent an * underflow. */ if(get_size(ptr) > size + HEADER_SIZE) { new_size = get_size(ptr) - size - HEADER_SIZE; } else { new_size = 0; } #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(new_size >= min_split_size) { split(allocator, heap, ptr, size); } #endif /* (SPLITTING_FIXED) || (SPLITTING_VARIABLE) */ mark_used(allocator, ptr); #ifdef FUTURE_FEATURES /* Update the used blocks list */ push_block(&ptr, &heap->used_blocks_head); #endif /* FUTURE_FEATURES */ #ifdef WITH_STATS /* Update statistics */ #ifdef REQUEST_SIZE_INFO heap->dmm_stats.mem_requested += size; #endif /* REQUEST_SIZE_INFO */ heap->dmm_stats.mem_used += HEADER_SIZE + get_size(ptr); heap->dmm_stats.live_objects += 1; heap->dmm_stats.num_malloc += 1; #endif /* WITH_STATS */ /* FIXME To be refactored - END */ } else { ptr = sys_alloc(allocator, heap, size); } #ifdef WITH_ADAPTIVITY /* Refresh the state of the heap allocator if a certain number of * malloc's has been served already */ /* TODO Define 50 as a constant */ if(heap->dmm_stats.num_malloc % 50) { malloc_state_refresh(heap); } #endif /* WITH_ADAPTIVITY */ #ifdef HAVE_LOCKS posix_unlock(heap); #endif /* HAVE_LOCKS */ return ptr; }