| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- /*
- * 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 freelist/memalign.c
- * @author Ioannis Koutras
- * @date February 2013
- * @brief memalign() implementation for freelist-organised raw blocks
- */
- #include "dmmlib/freelist/freelist.h"
- #include <inttypes.h>
- #include "memcpy.h"
- #include "dmmlib/config.h"
- #include "freelist/block_header_funcs.h"
- void * freelist_memalign(freelist_rb_t *raw_block, size_t alignment,
- size_t size) {
- void *return_ptr;
- return_ptr = freelist_malloc(raw_block, size + alignment - 1);
- if(return_ptr != NULL) {
- check_alignment:
- if(((uintptr_t) return_ptr) % alignment == 0) {
- /* Memory address is already aligned, no need for
- * modifications */
- return return_ptr;
- }
- size_t padding = (- (size_t) return_ptr) & (alignment - 1);
- block_header_t *block_header = get_header(return_ptr);
- /* Check if the currently selected memory block is the first
- * allocated in the raw block. If it is, then there is no previous
- * block in the data layout, so we cannot increase its size as this
- * would conclude to wasted space. Instead of this, we try to
- * allocate another block which is guaranteed not to be the first
- * memory block at this point. If we find one, then we free the
- * first allocated block and repeat the process of alignment.
- * Otherwise, we go to the next raw block. */
- size_t previous_size_availability =
- get_previous_size_availability(block_header);
- if(previous_size_availability == 1) {
- void *old_ptr = return_ptr;
- return_ptr = freelist_malloc(raw_block, size + alignment - 1);
- freelist_free(raw_block, old_ptr);
- if(return_ptr != NULL) {
- goto check_alignment;
- }
- } else {
- size_t previous_size = previous_size_availability >> 1;
- size_t previous_availability = previous_size_availability & 1;
- block_header_t *previous_block = (block_header_t *)
- ((uintptr_t) block_header - previous_size - HEADER_SIZE);
- block_header_t *next_block = get_dlnext(raw_block,
- block_header);
- previous_size += padding;
- previous_block->size = (previous_size << 1) |
- previous_availability;
- block_header->previous_size = (previous_size << 1) |
- previous_availability;
- #ifdef REQUEST_SIZE_INFO
- block_header->requested_size = size;
- #endif /* REQUEST_SIZE_INFO */
- size_t new_size = get_size(block_header) - padding;
- block_header->size = (new_size << 1) | 1;
- if(next_block != NULL) {
- next_block->previous_size = block_header->size;
- } else { /* The aligned memory block is the border pointer */
- raw_block->border_ptr = (block_header_t *)
- ((uintptr_t) block_header + padding);
- }
- memcpy((void *) ((uintptr_t) block_header + padding),
- (void *) block_header, HEADER_SIZE);
- return_ptr = (void *)((uintptr_t) return_ptr + padding);
- }
- }
- return return_ptr;
- }
|