From 1c5a7ce4767c024192e86a85978f8d3c683f86bc Mon Sep 17 00:00:00 2001 From: Tim Prins Date: Wed, 16 Jun 2004 15:53:55 +0000 Subject: [PATCH] First commit of the bucket allocator component. This commit was SVN r1316. --- src/mca/allocator/bucket/Makefile.am | 39 +++ src/mca/allocator/bucket/VERSION | 6 + src/mca/allocator/bucket/allocator_bucket.c | 93 +++++ .../allocator/bucket/allocator_bucket_alloc.c | 331 ++++++++++++++++++ .../allocator/bucket/allocator_bucket_alloc.h | 196 +++++++++++ src/mca/allocator/bucket/configure.params | 10 + 6 files changed, 675 insertions(+) create mode 100644 src/mca/allocator/bucket/Makefile.am create mode 100644 src/mca/allocator/bucket/VERSION create mode 100644 src/mca/allocator/bucket/allocator_bucket.c create mode 100644 src/mca/allocator/bucket/allocator_bucket_alloc.c create mode 100644 src/mca/allocator/bucket/allocator_bucket_alloc.h create mode 100644 src/mca/allocator/bucket/configure.params diff --git a/src/mca/allocator/bucket/Makefile.am b/src/mca/allocator/bucket/Makefile.am new file mode 100644 index 0000000000..104e8bdaab --- /dev/null +++ b/src/mca/allocator/bucket/Makefile.am @@ -0,0 +1,39 @@ +# -*- makefile -*- +# +# $HEADER$ +# + +include $(top_ompi_srcdir)/config/Makefile.options + +# According to the MCA spec, we have to make the output library here +# in the top-level directory, and it has to be named +# libompi_ssi_coll_ompi_basic.la + +if OMPI_BUILD_allocator_bucket_LOADABLE_MODULE +module_noinst = +module_install = mca_allocator_bucket.la +else +module_noinst = libmca_allocator_bucket.la +module_install = +endif + +mcamoduledir = $(libdir)/ompi +mcamodule_LTLIBRARIES = $(module_install) +mca_allocator_bucket_la_SOURCES = +mca_allocator_bucket_la_LIBADD = \ + src/libmca_allocator_bucket.la \ + $(LIBOMPI_LA) +mca_allocator_bucket_la_LDFLAGS = -module -avoid-version + +libmca_allocator_bucket_la_LDFLAGS = -module -avoid-version + +AM_CPPFLAGS = \ + -I$(top_ompi_builddir)/src/include \ + -I$(top_ompi_srcdir)/src \ + -I$(top_ompi_srcdir)/src/include + +noinst_LTLIBRARIES = libmca_allocator_bucket.la +libmca_allocator_bucket_la_SOURCES = \ + allocator_bucket.c \ + allocator_bucket_alloc.h \ + allocator_bucket_alloc.c diff --git a/src/mca/allocator/bucket/VERSION b/src/mca/allocator/bucket/VERSION new file mode 100644 index 0000000000..dadc1f42ab --- /dev/null +++ b/src/mca/allocator/bucket/VERSION @@ -0,0 +1,6 @@ +major=1 +minor=0 +release=0 +alpha=0 +beta=0 +svn=1 diff --git a/src/mca/allocator/bucket/allocator_bucket.c b/src/mca/allocator/bucket/allocator_bucket.c new file mode 100644 index 0000000000..23577045a9 --- /dev/null +++ b/src/mca/allocator/bucket/allocator_bucket.c @@ -0,0 +1,93 @@ +#include "mca/allocator/allocator.h" +#include "include/constants.h" +#include "mca/base/mca_base_param.h" +#include "mca/allocator/bucket/allocator_bucket_alloc.h" + +struct mca_allocator_t* mca_allocator_bucket_module_init( + bool *allow_multi_user_threads, + mca_allocator_segment_alloc_fn_t segment_alloc, + mca_allocator_segment_free_fn_t segment_free); + +int mca_allocator_bucket_module_open(void); + +int mca_allocator_bucket_module_close(void); + +void * mca_allocator_bucket_alloc_wrapper(struct mca_allocator_t* allocator, + size_t size, size_t align); + +struct mca_allocator_t* mca_allocator_bucket_module_init( + bool *allow_multi_user_threads, + mca_allocator_segment_alloc_fn_t segment_alloc, + mca_allocator_segment_free_fn_t segment_free) +{ + int num_buckets = 30; + int id; + size_t alloc_size = sizeof(mca_allocator_bucket_t); + mca_allocator_bucket_t * retval; + mca_allocator_bucket_t * allocator = segment_alloc(&alloc_size); + if(NULL == allocator) { + return(NULL); + } + id = mca_base_param_register_int("allocator","bucket","num_buckets", + NULL,num_buckets); + mca_base_param_lookup_int(id,&num_buckets); + + retval = mca_allocator_bucket_init((mca_allocator_t *) allocator, num_buckets, + segment_alloc, segment_free); + if(NULL == retval) { + segment_free(allocator); + return(NULL); + } + allocator->super.alc_alloc = mca_allocator_bucket_alloc_wrapper; + allocator->super.alc_realloc = mca_allocator_bucket_realloc; + allocator->super.alc_free = mca_allocator_bucket_free; + allocator->super.alc_finalize = mca_allocator_bucket_cleanup; + + return((mca_allocator_t *) allocator); +} + +int mca_allocator_bucket_module_open(void) { + + return(OMPI_SUCCESS); +} + +int mca_allocator_bucket_module_close(void) { + return(OMPI_SUCCESS); +} + +void * mca_allocator_bucket_alloc_wrapper(struct mca_allocator_t* allocator, + size_t size, size_t align) +{ + if(0 == align){ + return(mca_allocator_bucket_alloc(allocator, size)); + } + return(mca_allocator_bucket_alloc_align(allocator, size, align)); +} + + +mca_allocator_base_module_t mca_allocator_bucket_module = { + /* 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, + + "bucket", /* MCA module name */ + 1, /* MCA module major version */ + 0, /* MCA module minor version */ + 0, /* MCA module release version */ + mca_allocator_bucket_module_open, /* module open */ + mca_allocator_bucket_module_close /* module close */ + }, + + /* Next the MCA v1.0.0 module meta data */ + + { + /* Whether the module is checkpointable or not */ + false + }, + mca_allocator_bucket_module_init +}; + diff --git a/src/mca/allocator/bucket/allocator_bucket_alloc.c b/src/mca/allocator/bucket/allocator_bucket_alloc.c new file mode 100644 index 0000000000..86304fcb75 --- /dev/null +++ b/src/mca/allocator/bucket/allocator_bucket_alloc.c @@ -0,0 +1,331 @@ +/* + * $HEADER$ + */ + +#include "mca/allocator/bucket/allocator_bucket_alloc.h" +#include +/** + * The define controls the size in bytes of the 1st bucket and hence every one + * afterwards. + */ +#define MCA_ALLOCATOR_BUCKET_1_SIZE 8 +/** + * This is the number of left bit shifts from 1 needed to get to the number of + * bytes in the initial memory buckets + */ +#define MCA_ALLOCATOR_BUCKET_1_BITSHIFTS 3 + + /* + * Initializes the mca_allocator_bucket_options_t data structure for the passed + * parameters. + */ +mca_allocator_bucket_t * mca_allocator_bucket_init(mca_allocator_t * mem, + int num_buckets, + mca_allocator_segment_alloc_fn_t get_mem_funct, + mca_allocator_segment_free_fn_t free_mem_funct) +{ + mca_allocator_bucket_t * mem_options = (mca_allocator_bucket_t *) mem; + int i; + size_t size; + /* if a bad value is used for the number of buckets, default to 30 */ + if(i <= 0) { + num_buckets = 30; + } + /* initialize the array of buckets */ + size = sizeof(mca_allocator_bucket_bucket_t) * num_buckets; + mem_options->buckets = (mca_allocator_bucket_bucket_t*) get_mem_funct(&size); + if(NULL == mem_options->buckets) { + return(NULL); + } + for(i = 0; i < num_buckets; i++) { + mem_options->buckets[i].free_chunk = NULL; + mem_options->buckets[i].segment_head = NULL; + OBJ_CONSTRUCT(&(mem_options->buckets[i].lock), ompi_mutex_t); + } + mem_options->num_buckets = num_buckets; + mem_options->get_mem_fn = get_mem_funct; + mem_options->free_mem_fn = free_mem_funct; + return(mem_options); +} + +/* + * Accepts a request for memory in a specific region defined by the + * mca_allocator_bucket_options_t struct and returns a pointer to memory in that + * region or NULL if there was an error + * + */ +void * mca_allocator_bucket_alloc(mca_allocator_t * mem, size_t size) +{ + mca_allocator_bucket_t * mem_options = (mca_allocator_bucket_t *) mem; + int bucket_num = 0; + /* initialize for the later bit shifts */ + size_t bucket_size = 1; + size_t allocated_size; + mca_allocator_bucket_chunk_header_t * chunk; + mca_allocator_bucket_chunk_header_t * first_chunk; + mca_allocator_bucket_segment_head_t * segment_header; + /* add the size of the header into the amount we need to request */ + size += sizeof(mca_allocator_bucket_chunk_header_t); + /* figure out which bucket it will come from. */ + while(size > MCA_ALLOCATOR_BUCKET_1_SIZE) { + size >>= 1; + bucket_num++; + } + /* now that we know what bucket it will come from, we must get the lock */ + THREAD_LOCK(&(mem_options->buckets[bucket_num].lock)); + /* see if there is already a free chunk */ + if(NULL != mem_options->buckets[bucket_num].free_chunk) { + chunk = mem_options->buckets[bucket_num].free_chunk; + mem_options->buckets[bucket_num].free_chunk = chunk->u.next_free; + chunk->u.bucket = bucket_num; + /* go past the header */ + chunk += 1; + /*release the lock */ + THREAD_UNLOCK(&(mem_options->buckets[bucket_num].lock)); + return((void *) chunk); + } + /* figure out the size of bucket we need */ + bucket_size <<= (bucket_num + MCA_ALLOCATOR_BUCKET_1_BITSHIFTS); + allocated_size = bucket_size; + /* we have to add in the size of the segment header into the + * amount we need to request */ + allocated_size += sizeof(mca_allocator_bucket_segment_head_t); + /* attempt to get the memory */ + segment_header = (mca_allocator_bucket_segment_head_t *) + mem_options->get_mem_fn(&allocated_size); + if(NULL == segment_header) { + /* release the lock */ + THREAD_UNLOCK(&(mem_options->buckets[bucket_num].lock)); + return(NULL); + } + /* if were allocated more memory then we actually need, then we will try to + * break it up into multiple chunks in the current bucket */ + allocated_size -= (sizeof(mca_allocator_bucket_segment_head_t) + bucket_size); + chunk = first_chunk = segment_header->first_chunk = + (mca_allocator_bucket_chunk_header_t *) (segment_header + 1); + /* add the segment into the segment list */ + segment_header->next_segment = mem_options->buckets[bucket_num].segment_head; + mem_options->buckets[bucket_num].segment_head = segment_header; + if(allocated_size >= bucket_size) { + mem_options->buckets[bucket_num].free_chunk = + (mca_allocator_bucket_chunk_header_t *) ((char *) chunk + bucket_size); + chunk->next_in_segment = (mca_allocator_bucket_chunk_header_t *) + ((char *)chunk + bucket_size); + while(allocated_size >= bucket_size) { + chunk = (mca_allocator_bucket_chunk_header_t *) ((char *) chunk + bucket_size); + chunk->u.next_free = (mca_allocator_bucket_chunk_header_t *) + ((char *) chunk + bucket_size); + chunk->next_in_segment = chunk->u.next_free; + allocated_size -= bucket_size; + } + chunk->next_in_segment = first_chunk; + chunk->u.next_free = NULL; + } else { + first_chunk->next_in_segment = first_chunk; + } + first_chunk->u.bucket = bucket_num; + THREAD_UNLOCK(&(mem_options->buckets[bucket_num].lock)); + /* return the memory moved past the header */ + return((void *) (first_chunk + 1)); +} + +/* + * allocates an aligned region of memory + */ +void * mca_allocator_bucket_alloc_align(mca_allocator_t * mem, size_t size, size_t alignment) +{ + /** + * not yet working correctly + **/ + mca_allocator_bucket_t * mem_options = (mca_allocator_bucket_t *) mem; + int bucket_num = 1; + void * ptr; + size_t aligned_max_size, bucket_size; + size_t alignment_off, allocated_size; + mca_allocator_bucket_chunk_header_t * chunk; + mca_allocator_bucket_chunk_header_t * first_chunk; + mca_allocator_bucket_segment_head_t * segment_header; + char * aligned_memory; + + /* since we do not have a way to get pre aligned memory, we need to request + * a chunk then return an aligned spot in it. In the worst case we need + * the requested size plus the alignment and the header size */ + aligned_max_size = size + alignment + sizeof(mca_allocator_bucket_chunk_header_t) + + sizeof(mca_allocator_bucket_segment_head_t); + bucket_size = size; + allocated_size = aligned_max_size; + /* get some memory */ + ptr = mem_options->get_mem_fn(&allocated_size); + if(NULL == ptr) { + return(NULL); + } + /* the first part of the memory is the segment header */ + segment_header = (mca_allocator_bucket_segment_head_t *) ptr; + /* we temporarily define the first chunk to be right after the segment_header */ + first_chunk = (mca_allocator_bucket_chunk_header_t *) (segment_header + 1); + + /* we want to align the memory right after the header, so we go past the header */ + aligned_memory = (char *) (first_chunk + 1); + /* figure out how much the alignment is off by */ + alignment_off = (unsigned int) aligned_memory % alignment; + printf("%d ", alignment_off); + aligned_memory += alignment_off; + /* we now have an aligned piece of memory. Now we have to put the chunk header + * right before the aligned memory */ + first_chunk = (mca_allocator_bucket_chunk_header_t *) aligned_memory - 1; + while(bucket_size > MCA_ALLOCATOR_BUCKET_1_SIZE) { + bucket_size >>= 1; + bucket_num++; + } + bucket_size = 1; + bucket_size <<= MCA_ALLOCATOR_BUCKET_1_BITSHIFTS + bucket_num; + + /* if were allocated more memory then we actually need, then we will try to + * break it up into multiple chunks in the current bucket */ + allocated_size -= aligned_max_size; + chunk = segment_header->first_chunk = first_chunk; + /* we now need to get a lock on the bucket */ + THREAD_LOCK(&(mem_options->buckets[bucket_num].lock)); + /* add the segment into the segment list */ + segment_header->next_segment = mem_options->buckets[bucket_num].segment_head; + mem_options->buckets[bucket_num].segment_head = segment_header; + printf("break3\n"); + fflush(stdout); + if(allocated_size >= bucket_size) { + mem_options->buckets[bucket_num].free_chunk = + (mca_allocator_bucket_chunk_header_t *) ((char *) chunk + bucket_size); + chunk->next_in_segment = (mca_allocator_bucket_chunk_header_t *) + ((char *)chunk + bucket_size); + while(allocated_size >= bucket_size) { + chunk = (mca_allocator_bucket_chunk_header_t *) ((char *) chunk + bucket_size); + chunk->u.next_free = (mca_allocator_bucket_chunk_header_t *) + ((char *) chunk + bucket_size); + chunk->next_in_segment = chunk->u.next_free; + allocated_size -= bucket_size; + } + chunk->next_in_segment = first_chunk; + chunk->u.next_free = NULL; + } else { + first_chunk->next_in_segment = first_chunk; + } + first_chunk->u.bucket = bucket_num; + THREAD_UNLOCK(&(mem_options->buckets[bucket_num].lock)); + /* return the aligned memory */ + return((void *) (aligned_memory)); +} + +/* + * function to reallocate the segment of memory + */ +void * mca_allocator_bucket_realloc(mca_allocator_t * mem, void * ptr, + size_t size) +{ + mca_allocator_bucket_t * mem_options = (mca_allocator_bucket_t *) mem; + /* initialize for later bit shifts */ + size_t bucket_size = 1; + int bucket_num; + void * ret_ptr; + /* get the header of the chunk */ + mca_allocator_bucket_chunk_header_t * chunk = (mca_allocator_bucket_chunk_header_t *) ptr - 1; + bucket_num = chunk->u.bucket; + + bucket_size <<= (bucket_num + MCA_ALLOCATOR_BUCKET_1_BITSHIFTS); + /* since the header area is not available to the user, we need to + * subtract off the header size */ + bucket_size -= sizeof(mca_allocator_bucket_chunk_header_t); + /* if the requested size is less than or equal to what they ask for, + * just give them back what they passed in */ + if(size <= bucket_size) { + return(ptr); + } + /* we need a new space in memory, so let's get it */ + ret_ptr = mca_allocator_bucket_alloc((mca_allocator_t *) mem_options, size); + if(NULL == ret_ptr) { + return(NULL); + } + /* copy what they have in memory to the new spot */ + memcpy(ret_ptr, ptr, bucket_size); + /* free the old area in memory */ + mca_allocator_bucket_free((mca_allocator_t *) mem_options, ptr); + return(ret_ptr); +} + + +/* + * Frees the passed region of memory + * + */ +void mca_allocator_bucket_free(mca_allocator_t * mem, void * ptr) +{ + mca_allocator_bucket_t * mem_options = (mca_allocator_bucket_t *) mem; + mca_allocator_bucket_chunk_header_t * chunk = (mca_allocator_bucket_chunk_header_t *) ptr - 1; + int bucket_num = chunk->u.bucket; + THREAD_LOCK(&(mem_options->buckets[bucket_num].lock)); + chunk->u.next_free = mem_options->buckets[bucket_num].free_chunk; + mem_options->buckets[bucket_num].free_chunk = chunk; + THREAD_UNLOCK(&(mem_options->buckets[bucket_num].lock)); +} + +/* + * Frees all the memory from all the buckets back to the system. Note that + * this function only frees memory that was previously freed with + * mca_allocator_bucket_free(). + * + */ +int mca_allocator_bucket_cleanup(mca_allocator_t * mem) +{ + mca_allocator_bucket_t * mem_options = (mca_allocator_bucket_t *) mem; + int i; + mca_allocator_bucket_chunk_header_t * next_chunk; + mca_allocator_bucket_chunk_header_t * chunk; + mca_allocator_bucket_chunk_header_t * first_chunk; + mca_allocator_bucket_segment_head_t ** segment_header; + mca_allocator_bucket_segment_head_t * segment; + bool empty = true; + + for(i = 0; i < mem_options->num_buckets; i++) { + THREAD_LOCK(&(mem_options->buckets[i].lock)); + segment_header = &(mem_options->buckets[i].segment_head); + /* traverse the list of segment headers until we hit NULL */ + while(NULL != *segment_header) { + first_chunk = (*segment_header)->first_chunk; + chunk = first_chunk; + /* determine if the segment is free */ + do + { + if(chunk->u.bucket == i) { + empty = false; + } + chunk = chunk->next_in_segment; + } while(empty && (chunk != first_chunk)); + if(empty) { + chunk = first_chunk; + /* remove the chunks from the free list */ + do + { + if(mem_options->buckets[i].free_chunk == chunk) { + mem_options->buckets[i].free_chunk = chunk->u.next_free; + } else { + next_chunk = mem_options->buckets[i].free_chunk; + while(next_chunk->u.next_free != chunk) { + next_chunk = next_chunk->u.next_free; + } + next_chunk->u.next_free = chunk->u.next_free; + } + } while((chunk = chunk->next_in_segment) != first_chunk); + /* set the segment list to point to the next segment */ + segment = *segment_header; + *segment_header = segment->next_segment; + /* free the memory */ + mem_options->free_mem_fn(segment); + } else { + /* go to next segment */ + segment_header = &((*segment_header)->next_segment); + } + empty = true; + } + /* relese the lock on the bucket */ + THREAD_UNLOCK(&(mem_options->buckets[i].lock)); + } + return(OMPI_SUCCESS); +} diff --git a/src/mca/allocator/bucket/allocator_bucket_alloc.h b/src/mca/allocator/bucket/allocator_bucket_alloc.h new file mode 100644 index 0000000000..65e2bf8e34 --- /dev/null +++ b/src/mca/allocator/bucket/allocator_bucket_alloc.h @@ -0,0 +1,196 @@ +/** + * $HEADER$ + */ + +/** @file + * A generic memory allocator. + * + * + **/ + +#ifndef ALLOCATOR_BUCKET_ALLOC_H +#define ALLOCATOR_BUCKET_ALLOC_H + +#include +#include +#include +#include "threads/mutex.h" +#include "class/ompi_object.h" +#include "mca/allocator/allocator.h" + +/** + * Typedef so we can add a pointer to mca_allocator_bucket_chunk_header_t in + * mca_allocator_bucket_chunk_header_t + */ +typedef struct mca_allocator_bucket_chunk_header_t * mca_allocator_bucket_chunk_header_ptr_t; + +/** + * Structure for the header of each memory chunk + */ +struct mca_allocator_bucket_chunk_header_t { + mca_allocator_bucket_chunk_header_ptr_t next_in_segment; /**< The next chunk in the + memory segment */ + /** + * Union which holds either a pointer to the next free chunk + * or the bucket number + */ + union u { + mca_allocator_bucket_chunk_header_ptr_t next_free; /**< if the chunk is free this + will point to the next free + chunk in the bucket */ + int bucket; /**< the bucket number it belongs to */ + } u; /**< the union */ +}; + /** + * Typedef so we don't have to use struct + */ +typedef struct mca_allocator_bucket_chunk_header_t mca_allocator_bucket_chunk_header_t; + +/** + * Typedef so we can reference a pointer to mca_allocator_bucket_segment_head_t from itself + */ +typedef struct mca_allocator_bucket_segment_head_t * mca_allocator_bucket_segment_head_ptr; + +/** + * Structure that heads each segment + */ +struct mca_allocator_bucket_segment_head_t { + mca_allocator_bucket_chunk_header_t * first_chunk; /**< the first chunk of the header */ + mca_allocator_bucket_segment_head_ptr next_segment; /**< the next segment in the + bucket */ +}; +/** + * Typedef so we don't have to use struct + */ +typedef struct mca_allocator_bucket_segment_head_t mca_allocator_bucket_segment_head_t; + +/** + * Structure for each bucket + */ +struct mca_allocator_bucket_bucket_t { + mca_allocator_bucket_chunk_header_t * free_chunk; /**< the first free chunk of memory */ + ompi_mutex_t lock; /**< the lock on the bucket */ + mca_allocator_bucket_segment_head_t * segment_head; /**< the list of segment headers */ +}; +/** + * Typedef so we don't have to use struct + */ +typedef struct mca_allocator_bucket_bucket_t mca_allocator_bucket_bucket_t; + +/** + * Structure that holds the necessary information for each area of memory + */ +struct mca_allocator_bucket_t { + mca_allocator_t super; + mca_allocator_bucket_bucket_t * buckets; /**< the array of buckets */ + int num_buckets; /**< the number of buckets */ + mca_allocator_segment_alloc_fn_t get_mem_fn; /**< pointer to the function to get + more memory */ + mca_allocator_segment_free_fn_t free_mem_fn; /**< pointer to the function to free + memory */ +}; +/** + * Typedef so we don't have to use struct + */ +typedef struct mca_allocator_bucket_t mca_allocator_bucket_t; + +#if defined(c_plusplus) || defined(__cplusplus) +extern "C" { +#endif + /** + * Initializes the mca_allocator_bucket_options_t data structure for the passed + * parameters. + * @param numBuckets The number of buckets the allocator will use + * @param get_mem_funct A pointer to the function that the allocator + * will use to get more memory + * @param free_mem_funct A pointer to the function that the allocator + * will use to free memory + * + * @retval Pointer to the initialized mca_allocator_bucket_options_t structure + * @retval NULL if there was an error + */ + mca_allocator_bucket_t * mca_allocator_bucket_init(mca_allocator_t * mem, + int num_buckets, + mca_allocator_segment_alloc_fn_t get_mem_funct, + mca_allocator_segment_free_fn_t free_mem_funct); +/** + * Accepts a request for memory in a specific region defined by the + * mca_allocator_bucket_options_t struct and returns a pointer to memory in that + * region or NULL if there was an error + * + * @param mem_options 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_bucket_alloc(mca_allocator_t * mem, size_t size); + +/** + * Accepts a request for memory in a specific region defined by the + * mca_allocator_bucket_options_t struct and aligned by the specified amount and returns a + * pointer to memory in that region or NULL if there was an error + * + * @param mem_options A pointer to the appropriate struct for the area of + * memory. + * @param size The size of the requested area of memory + * @param alignment The requested alignment of the new area of memory. This + * MUST be a power of 2. If it is 0 then the memory is aligned on a page + * boundry + * + * @retval Pointer to the area of memory if the allocation was successful + * @retval NULL if the allocation was unsuccessful + * + */ + void * mca_allocator_bucket_alloc_align(mca_allocator_t * mem, size_t size, + size_t alignment); + +/** + * 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_options 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_bucket_realloc(mca_allocator_t * mem, void * ptr, + size_t size); + +/** + * Frees the passed region of memory + * + * @param mem_options 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_bucket_free(mca_allocator_t * mem, void * ptr); + +/** + * Frees all the memory from all the buckets back to the system. Note that + * this function only frees memory that was previously freed with + * mca_allocator_bucket_free(). + * + * @param mem_options A pointer to the appropriate struct for the area of + * memory. + * + * @retval None + * + */ + int mca_allocator_bucket_cleanup(mca_allocator_t * mem); + +#if defined(c_plusplus) || defined(__cplusplus) +} +#endif + +#endif /* ALLOCATOR_BUCKET_ALLOC_H */ diff --git a/src/mca/allocator/bucket/configure.params b/src/mca/allocator/bucket/configure.params new file mode 100644 index 0000000000..69f7c7d569 --- /dev/null +++ b/src/mca/allocator/bucket/configure.params @@ -0,0 +1,10 @@ +# -*- shell-script -*- +# +# $HEADER$ +# + +# Specific to this module + +PARAM_INIT_FILE=allocator_bucket_alloc.c +PARAM_CONFIG_HEADER_FILE="allocator_bucket_alloc.h" +PARAM_CONFIG_FILES="Makefile"