/* * 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. * */ #include "dmmlib/raw_block.h" #include #include #include "request_memory.h" #include "slab.h" #ifdef FL_RB_ONLY #include "dmmlib/freelist/freelist_rb.h" #include "dmmlib/freelist/initialize.h" #endif /* FL_RB_ONLY */ #ifdef BITMAP_RB_ONLY #include "bitmap/bitmap_rb.h" #endif /* BITMAP_RB_ONLY */ #include "locks.h" raw_block_header_t *create_raw_block(size_t raw_block_size, rb_type type) { raw_block_header_t *ptr; size_t padding; #ifdef BITMAP_RB_ONLY bitmap_rb_t *bitmap_rb; BMAP_EL_TYPE *bitmap_p; size_t vector_elements; size_t remaining_cells; #endif /* BITMAP_RB_ONLY */ #ifdef REQUEST_SIZE_INFO size_t requested_size = raw_block_size - sizeof(raw_block_header_t); #endif /* REQUEST_SIZE_INFO */ if(type == BIGBLOCK) { #ifdef PAGESIZE_ALIGN raw_block_size = (raw_block_size + SYS_PAGESIZE - 1) & (size_t) ~(SYS_PAGESIZE - 1); #else /* PAGESIZE_ALIGN */ raw_block_size = (raw_block_size + SYS_ALLOC_SIZE - 1) & (size_t) ~(SYS_ALLOC_SIZE - 1); #endif /* PAGESIZE_ALIGN */ } ptr = (raw_block_header_t *) request_memory(raw_block_size + SYS_ALLOC_SIZE - 1); if(ptr == NULL) { return NULL; } if((uintptr_t) ptr % SYS_ALLOC_SIZE != 0) { padding = (- (uintptr_t) ptr) & (SYS_ALLOC_SIZE - 1); munmap((void *) ptr, padding); ptr = (raw_block_header_t *) ((uintptr_t) ptr + padding); } else { padding = 0; } INIT_DEALY_LOCK(ptr->lock); DEALY_LOCK(ptr->lock); ptr->type = type; ptr->size = raw_block_size + SYS_ALLOC_SIZE - 1 - padding; switch(type) { case SLAB: initialize_slab((char *) ptr + sizeof(raw_block_header_t), raw_block_size - sizeof(raw_block_header_t)); break; #ifdef FL_RB_ONLY case FREELIST: initialize_freelist((char *) ptr + sizeof(raw_block_header_t), raw_block_size - sizeof(raw_block_header_t)); break; #endif /* FL_RB_ONLY */ #ifdef BITMAP_RB_ONLY case BITMAP: bitmap_rb = (bitmap_rb_t *)((char *)ptr + sizeof(raw_block_header_t)); bitmap_rb->bytes_per_cell = BITMAP_RESOLUTION; vector_elements = (raw_block_size - sizeof(raw_block_header_t) - sizeof(bitmap_rb_t)) / (BMAP_EL_SIZE + BMAP_EL_SIZE_BITS * bitmap_rb->bytes_per_cell); remaining_cells = ((raw_block_size - sizeof(raw_block_header_t) - sizeof(bitmap_rb_t)) % (BMAP_EL_SIZE + BMAP_EL_SIZE_BITS * bitmap_rb->bytes_per_cell)) / bitmap_rb->bytes_per_cell; if(remaining_cells == 0) { bitmap_rb->elements = vector_elements; } else { bitmap_rb->elements = vector_elements + 1; } /* Initialize the bitmap vector just right after the raw block * header */ bitmap_p = (BMAP_EL_TYPE *)((char *)bitmap_rb + sizeof(bitmap_rb_t)); for(size_t i = 0; i < bitmap_rb->elements; ++i) { /* If there are some remaining cells, so an extra bitmap vector * element is used, the cells that cannot be used by the * application, have to be set as already used. */ if(i == bitmap_rb->elements - 1 && remaining_cells != 0) { *bitmap_p = (BMAP_EL_TYPE) 1; *bitmap_p <<= remaining_cells; *bitmap_p -= 1; } else { *bitmap_p = BMAP_EL_INIT_VAL; } bitmap_p++; } break; #endif /* BITMAP_RB_ONLY */ case BIGBLOCK: #ifdef REQUEST_SIZE_INFO ptr->requested_size = requested_size; #endif /* REQUEST_SIZE_INFO */ break; } DEALY_UNLOCK(ptr->lock); return ptr; }