/* * 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 #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 */ 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) */ #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 */ ptr = NULL; #ifdef HAVE_LOCKS posix_lock(heap); #endif /* HAVE_LOCKS */ #ifdef WITH_FIXED_LISTS ptr = search_on_fixed(heap, req_padding(size)); if(ptr == NULL) { #endif /* WITH_FIXED_LISTS */ ptr = best_fit_on_freelist(heap, size); #ifdef WITH_FIXED_LISTS } #endif /* WITH_FIXED_LISTS */ if(ptr != NULL) { #ifdef FUTURE_FEATURES set_requested_size(ptr, size); #endif /* FUTURE_FEATURES */ /* 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 */ heap->dmm_stats.mem_allocated += req_padding(size); heap->dmm_stats.mem_requested += size; 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; } /* Currently all the memory space aware allocators are pre-initialized, so * we do not expect any custom_ahmalloc call without knowing which allocator * and heap are to be used. */ #ifndef WITH_MEMORY_SPACE_AWARENESS void * custom_malloc(size_t size) { return custom_ahmalloc(NULL, NULL, size); } #endif /* WITH_MEMORY_SPACE_AWARENESS */