1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ 2 /* 3 * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana 4 * University Research and Technology 5 * Corporation. All rights reserved. 6 * Copyright (c) 2004-2005 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) 2015 Los Alamos National Security, LLC. All rights 14 * reseved. 15 * $COPYRIGHT$ 16 * 17 * Additional copyrights may follow 18 * 19 * $HEADER$ 20 */ 21 22 /** @file 23 * A generic memory bucket allocator. 24 **/ 25 26 #ifndef ALLOCATOR_BUCKET_ALLOC_H 27 #define ALLOCATOR_BUCKET_ALLOC_H 28 29 #include "opal_config.h" 30 #include <stdlib.h> 31 #include <string.h> 32 #include "opal/threads/mutex.h" 33 #include "opal/mca/allocator/allocator.h" 34 35 BEGIN_C_DECLS 36 37 /** 38 * Structure for the header of each memory chunk 39 */ 40 struct mca_allocator_bucket_chunk_header_t { 41 struct mca_allocator_bucket_chunk_header_t * next_in_segment; 42 /**< The next chunk in the memory segment */ 43 /** 44 * Union which holds either a pointer to the next free chunk 45 * or the bucket number. Based on the current location of the chunk 46 * we use one or the other of these fields. If the chunk is owned 47 * by the user, then the bucket field is set, which allow us to know 48 * in which specific bucket we have to put it back on free (as the 49 * chunk don't have the size attached). When the allocator own the 50 * chunk, the next_free fild is used, which allow us to put these 51 * chunks a list of free elements. 52 */ 53 union u { 54 struct mca_allocator_bucket_chunk_header_t * next_free; 55 /**< if the chunk is free this will point to the next free chunk in the bucket */ 56 int bucket; /**< the bucket number it belongs to */ 57 } u; /**< the union */ 58 }; 59 /** 60 * Typedef so we don't have to use struct 61 */ 62 typedef struct mca_allocator_bucket_chunk_header_t mca_allocator_bucket_chunk_header_t; 63 64 /** 65 * Structure that heads each segment 66 */ 67 struct mca_allocator_bucket_segment_head_t { 68 struct mca_allocator_bucket_chunk_header_t * first_chunk; /**< the first chunk of the header */ 69 struct mca_allocator_bucket_segment_head_t * next_segment; /**< the next segment in the 70 bucket */ 71 }; 72 /** 73 * Typedef so we don't have to use struct 74 */ 75 typedef struct mca_allocator_bucket_segment_head_t mca_allocator_bucket_segment_head_t; 76 77 /** 78 * Structure for each bucket 79 */ 80 struct mca_allocator_bucket_bucket_t { 81 mca_allocator_bucket_chunk_header_t * free_chunk; /**< the first free chunk of memory */ 82 opal_mutex_t lock; /**< the lock on the bucket */ 83 mca_allocator_bucket_segment_head_t * segment_head; /**< the list of segment headers */ 84 }; 85 /** 86 * Typedef so we don't have to use struct 87 */ 88 typedef struct mca_allocator_bucket_bucket_t mca_allocator_bucket_bucket_t; 89 90 /** 91 * Structure that holds the necessary information for each area of memory 92 */ 93 struct mca_allocator_bucket_t { 94 mca_allocator_base_module_t super; /**< makes this a child of class mca_allocator_t */ 95 mca_allocator_bucket_bucket_t * buckets; /**< the array of buckets */ 96 int num_buckets; /**< the number of buckets */ 97 mca_allocator_base_component_segment_alloc_fn_t get_mem_fn; 98 /**< pointer to the function to get more memory */ 99 mca_allocator_base_component_segment_free_fn_t free_mem_fn; 100 /**< pointer to the function to free memory */ 101 }; 102 /** 103 * Typedef so we don't have to use struct 104 */ 105 typedef struct mca_allocator_bucket_t mca_allocator_bucket_t; 106 107 /** 108 * Initializes the mca_allocator_bucket_options_t data structure for the passed 109 * parameters. 110 * @param mem a pointer to the mca_allocator_t struct to be filled in 111 * @param num_buckets The number of buckets the allocator will use 112 * @param get_mem_funct A pointer to the function that the allocator 113 * will use to get more memory 114 * @param free_mem_funct A pointer to the function that the allocator 115 * will use to free memory 116 * 117 * @retval Pointer to the initialized mca_allocator_bucket_options_t structure 118 * @retval NULL if there was an error 119 */ 120 mca_allocator_bucket_t *mca_allocator_bucket_init(mca_allocator_base_module_t * mem, 121 int num_buckets, 122 mca_allocator_base_component_segment_alloc_fn_t get_mem_funct, 123 mca_allocator_base_component_segment_free_fn_t free_mem_funct); 124 /** 125 * Accepts a request for memory in a specific region defined by the 126 * mca_allocator_bucket_options_t struct and returns a pointer to memory in that 127 * region or NULL if there was an error 128 * 129 * @param mem A pointer to the appropriate struct for the area of memory. 130 * @param size The size of the requested area of memory 131 * 132 * @retval Pointer to the area of memory if the allocation was successful 133 * @retval NULL if the allocation was unsuccessful 134 */ 135 void * mca_allocator_bucket_alloc( 136 mca_allocator_base_module_t * mem, 137 size_t size); 138 139 /** 140 * Accepts a request for memory in a specific region defined by the 141 * mca_allocator_bucket_options_t struct and aligned by the specified amount and 142 * returns a pointer to memory in that region or NULL if there was an error 143 * 144 * @param mem A pointer to the appropriate struct for the area of 145 * memory. 146 * @param size The size of the requested area of memory 147 * @param alignment The requested alignment of the new area of memory. This 148 * MUST be a power of 2. 149 * 150 * @retval Pointer to the area of memory if the allocation was successful 151 * @retval NULL if the allocation was unsuccessful 152 * 153 */ 154 void * mca_allocator_bucket_alloc_align( 155 mca_allocator_base_module_t * mem, 156 size_t size, 157 size_t alignment); 158 159 /** 160 * Attempts to resize the passed region of memory into a larger or a smaller 161 * region. If it is unsuccessful, it will return NULL and the passed area of 162 * memory will be untouched. 163 * 164 * @param mem A pointer to the appropriate struct for the area of 165 * memory. 166 * @param size The size of the requested area of memory 167 * @param ptr A pointer to the region of memory to be resized 168 * 169 * @retval Pointer to the area of memory if the reallocation was successful 170 * @retval NULL if the allocation was unsuccessful 171 * 172 */ 173 void * mca_allocator_bucket_realloc( 174 mca_allocator_base_module_t * mem, 175 void * ptr, 176 size_t size); 177 178 /** 179 * Frees the passed region of memory 180 * 181 * @param mem A pointer to the appropriate struct for the area of 182 * memory. 183 * @param ptr A pointer to the region of memory to be freed 184 * 185 * @retval None 186 * 187 */ 188 void mca_allocator_bucket_free(mca_allocator_base_module_t * mem, 189 void * ptr); 190 191 /** 192 * Frees all the memory from all the buckets back to the system. Note that 193 * this function only frees memory that was previously freed with 194 * mca_allocator_bucket_free(). 195 * 196 * @param mem A pointer to the appropriate struct for the area of 197 * memory. 198 * 199 * @retval None 200 * 201 */ 202 int mca_allocator_bucket_cleanup(mca_allocator_base_module_t * mem); 203 204 /** 205 * Cleanup all resources held by this allocator. 206 * 207 * @param mem A pointer to the appropriate struct for the area of 208 * memory. 209 * 210 * @retval None 211 * 212 */ 213 int mca_allocator_bucket_finalize(mca_allocator_base_module_t * mem); 214 215 OPAL_DECLSPEC extern mca_allocator_base_component_t mca_allocator_bucket_component; 216 217 END_C_DECLS 218 219 #endif /* ALLOCATOR_BUCKET_ALLOC_H */