| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- /*
- * 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/memalign.c
- * @author Ioannis Koutras (joko@microlab.ntua.gr)
- * @date November 2012
- *
- * @brief Implementation of memory-aligned allocation calls for
- * freelist-organized raw blocks.
- */
- #include "dmmlib/memalign.h"
- #include <inttypes.h>
- #include <sys/mman.h>
- #include <assert.h>
- #include "dmmlib/config.h"
- #include "dmmlib/dmmlib.h"
- #include "memcpy.h"
- #include "default_rb.h"
- #include "dmmlib_trace.h"
- #include "locks.h"
- #include "statistics.h"
- #ifdef BITMAP_RB_ONLY
- #error Current memory-aligned allocation implementation supports only \
- freelist-organized raw blocks.
- #endif /* BITMAP_RB_ONLY */
- /** The obsolete function memalign() allocates size bytes and returns a pointer
- * to the allocated memory. The memory address will be a multiple of alignment,
- * which must be a power of two.
- */
- void *memalign(size_t alignment, size_t size) {
- void *memptr;
- DEFAULT_RB_T *encapsulated_rb;
- raw_block_header_t *raw_block;
- size_t extra_size;
- /* Verify that alignment is a power of two */
- assert((alignment && !(alignment & (alignment - 1))) != 0);
- memptr = NULL;
- /* extra_size denotes the worst-case scenario. Because memcpy() is used, at
- * least HEADER_SIZE is needed for no memory overlap. */
- extra_size = sizeof(raw_block_header_t) + alignment - 1;
- if(2 * (size + extra_size) < SYS_ALLOC_SIZE - sizeof(raw_block_header_t) -
- sizeof(freelist_rb_t)) {
- /* Search the available freelist-organized raw blocks */
- SLIST_FOREACH(raw_block, &systemallocator.rb_head, pointers) {
- #ifdef TRYLOCK_ON_MALLOC
- if(TRYLOCK_RAW_BLOCK(raw_block) == 0) {
- #else /* TRYLOCK_ON_MALLOC */
- LOCK_RAW_BLOCK(raw_block);
- #endif /* TRYLOCK_ON_MALLOC */
- encapsulated_rb = (freelist_rb_t *)
- ((uintptr_t) raw_block + sizeof(raw_block_header_t));
- memptr = freelist_memalign(encapsulated_rb, alignment, size);
- UNLOCK_RAW_BLOCK(raw_block);
- if(memptr != NULL) {
- break;
- }
- #ifdef TRYLOCK_ON_MALLOC
- }
- #endif /* TRYLOCK_ON_MALLOC */
- }
- if(memptr == NULL) { /* no block was found, try to create a new one */
- raw_block = create_raw_block((size_t) SYS_ALLOC_SIZE,
- DEFAULT_RB_TYPE);
- if(raw_block != NULL) {
- LOCK_GLOBAL();
- LOCK_RAW_BLOCK(raw_block);
- SLIST_INSERT_HEAD(&systemallocator.rb_head, raw_block, pointers);
- UNLOCK_GLOBAL();
- encapsulated_rb = (DEFAULT_RB_T *)
- ((uintptr_t) raw_block + sizeof(raw_block_header_t));
- memptr = freelist_memalign(encapsulated_rb, alignment, size);
- UNLOCK_RAW_BLOCK(raw_block);
- }
- }
- } else { /* A big block has to be created */
- memptr = (void *)create_raw_block(size + extra_size +
- sizeof(raw_block_header_t), BIGBLOCK);
- if(memptr != NULL) {
- memptr = (void *)((uintptr_t) memptr + sizeof(raw_block_header_t));
- /* Check if alignment is needed */
- if(((uintptr_t) memptr) % alignment != 0) {
- size_t padding = (- (size_t) memptr) & (alignment - 1);
- while(padding < sizeof(raw_block_header_t)) {
- padding += alignment;
- }
- /* Sometimes a deadlock is observed unless the old mutex is
- * destroyed. */
- DESTROY_RAW_BLOCK_LOCK(((raw_block_header_t *) memptr));
- /* Copy the raw block's header to the new location */
- memcpy((void *)((uintptr_t) memptr -
- sizeof(raw_block_header_t) + padding),
- (void *)((uintptr_t) memptr -
- sizeof(raw_block_header_t)),
- sizeof(raw_block_header_t)
- );
- /* Update *memptr */
- memptr = (void *)((uintptr_t) memptr + padding);
- /* Update big block's size and requested size */
- raw_block_header_t *aligned_header =
- (raw_block_header_t *)((uintptr_t) memptr -
- sizeof(raw_block_header_t));
- INIT_RAW_BLOCK_LOCK(aligned_header);
- LOCK_RAW_BLOCK(aligned_header);
- aligned_header->size -= padding;
- #ifdef REQUEST_SIZE_INFO
- aligned_header->requested_size = size;
- #endif /* REQUEST_SIZE_INFO */
- UNLOCK_RAW_BLOCK(aligned_header);
- }
- #ifdef WITH_DEBUG
- LOCK_GLOBAL();
- LOCK_RAW_BLOCK(((raw_block_header_t *) ((uintptr_t) memptr -
- sizeof(raw_block_header_t))));
- SLIST_INSERT_HEAD(&systemallocator.bb_head,
- (raw_block_header_t *) ((uintptr_t) memptr -
- sizeof(raw_block_header_t)), pointers);
- UNLOCK_RAW_BLOCK(((raw_block_header_t *) ((uintptr_t) memptr -
- sizeof(raw_block_header_t))));
- UNLOCK_GLOBAL();
- #endif /* WITH_DEBUG */
- }
- }
- if(memptr != NULL) {
- /* Assert that the returned address is a multiple of alignment */
- assert((uintptr_t) memptr % alignment == 0);
- #ifdef REQUEST_SIZE_INFO
- UPDATE_GLOBAL_STATS(MEMALIGN, size);
- #else /* REQUEST_SIZE_INFO */
- UPDATE_GLOBAL_STATS(MEMALIGN);
- #endif /* REQUEST_SIZE_INFO */
- }
- MEM_TRACE("dmmlib - ma %p %zu %zu\n", *memptr, alignment, size);
- return memptr;
- }
- /** The function posix_memalign() allocates size bytes and places the address of
- * the allocated memory in *memptr. The address of the allocated memory will be
- * a multiple of alignment, which must be a power of two and a multiple of
- * sizeof(void *). If size is 0, then posix_memalign() returns either NULL, or a
- * unique pointer value that can later be successfully passed to free().
- */
- int posix_memalign(void **memptr, size_t alignment, size_t size) {
- void *ptr = NULL;
- /* Input check */
- if(size == 0 || (alignment & 1) != 0 || alignment % sizeof(void *) != 0) {
- return -1;
- }
- ptr = memalign(alignment, size);
- if(ptr != NULL) {
- *memptr = ptr;
- return 0;
- }
- return -1;
- }
|