/* * Copyright 2012 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 dmmlib.c * @author Ioannis Koutras (joko@microlab.ntua.gr) * @date September 2012 * * @brief Implementations of malloc(), free() and calloc() calls. */ #include "dmmlib/dmmlib.h" #ifdef FL_RB_ONLY #include "freelist/freelist.h" #include "freelist/freelist_rb.h" #endif /* FL_RB_ONLY */ #ifdef BITMAP_RB_ONLY #include "bitmap/bitmap.h" #include "bitmap/bitmap_rb.h" #endif /* BITMAP_RB_ONLY */ #include "release_memory.h" #include #include /* for memset() */ #include "trace.h" #ifdef WITH_DEBUG #include "debug.h" #endif /* WITH_DEBUG */ void * malloc(size_t size) { raw_block_header_t *raw_block, *new_raw_block; size_t allocation_size; void *ptr; raw_block = systemallocator.raw_block_head; ptr = NULL; if(size == 0) { return NULL; } TRACE_1("dmmlib - malloc - request %zu bytes\n", size); /* Try to find a raw block available for allocation */ while(raw_block != NULL) { ptr = dmmlib_malloc(raw_block, size); if(ptr != NULL) { break; } raw_block = raw_block->next_raw_block; } if(ptr == NULL) { #ifdef FL_RB_ONLY allocation_size = size + sizeof(raw_block_header_t) + sizeof(freelist_rb_t); #endif /* FL_RB_ONLY */ #ifdef BITMAP_RB_ONLY allocation_size = size + sizeof(raw_block_header_t) + sizeof(bitmap_rb_t); #endif /* BITMAP_RB_ONLY */ if(allocation_size < SYS_ALLOC_SIZE / 2) { allocation_size = SYS_ALLOC_SIZE; } else { ptr = (void *)create_new_raw_block(size + sizeof(raw_block_header_t), BIGBLOCK); if(ptr != NULL) { TRACE_1("dmmlib - malloc - allocated a whole raw block of %zu" " bytes at %p\n", size + sizeof(raw_block_header_t), (void *)ptr); #ifdef WITH_ALLOCATOR_STATS systemallocator.dmm_stats.total_mem_allocated += size + sizeof(raw_block_header_t); systemallocator.dmm_stats.live_objects++; systemallocator.dmm_stats.num_malloc++; TRACE_1("dmmlib - global allocated memory: %zu bytes\n", systemallocator.dmm_stats.total_mem_allocated); #ifdef REQUEST_SIZE_INFO systemallocator.dmm_stats.total_mem_requested += size; TRACE_1("dmmlib - global requested memory: %zu bytes\n", systemallocator.dmm_stats.total_mem_requested); #endif /* REQUEST_SIZE_INFO */ #endif /* WITH_ALLOCATOR_STATS */ ptr = (void *)((char *)ptr + sizeof(raw_block_header_t)); } return ptr; } pthread_mutex_lock(&systemallocator.creation_mutex); #ifdef FL_RB_ONLY new_raw_block = create_new_raw_block(allocation_size, FREELIST); #endif /* FL_RB_ONLY */ #ifdef BITMAP_RB_ONLY new_raw_block = create_new_raw_block(allocation_size, BITMAP); #endif /* BITMAP_RB_ONLY */ if(new_raw_block != NULL) { new_raw_block->next_raw_block = systemallocator.raw_block_head; systemallocator.raw_block_head = new_raw_block; pthread_mutex_unlock(&systemallocator.creation_mutex); ptr = dmmlib_malloc(new_raw_block, size); #ifdef BITMAP_RB_ONLY // FIXME If ptr is still NULL, then make a last try to allocate a // big block. This has to do with the current limitation of checking // max. two bitmap vector elements. if(ptr == NULL) { ptr = (void *) create_new_raw_block(size + sizeof(raw_block_header_t), BIGBLOCK); if(ptr != NULL) { TRACE_1("dmmlib - malloc - allocated a whole raw block of %zu" " bytes at %p\n", size + sizeof(raw_block_header_t), (void *)ptr); #ifdef WITH_ALLOCATOR_STATS systemallocator.dmm_stats.total_mem_allocated += size + sizeof(raw_block_header_t); systemallocator.dmm_stats.live_objects++; systemallocator.dmm_stats.num_malloc++; TRACE_1("dmmlib - global allocated memory: %zu bytes\n", systemallocator.dmm_stats.total_mem_allocated); #ifdef REQUEST_SIZE_INFO systemallocator.dmm_stats.total_mem_requested += size; TRACE_1("dmmlib - global requested memory: %zu bytes\n", systemallocator.dmm_stats.total_mem_requested); #endif /* REQUEST_SIZE_INFO */ #endif /* WITH_ALLOCATOR_STATS */ ptr = (void *)((char *)ptr + sizeof(raw_block_header_t)); } } #endif /* BITMAP_RB_ONLY */ } } #ifdef WITH_DEBUG get_raw_blocks(&systemallocator); #endif /* WITH_DEBUG */ return ptr; } void free(void *ptr) { raw_block_header_t *current_raw_block; bool found; if(ptr == NULL) { return; } found = false; current_raw_block = systemallocator.raw_block_head; while(current_raw_block) { if((char *)ptr - (char *)(current_raw_block) - sizeof(raw_block_header_t) < current_raw_block->size) { found = true; break; } current_raw_block = current_raw_block->next_raw_block; } if(found == true) { dmmlib_free(current_raw_block, ptr); } else { // It has to be a BIGBLOCK, just munmap it current_raw_block = (raw_block_header_t *)((char *)ptr - sizeof(raw_block_header_t)); TRACE_1("dmmlib - free - free'ing %zu bytes from raw block %p\n", current_raw_block->size, (void *)current_raw_block); #ifdef WITH_ALLOCATOR_STATS systemallocator.dmm_stats.total_mem_allocated -= current_raw_block->size; TRACE_1("dmmlib - global allocated memory: %zu bytes\n", systemallocator.dmm_stats.total_mem_allocated); #ifdef REQUEST_SIZE_INFO systemallocator.dmm_stats.total_mem_requested -= current_raw_block->size - sizeof(raw_block_header_t); TRACE_1("dmmlib - global requested memory: %zu bytes\n", systemallocator.dmm_stats.total_mem_requested); #endif /* REQUEST_SIZE_INFO */ systemallocator.dmm_stats.live_objects--; systemallocator.dmm_stats.num_free++; #endif /* WITH_ALLOCATOR_STATS */ release_memory(current_raw_block); } } void * realloc(void *ptr, size_t size) { raw_block_header_t *current_raw_block; bool found; if(ptr == NULL) { return malloc(size); } if(size == 0) { free(ptr); #ifdef BITMAP_RB_ONLY return malloc(CHUNK_HDR_SIZE + 32); // FIXME 32 <- minimum size #endif /* BITMAP_RB_ONLY */ #ifdef FL_RB_ONLY return malloc((size_t) 32); // FIXME 32 <- minimum size #endif /* FL_RB_ONLY */ } found = false; current_raw_block = systemallocator.raw_block_head; while(current_raw_block) { if((char *)ptr - (char *)(current_raw_block) - sizeof(raw_block_header_t) < current_raw_block->size) { found = true; break; } current_raw_block = current_raw_block->next_raw_block; } if(found == true) { #ifdef BITMAP_RB_ONLY return bitmap_realloc(current_raw_block, ptr, size); #endif /* BITMAP_RB_ONLY */ #ifdef FL_RB_ONLY return freelist_realloc(current_raw_block, ptr, size); #endif /* FL_RB_ONLY */ } else { return NULL; } } void * calloc(size_t nmemb, size_t size) { size_t i; char *buf[nmemb]; if(nmemb == 0 || size == 0) { return NULL; } i = 0; while(i < nmemb) { buf[i] = (char*)malloc(size); memset(buf[i], '\0', size); i++; } return buf[0]; }