allocator_bucket_alloc.c
来自「MPI stands for the Message Passing Inter」· C语言 代码 · 共 393 行 · 第 1/2 页
C
393 行
/* * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. * Copyright (c) 2004-2005 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * Copyright (c) 2007 IBM Corp., All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ */#include "ompi_config.h"#include "ompi/constants.h"#include "ompi/mca/allocator/bucket/allocator_bucket_alloc.h"/** * The define controls the size in bytes of the 1st bucket and hence every one * afterwards. */#define MCA_ALLOCATOR_BUCKET_1_SIZE 8/** * This is the number of left bit shifts from 1 needed to get to the number of * bytes in the initial memory buckets */#define MCA_ALLOCATOR_BUCKET_1_BITSHIFTS 3 /* * Initializes the mca_allocator_bucket_options_t data structure for the passed * parameters. */mca_allocator_bucket_t * mca_allocator_bucket_init( mca_allocator_base_module_t * mem, int num_buckets, mca_allocator_base_component_segment_alloc_fn_t get_mem_funct, mca_allocator_base_component_segment_free_fn_t free_mem_funct){ mca_allocator_bucket_t * mem_options = (mca_allocator_bucket_t *) mem; int i; size_t size; /* if a bad value is used for the number of buckets, default to 30 */ if(num_buckets <= 0) { num_buckets = 30; } /* initialize the array of buckets */ size = sizeof(mca_allocator_bucket_bucket_t) * num_buckets; mem_options->buckets = (mca_allocator_bucket_bucket_t*) malloc(size); if(NULL == mem_options->buckets) { return(NULL); } for(i = 0; i < num_buckets; i++) { mem_options->buckets[i].free_chunk = NULL; mem_options->buckets[i].segment_head = NULL; OBJ_CONSTRUCT(&(mem_options->buckets[i].lock), opal_mutex_t); } mem_options->num_buckets = num_buckets; mem_options->get_mem_fn = get_mem_funct; mem_options->free_mem_fn = free_mem_funct; return(mem_options);}/* * Accepts a request for memory in a specific region defined by the * mca_allocator_bucket_options_t struct and returns a pointer to memory in that * region or NULL if there was an error * */void * mca_allocator_bucket_alloc( mca_allocator_base_module_t * mem, size_t size, mca_mpool_base_registration_t** registration){ mca_allocator_bucket_t * mem_options = (mca_allocator_bucket_t *) mem; /* initialize for the later bit shifts */ int bucket_num = 0; size_t bucket_size = MCA_ALLOCATOR_BUCKET_1_SIZE; size_t allocated_size; mca_allocator_bucket_chunk_header_t * chunk; mca_allocator_bucket_chunk_header_t * first_chunk; mca_allocator_bucket_segment_head_t * segment_header; /* add the size of the header into the amount we need to request */ size += sizeof(mca_allocator_bucket_chunk_header_t); /* figure out which bucket it will come from. */ while(size > bucket_size) { bucket_num++; bucket_size <<= 1; } /* now that we know what bucket it will come from, we must get the lock */ OPAL_THREAD_LOCK(&(mem_options->buckets[bucket_num].lock)); /* see if there is already a free chunk */ if(NULL != mem_options->buckets[bucket_num].free_chunk) { chunk = mem_options->buckets[bucket_num].free_chunk; mem_options->buckets[bucket_num].free_chunk = chunk->u.next_free; chunk->u.bucket = bucket_num; /* go past the header */ chunk += 1; /*release the lock */ OPAL_THREAD_UNLOCK(&(mem_options->buckets[bucket_num].lock)); return((void *) chunk); } /* figure out the size of bucket we need */ allocated_size = bucket_size; /* we have to add in the size of the segment header into the * amount we need to request */ allocated_size += sizeof(mca_allocator_bucket_segment_head_t); /* attempt to get the memory */ segment_header = (mca_allocator_bucket_segment_head_t *) mem_options->get_mem_fn(mem_options->super.alc_mpool, &allocated_size, registration); if(NULL == segment_header) { /* release the lock */ OPAL_THREAD_UNLOCK(&(mem_options->buckets[bucket_num].lock)); return(NULL); } /* if were allocated more memory then we actually need, then we will try to * break it up into multiple chunks in the current bucket */ allocated_size -= (sizeof(mca_allocator_bucket_segment_head_t) + bucket_size); chunk = first_chunk = segment_header->first_chunk = (mca_allocator_bucket_chunk_header_t *) (segment_header + 1); /* add the segment into the segment list */ segment_header->next_segment = mem_options->buckets[bucket_num].segment_head; mem_options->buckets[bucket_num].segment_head = segment_header; if(allocated_size >= bucket_size) { mem_options->buckets[bucket_num].free_chunk = (mca_allocator_bucket_chunk_header_t *) ((char *) chunk + bucket_size); chunk->next_in_segment = (mca_allocator_bucket_chunk_header_t *) ((char *)chunk + bucket_size); while(allocated_size >= bucket_size) { chunk = (mca_allocator_bucket_chunk_header_t *) ((char *) chunk + bucket_size); chunk->u.next_free = (mca_allocator_bucket_chunk_header_t *) ((char *) chunk + bucket_size); chunk->next_in_segment = chunk->u.next_free; allocated_size -= bucket_size; } chunk->next_in_segment = first_chunk; chunk->u.next_free = NULL; } else { first_chunk->next_in_segment = first_chunk; } first_chunk->u.bucket = bucket_num; OPAL_THREAD_UNLOCK(&(mem_options->buckets[bucket_num].lock)); /* return the memory moved past the header */ return((void *) (first_chunk + 1));}/* * allocates an aligned region of memory */void * mca_allocator_bucket_alloc_align( mca_allocator_base_module_t * mem, size_t size, size_t alignment, mca_mpool_base_registration_t** registration){ mca_allocator_bucket_t * mem_options = (mca_allocator_bucket_t *) mem; int bucket_num = 1; void * ptr; size_t aligned_max_size, bucket_size; size_t alignment_off, allocated_size; mca_allocator_bucket_chunk_header_t * chunk; mca_allocator_bucket_chunk_header_t * first_chunk; mca_allocator_bucket_segment_head_t * segment_header; char * aligned_memory; /* since we do not have a way to get pre aligned memory, we need to request * a chunk then return an aligned spot in it. In the worst case we need * the requested size plus the alignment and the header size */ aligned_max_size = size + alignment + sizeof(mca_allocator_bucket_chunk_header_t) + sizeof(mca_allocator_bucket_segment_head_t); bucket_size = size + sizeof(mca_allocator_bucket_chunk_header_t); allocated_size = aligned_max_size; /* get some memory */ ptr = mem_options->get_mem_fn(mem_options->super.alc_mpool, &allocated_size, registration); if(NULL == ptr) { return(NULL); } /* the first part of the memory is the segment header */ segment_header = (mca_allocator_bucket_segment_head_t *) ptr; /* we temporarily define the first chunk to be right after the segment_header */ first_chunk = (mca_allocator_bucket_chunk_header_t *) (segment_header + 1); /* we want to align the memory right after the header, so we go past the header */ aligned_memory = (char *) (first_chunk + 1); /* figure out how much the alignment is off by */ alignment_off = ((size_t) aligned_memory) % alignment; aligned_memory += (alignment - alignment_off); /* we now have an aligned piece of memory. Now we have to put the chunk * header right before the aligned memory */ first_chunk = (mca_allocator_bucket_chunk_header_t *) aligned_memory - 1; while(bucket_size > MCA_ALLOCATOR_BUCKET_1_SIZE) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?