|
| 1 | +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ |
| 2 | +/* |
| 3 | + * Copyright (c) 2009-2012 Oak Ridge National Laboratory. All rights reserved. |
| 4 | + * Copyright (c) 2009-2012 Mellanox Technologies. All rights reserved. |
| 5 | + * Copyright (c) 2015 Research Organization for Information Science |
| 6 | + * and Technology (RIST). All rights reserved. |
| 7 | + * $COPYRIGHT$ |
| 8 | + * |
| 9 | + * Additional copyrights may follow |
| 10 | + * |
| 11 | + * $HEADER$ |
| 12 | + */ |
| 13 | + |
| 14 | + |
| 15 | +#include "ompi_config.h" |
| 16 | +#include <stdlib.h> |
| 17 | + |
| 18 | +#include "coll_ml.h" |
| 19 | +#include "coll_ml_inlines.h" |
| 20 | +#include "coll_ml_allocation.h" |
| 21 | + |
| 22 | +mca_bcol_base_memory_block_desc_t *mca_coll_ml_allocate_block(struct mca_coll_ml_component_t *ml_component, |
| 23 | + mca_bcol_base_memory_block_desc_t *ml_memblock) |
| 24 | +{ |
| 25 | + mca_bcol_base_memory_block_desc_t *ret = NULL; |
| 26 | + mca_bcol_base_memory_block_desc_t *memory_block = NULL; |
| 27 | + mca_coll_ml_lmngr_t *memory_manager = NULL; |
| 28 | + |
| 29 | + if (ml_memblock) { |
| 30 | + ML_ERROR(("Memory already allocated - expecting NULL pointer")); |
| 31 | + return ret; |
| 32 | + } |
| 33 | + memory_block = (mca_bcol_base_memory_block_desc_t*) calloc(1, sizeof(mca_bcol_base_memory_block_desc_t)); |
| 34 | + |
| 35 | + if (NULL == memory_block){ |
| 36 | + ML_ERROR(("Couldn't allocate memory for ml_memblock")); |
| 37 | + return ret; |
| 38 | + } |
| 39 | + |
| 40 | + memory_manager = &ml_component->memory_manager; |
| 41 | + memory_block->block = mca_coll_ml_lmngr_alloc(memory_manager); |
| 42 | + memory_block->size_block = memory_manager->list_block_size; |
| 43 | + |
| 44 | + if (!memory_block->block){ |
| 45 | + ML_VERBOSE(1, ("lmngr failed.")); |
| 46 | + ret = NULL; |
| 47 | + goto exit_ERROR; |
| 48 | + } |
| 49 | + |
| 50 | + return memory_block; |
| 51 | + |
| 52 | +exit_ERROR: |
| 53 | + if (memory_block){ |
| 54 | + free(memory_block); |
| 55 | + return ret; |
| 56 | + } |
| 57 | + |
| 58 | + return ret; |
| 59 | +} |
| 60 | + |
| 61 | +void mca_coll_ml_free_block (mca_bcol_base_memory_block_desc_t *ml_memblock) |
| 62 | +{ |
| 63 | + if (!ml_memblock) |
| 64 | + return; |
| 65 | + |
| 66 | + if (ml_memblock->buffer_descs){ |
| 67 | + free(ml_memblock->buffer_descs); |
| 68 | + } |
| 69 | + |
| 70 | + mca_coll_ml_lmngr_free(ml_memblock->block); |
| 71 | + free(ml_memblock->bank_release_counters); |
| 72 | + free(ml_memblock->ready_for_memsync); |
| 73 | + free(ml_memblock->bank_is_busy); |
| 74 | + free(ml_memblock); |
| 75 | +} |
| 76 | + |
| 77 | +int mca_coll_ml_initialize_block(mca_bcol_base_memory_block_desc_t *ml_memblock, |
| 78 | + uint32_t num_buffers, |
| 79 | + uint32_t num_banks, |
| 80 | + uint32_t buffer_size, |
| 81 | + int32_t data_offset, |
| 82 | + opal_list_t *bcols_in_use) |
| 83 | +{ |
| 84 | + int ret = OMPI_SUCCESS; |
| 85 | + uint32_t bank_loop, buff_loop; |
| 86 | + uint64_t addr_offset = 0; |
| 87 | + mca_bcol_base_payload_buffer_desc_t *pbuff_descs = NULL,*pbuff_desc = NULL; |
| 88 | + |
| 89 | + if (0 == num_banks || 0 == num_buffers || 0 == buffer_size) { |
| 90 | + return OMPI_ERR_BAD_PARAM; |
| 91 | + } |
| 92 | + |
| 93 | + if (NULL == ml_memblock){ |
| 94 | + ML_ERROR(("Memory block not initialized")); |
| 95 | + ret = OMPI_ERROR; |
| 96 | + goto exit_ERROR; |
| 97 | + } |
| 98 | + |
| 99 | + if (ml_memblock->size_block < (num_buffers * num_banks * buffer_size) ){ |
| 100 | + ML_ERROR(("Not enough memory for all buffers and banks in the memory block")); |
| 101 | + ret = OMPI_ERROR; |
| 102 | + goto exit_ERROR; |
| 103 | + } |
| 104 | + |
| 105 | + pbuff_descs = (mca_bcol_base_payload_buffer_desc_t*) malloc(sizeof(mca_bcol_base_payload_buffer_desc_t) |
| 106 | + * num_banks * num_buffers); |
| 107 | + if (NULL == pbuff_descs) { |
| 108 | + return OMPI_ERR_OUT_OF_RESOURCE; |
| 109 | + } |
| 110 | + |
| 111 | + for(bank_loop = 0; bank_loop < num_banks; bank_loop++) |
| 112 | + for(buff_loop = 0; buff_loop < num_buffers; buff_loop++){ |
| 113 | + pbuff_desc = &pbuff_descs[bank_loop*num_buffers + buff_loop]; |
| 114 | + |
| 115 | + pbuff_desc->base_data_addr = (void *) |
| 116 | + ((char *)ml_memblock->block->base_addr + addr_offset); |
| 117 | + pbuff_desc->data_addr = (void *) |
| 118 | + ((char *)pbuff_desc->base_data_addr + (size_t)data_offset); |
| 119 | + |
| 120 | + addr_offset+=buffer_size; |
| 121 | + pbuff_desc->buffer_index = BUFFER_INDEX(bank_loop,num_buffers,buff_loop); |
| 122 | + |
| 123 | + pbuff_desc->bank_index=bank_loop; |
| 124 | + pbuff_desc->generation_number=0; |
| 125 | + } |
| 126 | + |
| 127 | + /* Initialize ml memory block */ |
| 128 | + /* gvm FIX:This counter when zero indicates that the bank is ready for |
| 129 | + * recycle. This is initialized to number of bcol components as each bcol is responsible for |
| 130 | + * releasing the buffers of a bank. This initialization will have |
| 131 | + * faulty behavior, example in case of multiple interfaces, when more than |
| 132 | + * one bcol module of the component type is in use. |
| 133 | + */ |
| 134 | + ml_memblock->bank_release_counters = (uint32_t *) calloc(num_banks, sizeof(uint32_t)); |
| 135 | + if (NULL == ml_memblock->bank_release_counters) { |
| 136 | + ret = OMPI_ERR_OUT_OF_RESOURCE; |
| 137 | + goto exit_ERROR; |
| 138 | + } |
| 139 | + |
| 140 | + ml_memblock->ready_for_memsync = (bool *) calloc(num_banks, sizeof(bool)); |
| 141 | + if (NULL == ml_memblock->ready_for_memsync) { |
| 142 | + ret = OMPI_ERR_OUT_OF_RESOURCE; |
| 143 | + goto exit_ERROR; |
| 144 | + } |
| 145 | + |
| 146 | + ml_memblock->bank_is_busy = (bool *) calloc(num_banks, sizeof(bool)); |
| 147 | + if (NULL == ml_memblock->bank_is_busy) { |
| 148 | + ret = OMPI_ERR_OUT_OF_RESOURCE; |
| 149 | + goto exit_ERROR; |
| 150 | + } |
| 151 | + |
| 152 | + /* Set index for first bank to sync */ |
| 153 | + ml_memblock->memsync_counter = 0; |
| 154 | + |
| 155 | + /* use first bank and first buffer */ |
| 156 | + ml_memblock->next_free_buffer = 0; |
| 157 | + |
| 158 | + ml_memblock->block_addr_offset = addr_offset; |
| 159 | + ml_memblock->num_buffers_per_bank = num_buffers; |
| 160 | + ml_memblock->num_banks = num_banks; |
| 161 | + ml_memblock->size_buffer = buffer_size; |
| 162 | + ml_memblock->buffer_descs = pbuff_descs; |
| 163 | + |
| 164 | + return ret; |
| 165 | + |
| 166 | +exit_ERROR: |
| 167 | + /* Free all buffer descriptors */ |
| 168 | + if (pbuff_descs){ |
| 169 | + free(pbuff_descs); |
| 170 | + } |
| 171 | + |
| 172 | + return ret; |
| 173 | +} |
| 174 | + |
| 175 | +mca_bcol_base_payload_buffer_desc_t *mca_coll_ml_alloc_buffer (mca_coll_ml_module_t *module) |
| 176 | +{ |
| 177 | + uint64_t bindex; |
| 178 | + uint32_t bank, buffer, num_buffers; |
| 179 | + mca_bcol_base_memory_block_desc_t *ml_memblock = module->payload_block; |
| 180 | + mca_bcol_base_payload_buffer_desc_t *pbuff_descs = NULL, |
| 181 | + *ml_membuffer = NULL; |
| 182 | + |
| 183 | + /* Return a buffer */ |
| 184 | + num_buffers = ml_memblock->num_buffers_per_bank; |
| 185 | + pbuff_descs = ml_memblock->buffer_descs; |
| 186 | + bindex = ml_memblock->next_free_buffer; |
| 187 | + buffer = bindex % num_buffers; |
| 188 | + bank = bindex/num_buffers; |
| 189 | + |
| 190 | + ML_VERBOSE(10, ("ML allocator: allocating buffer index %d, bank index %d", buffer, bank)); |
| 191 | + |
| 192 | + /* First buffer in bank, use next bank */ |
| 193 | + if (0 == buffer) { |
| 194 | + if(!ml_memblock->bank_is_busy[bank]) { |
| 195 | + /* the bank is free, mark it busy */ |
| 196 | + ml_memblock->bank_is_busy[bank] = true; |
| 197 | + ML_VERBOSE(10, ("ML allocator: reset bank %d to value %d", bank, |
| 198 | + ml_memblock->bank_release_counters[bank])); |
| 199 | + } else { |
| 200 | + /* the bank is busy, return NULL and upper layer will handle it */ |
| 201 | + ML_VERBOSE(10, ("No free payload buffers are available for use." |
| 202 | + " Next memory bank is still used by one of bcols")); |
| 203 | + return NULL; |
| 204 | + } |
| 205 | + } |
| 206 | + |
| 207 | + assert(true == ml_memblock->bank_is_busy[bank]); |
| 208 | + |
| 209 | + ml_membuffer = &pbuff_descs[bindex]; |
| 210 | + ML_VERBOSE(10, ("ML allocator: ml buffer index %d", bindex)); |
| 211 | + |
| 212 | + /* Compute next free buffer */ |
| 213 | + buffer = (buffer == num_buffers - 1) ? 0 : buffer + 1; |
| 214 | + if (0 == buffer) { |
| 215 | + bank = (bank == ml_memblock->num_banks - 1) ? 0 : bank + 1; |
| 216 | + } |
| 217 | + |
| 218 | + ml_memblock->next_free_buffer = BUFFER_INDEX(bank,num_buffers,buffer); |
| 219 | + |
| 220 | + return ml_membuffer; |
| 221 | +} |
0 commit comments