/* * Copyright 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 src/malloc.c * @author Ioannis Koutras (joko@microlab.ntua.gr) * @date September 2012 * * @brief Implementation of malloc() call. */ #include "dmmlib/dmmlib.h" #include #include #include "tls_allocator.h" #include "dmmlib/debug.h" #include "dmmlib/lists.h" #include "locks.h" #include "default_rb.h" #include "dmmlib_trace.h" #include "statistics.h" void * malloc(size_t size) { size_t sys_alloc_size; raw_block_header_t *raw_block, *new_raw_block; DEFAULT_RB_T *encapsulated_rb; void *ptr; if(size == 0) { return (void *) 0xD34D; } get_tls_allocator(); #ifdef WITH_KNOBS sys_alloc_size = (size_t) tls_allocator->dmm_knobs.sys_alloc_size; #else /* WITH_KNOBS */ sys_alloc_size = SYS_ALLOC_SIZE; #endif /* WITH_KNOBS */ /* Check if the size is appropriate for the use of a freelist-organized or * bitmap-organized raw block. */ #ifdef BITMAP_RB_ONLY /* FIXME currently the raw block size and resolution are fixed */ size_t bm_vector_size = BMAP_EL_SIZE * (sys_alloc_size + BMAP_EL_SIZE - sizeof(raw_block_header_t) - sizeof(bitmap_rb_t)) / (BMAP_EL_SIZE + BMAP_EL_SIZE_BITS * BITMAP_RESOLUTION); if(2 * size < sys_alloc_size - sizeof(raw_block_header_t) - sizeof(bitmap_rb_t) - bm_vector_size) { #endif /* BITMAP_RB_ONLY */ #ifdef FL_RB_ONLY if(2 * size < sys_alloc_size - sizeof(raw_block_header_t) - sizeof(freelist_rb_t)) { #endif /* FL_RB_ONLY */ ptr = NULL; /* Try to find a raw block available for allocation */ SLIST_FOREACH(raw_block, &tls_allocator->rb_head, pointers) { #ifdef TRYLOCK_ON_MALLOC if(DEALY_TRYLOCK(raw_block->lock) == 0) { #else /* TRYLOCK_ON_MALLOC */ DEALY_LOCK(raw_block->lock); #endif /* TRYLOCK_ON_MALLOC */ encapsulated_rb = (DEFAULT_RB_T *) ((uintptr_t) raw_block + sizeof(raw_block_header_t)); ptr = dmmlib_malloc(encapsulated_rb, size); DEALY_UNLOCK(raw_block->lock); if(ptr != NULL) { /* Check that a valid pointer has been returned */ assert(((uintptr_t) raw_block < (uintptr_t) ptr) && ((uintptr_t) ptr < (uintptr_t) raw_block + raw_block->size + sizeof(raw_block_header_t))); break; } #ifdef TRYLOCK_ON_MALLOC } #endif /* TRYLOCK_ON_MALLOC */ } if(ptr == NULL) { /* No raw block was found, try to create a new one and allocate a * memory block from there. */ new_raw_block = create_raw_block(sys_alloc_size, DEFAULT_RB_TYPE); if(new_raw_block != NULL) { SLIST_INSERT_HEAD(&tls_allocator->rb_head, new_raw_block, pointers); encapsulated_rb = (DEFAULT_RB_T *) ((uintptr_t) new_raw_block + sizeof(raw_block_header_t)); ptr = dmmlib_malloc(encapsulated_rb, size); } } } else { /* The memory request size is too large to serve it inside a * freelist-organized or bitmap-organized raw block, so a big raw block * shall be used. */ ptr = create_raw_block(size + sizeof(raw_block_header_t), BIGBLOCK); if(ptr != NULL) { ptr = (void *)((uintptr_t) ptr + sizeof(raw_block_header_t)); } } MEM_TRACE("dmmlib - m %p %zu\n", ptr, size); if(ptr != NULL) { #ifdef REQUEST_SIZE_INFO UPDATE_GLOBAL_STATS(MALLOC, size); #else /* REQUEST_SIZE_INFO */ UPDATE_GLOBAL_STATS(MALLOC); #endif /* REQUEST_SIZE_INFO */ } return ptr; }