allocator_basic.c

来自「MPI stands for the Message Passing Inter」· C语言 代码 · 共 385 行

C
385
字号
/* * 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) 2006      Sun Microsystems, Inc.  All rights reserved. * $COPYRIGHT$ *  * Additional copyrights may follow *  * $HEADER$ */#include "ompi_config.h"#include "opal/util/output.h"#include "allocator_basic.h"#include "ompi/constants.h"mca_allocator_base_component_t mca_allocator_basic_component = {                                                                                                           /* First, the mca_base_module_t struct containing meta information     about the module itself */                                                                                                           {    /* Indicate that we are a allocator v1.0.0 module (which also implies a       specific MCA version) */                                                                                                             MCA_ALLOCATOR_BASE_VERSION_1_0_0,                                                                                                             "basic", /* MCA module name */    1,  /* MCA module major version */    0,  /* MCA module minor version */    0,  /* MCA module release version */    mca_allocator_basic_component_open,  /* module open */    mca_allocator_basic_component_close  /* module close */  },                                                                                                           /* Next the MCA v1.0.0 module meta data */                                                                                                           {    /* Whether the module is checkpointable or not */    false  },  mca_allocator_basic_component_init};OBJ_CLASS_INSTANCE(    mca_allocator_basic_segment_t,    ompi_free_list_item_t,    NULL,    NULL);int mca_allocator_basic_component_open(void){    return OMPI_SUCCESS;}int mca_allocator_basic_component_close(void){    return OMPI_SUCCESS;}/**  *  */mca_allocator_base_module_t* mca_allocator_basic_component_init(    bool enable_mpi_threads,    mca_allocator_base_component_segment_alloc_fn_t segment_alloc,    mca_allocator_base_component_segment_free_fn_t segment_free,     struct mca_mpool_base_module_t* mpool){    mca_allocator_basic_module_t *module = (mca_allocator_basic_module_t *)                                            malloc(sizeof(mca_allocator_basic_module_t));    if (NULL == module) {        return NULL;    }    module->super.alc_alloc = mca_allocator_basic_alloc;    module->super.alc_realloc = mca_allocator_basic_realloc;    module->super.alc_free = mca_allocator_basic_free;    module->super.alc_compact = mca_allocator_basic_compact;    module->super.alc_finalize = mca_allocator_basic_finalize;    module->super.alc_mpool = mpool;    module->seg_alloc = segment_alloc;    module->seg_free = segment_free;    OBJ_CONSTRUCT(&module->seg_list, opal_list_t);    OBJ_CONSTRUCT(&module->seg_lock, opal_mutex_t);    OBJ_CONSTRUCT(&module->seg_descriptors, ompi_free_list_t);     ompi_free_list_init(&module->seg_descriptors,        sizeof(mca_allocator_basic_segment_t),        OBJ_CLASS(mca_allocator_basic_segment_t),        0,  /* initial size */        -1, /* maximum size */        16, /* increment to grow by */        NULL);    return &module->super;}                                                                                                         /**  * Combine adjacent segments together. */static void mca_allocator_basic_combine_prev(    mca_allocator_basic_module_t* module,     mca_allocator_basic_segment_t* seg){    opal_list_item_t* item = opal_list_get_prev(seg);    if(item != opal_list_get_begin(&module->seg_list)) {        mca_allocator_basic_segment_t *prev = (mca_allocator_basic_segment_t*)item;        if(prev->seg_addr + prev->seg_size == seg->seg_addr) {            prev->seg_size += seg->seg_size;            opal_list_remove_item(&module->seg_list, &seg->seg_item.super);            OMPI_FREE_LIST_RETURN(&module->seg_descriptors, &seg->seg_item);            return;        }    }}static void mca_allocator_basic_combine_next(    mca_allocator_basic_module_t* module,     mca_allocator_basic_segment_t* seg){    opal_list_item_t *item = opal_list_get_next(seg);    if(item != opal_list_get_end(&module->seg_list)) {        mca_allocator_basic_segment_t *next = (mca_allocator_basic_segment_t*)item;        if(seg->seg_addr + seg->seg_size == next->seg_addr) {            next->seg_addr = seg->seg_addr;            next->seg_size += seg->seg_size;            opal_list_remove_item(&module->seg_list, &seg->seg_item.super);            OMPI_FREE_LIST_RETURN(&module->seg_descriptors, &seg->seg_item);            return;        }    }}/**  * Accepts a request for memory in a specific region defined by the  * mca_allocator_basic_options_t struct and returns a pointer to memory in that  * region or NULL if there was an error  *  * @param mem A pointer to the appropriate struct for the area of memory.  * @param size The size of the requested area of memory  *  * @retval Pointer to the area of memory if the allocation was successful  * @retval NULL if the allocation was unsuccessful  */void *mca_allocator_basic_alloc(    mca_allocator_base_module_t * base,     size_t size,    size_t align,     mca_mpool_base_registration_t** registration){    mca_allocator_basic_module_t* module = (mca_allocator_basic_module_t*)base;    mca_allocator_basic_segment_t* seg;    ompi_free_list_item_t* item;    unsigned char* addr;    size_t allocated_size;    OPAL_THREAD_LOCK(&module->seg_lock);    /* add the size of the header into the amount we need to request */    size += sizeof(size_t);    /* normalize size so we don't end up with seg_addr on an odd boundary */    size += sizeof(size_t) - (size & (sizeof(size_t) - 1));    /* search the list for a segment of the required size */    for(item =  (ompi_free_list_item_t*) opal_list_get_first(&module->seg_list);        item != (ompi_free_list_item_t*) opal_list_get_end(&module->seg_list);        item =  (ompi_free_list_item_t*) opal_list_get_next(&item->super)) {        seg = (mca_allocator_basic_segment_t*)item;        /* split the segment */        if(seg->seg_size > size) {            addr = seg->seg_addr;            seg->seg_addr += size;            seg->seg_size -= size;            OPAL_THREAD_UNLOCK(&module->seg_lock);            *(size_t*)addr = size;            return addr+sizeof(size_t);        } else if (seg->seg_size == size) {            addr = seg->seg_addr;            opal_list_remove_item(&module->seg_list, &item->super);            OMPI_FREE_LIST_RETURN(&module->seg_descriptors, item);            OPAL_THREAD_UNLOCK(&module->seg_lock);            *(size_t*)addr = size;            return addr+sizeof(size_t);        }    }    /* request additional block */    allocated_size = (unsigned char)size;    if(NULL == (addr = (unsigned char *)module->seg_alloc(module->super.alc_mpool, &allocated_size, registration))) {        OPAL_THREAD_UNLOCK(&module->seg_lock);        return NULL;    }    /* create a segment for any extra allocation */    if(allocated_size > size) {        int rc;        OMPI_FREE_LIST_GET(&module->seg_descriptors, item, rc);        if(rc != OMPI_SUCCESS) {            OPAL_THREAD_UNLOCK(&module->seg_lock);            return NULL;        }        seg = (mca_allocator_basic_segment_t*)item;        seg->seg_addr = addr + size;        seg->seg_size = allocated_size - size;        opal_list_append(&module->seg_list, &item->super);    }    *(size_t*)addr = size;    OPAL_THREAD_UNLOCK(&module->seg_lock);    return addr+sizeof(size_t);}/**  * Attempts to resize the passed region of memory into a larger or a smaller  * region. If it is unsuccessful, it will return NULL and the passed area of  * memory will be untouched.  *  * @param mem A pointer to the appropriate struct for the area of  * memory.  * @param size The size of the requested area of memory  * @param ptr A pointer to the region of memory to be resized  *  * @retval Pointer to the area of memory if the reallocation was successful  * @retval NULL if the allocation was unsuccessful  *  */void * mca_allocator_basic_realloc(    mca_allocator_base_module_t * base,     void * ptr,     size_t size,     mca_mpool_base_registration_t** registration){    unsigned char* addr = ((unsigned char*)ptr) - sizeof(size_t);    size_t alloc_size = *(size_t*)addr;    if(size <= alloc_size)        return ptr;    addr = (unsigned char *)mca_allocator_basic_alloc(base,size,0,registration);    if(addr == NULL)        return addr;    memcpy(addr,ptr,alloc_size);    mca_allocator_basic_free(base,ptr);    return addr;}/**  * Frees the passed region of memory  *  * @param mem A pointer to the appropriate struct for the area of  * memory.  * @param ptr A pointer to the region of memory to be freed  *  * @retval None  *  */void mca_allocator_basic_free(    mca_allocator_base_module_t * base,    void * ptr){    mca_allocator_basic_module_t* module = (mca_allocator_basic_module_t*)base;    mca_allocator_basic_segment_t* seg;    ompi_free_list_item_t *item;    unsigned char* addr = (unsigned char*)ptr - sizeof(size_t);    size_t size = *(size_t*)addr;    int rc;    OPAL_THREAD_LOCK(&module->seg_lock);    /* maintain the free list in sorted order by address */    for(item =  (ompi_free_list_item_t*) opal_list_get_first(&module->seg_list);        item != (ompi_free_list_item_t*) opal_list_get_end(&module->seg_list);        item =  (ompi_free_list_item_t*) opal_list_get_next((&item->super))) {        seg = (mca_allocator_basic_segment_t*)item;        if (seg->seg_addr < addr) {            /* can we grow the current entry */            if(seg->seg_addr + seg->seg_size == addr) {                seg->seg_size += size;                mca_allocator_basic_combine_next(module, seg);                OPAL_THREAD_UNLOCK(&module->seg_lock);                return;            }             /* otherwise continue to check next larger entry */        } else  {            /* can this be combined with current entry */            if(addr + size == seg->seg_addr) {                seg->seg_addr = addr;                seg->seg_size += size;                mca_allocator_basic_combine_prev(module, seg);                OPAL_THREAD_UNLOCK(&module->seg_lock);                return;            /* insert before larger entry */            } else {                mca_allocator_basic_segment_t* new_seg;                OMPI_FREE_LIST_GET(&module->seg_descriptors, item, rc);                if(rc != OMPI_SUCCESS) {                    OPAL_THREAD_UNLOCK(&module->seg_lock);                    return;                }                new_seg = (mca_allocator_basic_segment_t*)item;                new_seg->seg_addr = addr;                new_seg->seg_size = size;                opal_list_insert_pos(&module->seg_list, &seg->seg_item.super, &item->super);                OPAL_THREAD_UNLOCK(&module->seg_lock);                return;            }        }    }    /* append to the end of the list */    OMPI_FREE_LIST_GET(&module->seg_descriptors, item, rc);    if(rc != OMPI_SUCCESS) {        OPAL_THREAD_UNLOCK(&module->seg_lock);        return;    }    seg = (mca_allocator_basic_segment_t*)item;    seg->seg_addr = addr;    seg->seg_size = size;    opal_list_append(&module->seg_list, &item->super);    OPAL_THREAD_UNLOCK(&module->seg_lock);}/**  * Frees all the memory from all the basics back to the system. Note that  * this function only frees memory that was previously freed with  * mca_allocator_basic_free().  *  * @param mem A pointer to the appropriate struct for the area of  * memory.  *  * @retval None  *  */int mca_allocator_basic_compact(mca_allocator_base_module_t * mem){    return OMPI_SUCCESS;}/**  * Cleanup all resources held by this allocator.  *  * @param mem A pointer to the appropriate struct for the area of  * memory.  *  * @retval None  *  */int mca_allocator_basic_finalize(mca_allocator_base_module_t * base){    mca_allocator_basic_module_t* module = (mca_allocator_basic_module_t*)base;    OBJ_DESTRUCT(&module->seg_list);    OBJ_DESTRUCT(&module->seg_lock);    OBJ_DESTRUCT(&module->seg_descriptors);    free(module);    return OMPI_SUCCESS;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?