root/oshmem/mca/sshmem/ucx/sshmem_ucx_shadow.c

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

DEFINITIONS

This source file includes following definitions.
  1. sshmem_ucx_shadow_is_free
  2. sshmem_ucx_shadow_set_elem
  3. sshmem_ucx_shadow_create
  4. sshmem_ucx_shadow_destroy
  5. sshmem_ucx_shadow_alloc
  6. sshmem_ucx_shadow_merge_blocks
  7. sshmem_ucx_shadow_realloc
  8. sshmem_ucx_shadow_free
  9. sshmem_ucx_shadow_size

   1 /*
   2  * Copyright (c) 2019      Mellanox Technologies, Inc.
   3  *                         All rights reserved.
   4  * $COPYRIGHT$
   5  *
   6  * Additional copyrights may follow
   7  *
   8  * $HEADER$
   9  */
  10 
  11 #include "oshmem_config.h"
  12 
  13 #include "oshmem/mca/sshmem/sshmem.h"
  14 #include "oshmem/include/shmemx.h"
  15 #include "oshmem/mca/sshmem/base/base.h"
  16 
  17 #include "sshmem_ucx.h"
  18 
  19 #define SSHMEM_UCX_SHADOW_ELEM_FLAG_FREE     0x1
  20 
  21 typedef struct sshmem_ucx_shadow_alloc_elem {
  22     unsigned                       flags;
  23     unsigned                       block_size;
  24 } sshmem_ucx_shadow_alloc_elem_t;
  25 
  26 struct sshmem_ucx_shadow_allocator {
  27     size_t                         num_elems;
  28     sshmem_ucx_shadow_alloc_elem_t elems[];
  29 };
  30 
  31 static int sshmem_ucx_shadow_is_free(sshmem_ucx_shadow_alloc_elem_t *elem)
  32 {
  33     return elem->flags & SSHMEM_UCX_SHADOW_ELEM_FLAG_FREE;
  34 }
  35 
  36 static void sshmem_ucx_shadow_set_elem(sshmem_ucx_shadow_alloc_elem_t *elem,
  37                                        unsigned flags, unsigned block_size)
  38 {
  39     elem->flags      = flags;
  40     elem->block_size = block_size;
  41 }
  42 
  43 sshmem_ucx_shadow_allocator_t *sshmem_ucx_shadow_create(unsigned count)
  44 {
  45     sshmem_ucx_shadow_allocator_t *allocator;
  46 
  47     allocator = calloc(1, sizeof(*allocator) +
  48                        count * sizeof(*allocator->elems));
  49     if (allocator) {
  50         /* initialization: set initial element to the whole buffer */
  51         sshmem_ucx_shadow_set_elem(&allocator->elems[0],
  52                                    SSHMEM_UCX_SHADOW_ELEM_FLAG_FREE, count);
  53         allocator->num_elems = count;
  54     }
  55 
  56     return allocator;
  57 }
  58 
  59 void sshmem_ucx_shadow_destroy(sshmem_ucx_shadow_allocator_t *allocator)
  60 {
  61     free(allocator); /* no leak check. TODO add leak warnings/debug */
  62 }
  63 
  64 int sshmem_ucx_shadow_alloc(sshmem_ucx_shadow_allocator_t *allocator,
  65                             unsigned count, unsigned *index)
  66 {
  67     sshmem_ucx_shadow_alloc_elem_t *end = &allocator->elems[allocator->num_elems];
  68     sshmem_ucx_shadow_alloc_elem_t *elem;
  69 
  70     assert(count > 0);
  71 
  72     for (elem = &allocator->elems[0]; elem < end; elem += elem->block_size) {
  73         if (sshmem_ucx_shadow_is_free(elem) && (elem->block_size >= count)) {
  74             /* found suitable free element */
  75             if (elem->block_size > count) {
  76                 /* create new 'free' element for tail of current buffer */
  77                 sshmem_ucx_shadow_set_elem(elem + count,
  78                                            SSHMEM_UCX_SHADOW_ELEM_FLAG_FREE,
  79                                            elem->block_size - count);
  80             }
  81 
  82             /* set the size and flags of the allocated element */
  83             sshmem_ucx_shadow_set_elem(elem, 0, count);
  84             *index = elem - &allocator->elems[0];
  85             return OSHMEM_SUCCESS;
  86         }
  87     }
  88 
  89     return OSHMEM_ERR_OUT_OF_RESOURCE;
  90 }
  91 
  92 static void sshmem_ucx_shadow_merge_blocks(sshmem_ucx_shadow_allocator_t *allocator)
  93 {
  94     sshmem_ucx_shadow_alloc_elem_t *elem = &allocator->elems[0];
  95     sshmem_ucx_shadow_alloc_elem_t *end  = &allocator->elems[allocator->num_elems];
  96     sshmem_ucx_shadow_alloc_elem_t *next_elem;
  97 
  98     while ( (next_elem = (elem + elem->block_size)) < end) {
  99         if (sshmem_ucx_shadow_is_free(elem) && sshmem_ucx_shadow_is_free(next_elem)) {
 100             /* current & next elements are free, should be merged */
 101             elem->block_size += next_elem->block_size;
 102             /* clean element which is merged */
 103             sshmem_ucx_shadow_set_elem(next_elem, 0, 0);
 104         } else {
 105             elem = next_elem;
 106         }
 107     }
 108 }
 109 
 110 
 111 
 112 int sshmem_ucx_shadow_realloc(sshmem_ucx_shadow_allocator_t *allocator,
 113                               unsigned count, unsigned old_index, unsigned *index,
 114                               int *inplace)
 115 {
 116     sshmem_ucx_shadow_alloc_elem_t *elem = &allocator->elems[old_index];
 117     unsigned old_count                   = elem->block_size;
 118     sshmem_ucx_shadow_alloc_elem_t *end;
 119     sshmem_ucx_shadow_alloc_elem_t *next;
 120 
 121     assert(count > 0);
 122     assert(!sshmem_ucx_shadow_is_free(elem));
 123 
 124     *inplace = 1;
 125 
 126     if (count == old_count) {
 127         *index = old_index;
 128         return OSHMEM_SUCCESS;
 129     }
 130 
 131     if (count < old_count) {
 132         /* requested block is shorter than allocated block
 133          * then just cut current buffer */
 134         sshmem_ucx_shadow_set_elem(elem + count,
 135                                    SSHMEM_UCX_SHADOW_ELEM_FLAG_FREE,
 136                                    elem->block_size - count);
 137         elem->block_size = count;
 138         *index           = old_index;
 139         sshmem_ucx_shadow_merge_blocks(allocator);
 140         return OSHMEM_SUCCESS;
 141     }
 142 
 143     assert(count > old_count);
 144 
 145     end  = &allocator->elems[allocator->num_elems];
 146     next = &elem[old_count];
 147     /* try to check if next element is free & has enough length */
 148     if ((next < end) &&                    /* non-last element? */
 149         sshmem_ucx_shadow_is_free(next) && /* next is free */
 150         (old_count + next->block_size >= count))
 151     {
 152         assert(elem < next);
 153         assert(elem + count > next);
 154         assert(elem + count <= end);
 155         assert(next + next->block_size <= end);
 156 
 157         if (old_count + next->block_size > count) {
 158             sshmem_ucx_shadow_set_elem(elem + count, SSHMEM_UCX_SHADOW_ELEM_FLAG_FREE,
 159                                        old_count + next->block_size - count);
 160         }
 161 
 162         sshmem_ucx_shadow_set_elem(next, 0, 0);
 163         elem->block_size = count;
 164         *index           = old_index;
 165         return OSHMEM_SUCCESS;
 166     }
 167 
 168     *inplace = 0;
 169     return sshmem_ucx_shadow_alloc(allocator, count, index);
 170 }
 171 
 172 int sshmem_ucx_shadow_free(sshmem_ucx_shadow_allocator_t *allocator,
 173                            unsigned index)
 174 {
 175     sshmem_ucx_shadow_alloc_elem_t *elem = &allocator->elems[index];
 176 
 177     elem->flags |= SSHMEM_UCX_SHADOW_ELEM_FLAG_FREE;
 178     sshmem_ucx_shadow_merge_blocks(allocator);
 179     return OSHMEM_SUCCESS;
 180 }
 181 
 182 unsigned sshmem_ucx_shadow_size(sshmem_ucx_shadow_allocator_t *allocator,
 183                                 unsigned index)
 184 {
 185     sshmem_ucx_shadow_alloc_elem_t *elem = &allocator->elems[index];
 186 
 187     assert(!sshmem_ucx_shadow_is_free(elem));
 188     return elem->block_size;
 189 }

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