root/opal/mca/allocator/basic/allocator_basic.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mca_allocator_basic_component_open
  2. mca_allocator_basic_component_close
  3. mca_allocator_basic_component_init
  4. mca_allocator_basic_combine_prev
  5. mca_allocator_basic_combine_next
  6. mca_allocator_basic_alloc
  7. mca_allocator_basic_realloc
  8. mca_allocator_basic_free
  9. mca_allocator_basic_compact
  10. mca_allocator_basic_finalize

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2013 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
  10  *                         University of Stuttgart.  All rights reserved.
  11  * Copyright (c) 2004-2005 The Regents of the University of California.
  12  *                         All rights reserved.
  13  * Copyright (c) 2006      Sun Microsystems, Inc.  All rights reserved.
  14  * Copyright (c) 2008      Cisco Systems, Inc.  All rights reserved.
  15  * Copyright (c) 2011      NVIDIA Corporation.  All rights reserved.
  16  * Copyright (c) 2015      Los Alamos National Security, LLC. All rights
  17  *                         reserved.
  18  * $COPYRIGHT$
  19  *
  20  * Additional copyrights may follow
  21  *
  22  * $HEADER$
  23  */
  24 
  25 #include "opal_config.h"
  26 #include "allocator_basic.h"
  27 #include "opal/constants.h"
  28 
  29 
  30 
  31 mca_allocator_base_component_t mca_allocator_basic_component = {
  32 
  33   /* First, the mca_base_module_t struct containing meta information
  34      about the module itself */
  35 
  36   {
  37     MCA_ALLOCATOR_BASE_VERSION_2_0_0,
  38 
  39     "basic", /* MCA module name */
  40     OPAL_MAJOR_VERSION,
  41     OPAL_MINOR_VERSION,
  42     OPAL_RELEASE_VERSION,
  43     mca_allocator_basic_component_open,  /* module open */
  44     mca_allocator_basic_component_close  /* module close */
  45   },
  46   {
  47       /* The component is checkpoint ready */
  48       MCA_BASE_METADATA_PARAM_CHECKPOINT
  49   },
  50   mca_allocator_basic_component_init
  51 };
  52 
  53 
  54 OBJ_CLASS_INSTANCE(
  55     mca_allocator_basic_segment_t,
  56     opal_free_list_item_t,
  57     NULL,
  58     NULL);
  59 
  60 
  61 int mca_allocator_basic_component_open(void)
  62 {
  63     return OPAL_SUCCESS;
  64 }
  65 
  66 
  67 int mca_allocator_basic_component_close(void)
  68 {
  69     return OPAL_SUCCESS;
  70 }
  71 
  72 
  73 /**
  74   *
  75   */
  76 
  77 mca_allocator_base_module_t* mca_allocator_basic_component_init(
  78     bool enable_mpi_threads,
  79     mca_allocator_base_component_segment_alloc_fn_t segment_alloc,
  80     mca_allocator_base_component_segment_free_fn_t segment_free,
  81     void *context)
  82 {
  83     mca_allocator_basic_module_t *module = (mca_allocator_basic_module_t *)
  84                                             malloc(sizeof(mca_allocator_basic_module_t));
  85     if (NULL == module) {
  86         return NULL;
  87     }
  88 
  89     module->super.alc_alloc = mca_allocator_basic_alloc;
  90     module->super.alc_realloc = mca_allocator_basic_realloc;
  91     module->super.alc_free = mca_allocator_basic_free;
  92     module->super.alc_compact = mca_allocator_basic_compact;
  93     module->super.alc_finalize = mca_allocator_basic_finalize;
  94     module->super.alc_context = context;
  95     module->seg_alloc = segment_alloc;
  96     module->seg_free = segment_free;
  97     OBJ_CONSTRUCT(&module->seg_list, opal_list_t);
  98     OBJ_CONSTRUCT(&module->seg_lock, opal_mutex_t);
  99     OBJ_CONSTRUCT(&module->seg_descriptors, opal_free_list_t);
 100 
 101     opal_free_list_init (&module->seg_descriptors,
 102         sizeof(mca_allocator_basic_segment_t),
 103         opal_cache_line_size,
 104         OBJ_CLASS(mca_allocator_basic_segment_t),
 105         0,opal_cache_line_size,
 106         0,  /* initial size */
 107         -1, /* maximum size */
 108         16, /* increment to grow by */
 109         NULL, 0, NULL, NULL, NULL);
 110 
 111     return &module->super;
 112 }
 113 
 114 /**
 115   * Combine adjacent segments together.
 116  */
 117 
 118 static void mca_allocator_basic_combine_prev(
 119     mca_allocator_basic_module_t* module,
 120     mca_allocator_basic_segment_t* seg)
 121 {
 122     opal_list_item_t* item = opal_list_get_prev(seg);
 123     if(item != opal_list_get_begin(&module->seg_list)) {
 124         mca_allocator_basic_segment_t *prev = (mca_allocator_basic_segment_t*)item;
 125         if(prev->seg_addr + prev->seg_size == seg->seg_addr) {
 126             prev->seg_size += seg->seg_size;
 127             opal_list_remove_item(&module->seg_list, &seg->seg_item.super);
 128             opal_free_list_return (&module->seg_descriptors, &seg->seg_item);
 129             return;
 130         }
 131     }
 132 }
 133 
 134 static void mca_allocator_basic_combine_next(
 135     mca_allocator_basic_module_t* module,
 136     mca_allocator_basic_segment_t* seg)
 137 {
 138     opal_list_item_t *item = opal_list_get_next(seg);
 139     if(item != opal_list_get_end(&module->seg_list)) {
 140         mca_allocator_basic_segment_t *next = (mca_allocator_basic_segment_t*)item;
 141         if(seg->seg_addr + seg->seg_size == next->seg_addr) {
 142             next->seg_addr = seg->seg_addr;
 143             next->seg_size += seg->seg_size;
 144             opal_list_remove_item(&module->seg_list, &seg->seg_item.super);
 145             opal_free_list_return (&module->seg_descriptors, &seg->seg_item);
 146             return;
 147         }
 148     }
 149 }
 150 
 151 /**
 152   * Accepts a request for memory in a specific region defined by the
 153   * mca_allocator_basic_options_t struct and returns a pointer to memory in that
 154   * region or NULL if there was an error
 155   *
 156   * @param mem A pointer to the appropriate struct for the area of memory.
 157   * @param size The size of the requested area of memory
 158   *
 159   * @retval Pointer to the area of memory if the allocation was successful
 160   * @retval NULL if the allocation was unsuccessful
 161   */
 162 
 163 void *mca_allocator_basic_alloc(
 164     mca_allocator_base_module_t * base,
 165     size_t size,
 166     size_t align)
 167 {
 168     mca_allocator_basic_module_t* module = (mca_allocator_basic_module_t*)base;
 169     mca_allocator_basic_segment_t* seg;
 170     unsigned char* addr;
 171     size_t allocated_size;
 172     OPAL_THREAD_LOCK(&module->seg_lock);
 173 
 174     /* add the size of the header into the amount we need to request */
 175     size += sizeof(size_t);
 176     /* normalize size so we don't end up with seg_addr on an odd boundary */
 177     size += sizeof(size_t) - (size & (sizeof(size_t) - 1));
 178     /* search the list for a segment of the required size */
 179     OPAL_LIST_FOREACH(seg, &module->seg_list, mca_allocator_basic_segment_t) {
 180         /* split the segment */
 181         if(seg->seg_size > size) {
 182             addr = seg->seg_addr;
 183             seg->seg_addr += size;
 184             seg->seg_size -= size;
 185             OPAL_THREAD_UNLOCK(&module->seg_lock);
 186             *(size_t*)addr = size;
 187             return addr+sizeof(size_t);
 188         } else if (seg->seg_size == size) {
 189             addr = seg->seg_addr;
 190             opal_list_remove_item(&module->seg_list, (opal_list_item_t *) seg);
 191             opal_free_list_return (&module->seg_descriptors, (opal_free_list_item_t *) seg);
 192             OPAL_THREAD_UNLOCK(&module->seg_lock);
 193             *(size_t*)addr = size;
 194             return addr+sizeof(size_t);
 195         }
 196     }
 197 
 198     /* request additional block */
 199     allocated_size = size;
 200     if(NULL == (addr = (unsigned char *)module->seg_alloc(module->super.alc_context, &allocated_size))) {
 201         OPAL_THREAD_UNLOCK(&module->seg_lock);
 202         return NULL;
 203     }
 204 
 205     /* create a segment for any extra allocation */
 206     if(allocated_size > size) {
 207         seg = (mca_allocator_basic_segment_t *) opal_free_list_get (&module->seg_descriptors);
 208         if (NULL == seg) {
 209             OPAL_THREAD_UNLOCK(&module->seg_lock);
 210             return NULL;
 211         }
 212         seg->seg_addr = addr + size;
 213         seg->seg_size = allocated_size - size;
 214         opal_list_append (&module->seg_list, (opal_list_item_t *) seg);
 215     }
 216 
 217     *(size_t*)addr = size;
 218     OPAL_THREAD_UNLOCK(&module->seg_lock);
 219     return addr+sizeof(size_t);
 220 }
 221 
 222 
 223 /**
 224   * Attempts to resize the passed region of memory into a larger or a smaller
 225   * region. If it is unsuccessful, it will return NULL and the passed area of
 226   * memory will be untouched.
 227   *
 228   * @param mem A pointer to the appropriate struct for the area of
 229   * memory.
 230   * @param size The size of the requested area of memory
 231   * @param ptr A pointer to the region of memory to be resized
 232   *
 233   * @retval Pointer to the area of memory if the reallocation was successful
 234   * @retval NULL if the allocation was unsuccessful
 235   *
 236   */
 237 
 238 void * mca_allocator_basic_realloc(
 239     mca_allocator_base_module_t * base,
 240     void * ptr,
 241     size_t size)
 242 {
 243     unsigned char* addr = ((unsigned char*)ptr) - sizeof(size_t);
 244     size_t alloc_size = *(size_t*)addr;
 245     if(size <= alloc_size)
 246         return ptr;
 247     addr = (unsigned char *)mca_allocator_basic_alloc(base, size, 0);
 248     if(addr == NULL)
 249         return addr;
 250     memcpy(addr,ptr,alloc_size);
 251     mca_allocator_basic_free(base,ptr);
 252     return addr;
 253 }
 254 
 255 
 256 /**
 257   * Frees the passed region of memory
 258   *
 259   * @param mem A pointer to the appropriate struct for the area of
 260   * memory.
 261   * @param ptr A pointer to the region of memory to be freed
 262   *
 263   * @retval None
 264   *
 265   */
 266 void mca_allocator_basic_free(
 267     mca_allocator_base_module_t * base,
 268     void * ptr)
 269 {
 270     mca_allocator_basic_module_t* module = (mca_allocator_basic_module_t*)base;
 271     mca_allocator_basic_segment_t* seg;
 272     unsigned char* addr = (unsigned char*)ptr - sizeof(size_t);
 273     size_t size = *(size_t*)addr;
 274     OPAL_THREAD_LOCK(&module->seg_lock);
 275 
 276     /* maintain the free list in sorted order by address */
 277     OPAL_LIST_FOREACH(seg, &module->seg_list, mca_allocator_basic_segment_t) {
 278         if (seg->seg_addr < addr) {
 279 
 280             /* can we grow the current entry */
 281             if(seg->seg_addr + seg->seg_size == addr) {
 282                 seg->seg_size += size;
 283                 mca_allocator_basic_combine_next(module, seg);
 284                 OPAL_THREAD_UNLOCK(&module->seg_lock);
 285                 return;
 286             }
 287             /* otherwise continue to check next larger entry */
 288 
 289         } else  {
 290 
 291             /* can this be combined with current entry */
 292             if(addr + size == seg->seg_addr) {
 293                 seg->seg_addr = addr;
 294                 seg->seg_size += size;
 295                 mca_allocator_basic_combine_prev(module, seg);
 296                 OPAL_THREAD_UNLOCK(&module->seg_lock);
 297                 return;
 298 
 299             /* insert before larger entry */
 300             } else {
 301                 mca_allocator_basic_segment_t* new_seg;
 302                 new_seg = (mca_allocator_basic_segment_t *)
 303                     opal_free_list_get (&module->seg_descriptors);
 304                 if(NULL == new_seg) {
 305                     OPAL_THREAD_UNLOCK(&module->seg_lock);
 306                     return;
 307                 }
 308                 new_seg->seg_addr = addr;
 309                 new_seg->seg_size = size;
 310                 opal_list_insert_pos(&module->seg_list, &seg->seg_item.super, (opal_list_item_t *) new_seg);
 311                 OPAL_THREAD_UNLOCK(&module->seg_lock);
 312                 return;
 313             }
 314         }
 315     }
 316 
 317     /* append to the end of the list */
 318     seg = (mca_allocator_basic_segment_t *) opal_free_list_get (&module->seg_descriptors);
 319     if(NULL == seg) {
 320         OPAL_THREAD_UNLOCK(&module->seg_lock);
 321         return;
 322     }
 323     seg->seg_addr = addr;
 324     seg->seg_size = size;
 325     opal_list_append(&module->seg_list, (opal_list_item_t *) seg);
 326     OPAL_THREAD_UNLOCK(&module->seg_lock);
 327 }
 328 
 329 
 330 /**
 331   * Frees all the memory from all the basics back to the system. Note that
 332   * this function only frees memory that was previously freed with
 333   * mca_allocator_basic_free().
 334   *
 335   * @param mem A pointer to the appropriate struct for the area of
 336   * memory.
 337   *
 338   * @retval None
 339   *
 340   */
 341 
 342 int mca_allocator_basic_compact(mca_allocator_base_module_t * mem)
 343 {
 344     return OPAL_SUCCESS;
 345 }
 346 
 347 /**
 348   * Cleanup all resources held by this allocator.
 349   *
 350   * @param mem A pointer to the appropriate struct for the area of
 351   * memory.
 352   *
 353   * @retval None
 354   *
 355   */
 356 
 357 int mca_allocator_basic_finalize(mca_allocator_base_module_t * base)
 358 {
 359     mca_allocator_basic_module_t* module = (mca_allocator_basic_module_t*)base;
 360     // clear the list as we don't own these bits
 361     while (NULL != opal_list_remove_first(&module->seg_list)) {
 362       continue;
 363     }
 364     OBJ_DESTRUCT(&module->seg_list);
 365     OBJ_DESTRUCT(&module->seg_lock);
 366     OBJ_DESTRUCT(&module->seg_descriptors);
 367     free(module);
 368     return OPAL_SUCCESS;
 369 }
 370 
 371 

/* [<][>][^][v][top][bottom][index][help] */