- Added functionality to MPI_Alloc_mem and MPI_Free_mem so that they
call the memory pool to do special memory allocations, and extended the mpool so that it will do the allocations and keep tack of them in a tree. Currently, if you pass MPI_INFO_NULL to MPI_Alloc_mem, we will try to allocate the memory and register it with as many mpools as possible. Alternatively, one can pass an info object with the names of the mpools as keys, and from these we decide which mpools to register the new memory with. - fixed some comments in the allocator and fixed a minor bug - extended the red black tree test and made a minor correction This commit was SVN r5902.
Этот коммит содержится в:
родитель
459be82daa
Коммит
75b0b519d8
@ -272,7 +272,6 @@ int ompi_rb_tree_destroy(ompi_rb_tree_t *tree)
|
||||
* inorder destroy */
|
||||
item = (ompi_list_item_t *) tree->root_ptr;
|
||||
OMPI_FREE_LIST_RETURN(&(tree->free_list), item);
|
||||
--tree->tree_size;
|
||||
|
||||
/* free the tree->nill node */
|
||||
item = (ompi_list_item_t *) tree->nill;
|
||||
@ -418,8 +417,6 @@ inorder_destroy(ompi_rb_tree_t *tree, ompi_rb_tree_node_t * node)
|
||||
|
||||
inorder_destroy(tree, node->left);
|
||||
|
||||
--tree->tree_size;
|
||||
|
||||
if (node->left != tree->nill) {
|
||||
item = (ompi_list_item_t *) node->left;
|
||||
--tree->tree_size;
|
||||
|
@ -28,7 +28,7 @@ extern "C" {
|
||||
struct mca_allocator_base_module_t;
|
||||
|
||||
/**
|
||||
* The allocate function typedef for the functrion to be provided by the component.
|
||||
* The allocate function typedef for the function to be provided by the component.
|
||||
*/
|
||||
typedef void* (*mca_allocator_base_module_alloc_fn_t)(struct mca_allocator_base_module_t*, size_t size, size_t align, void* user_out);
|
||||
|
||||
@ -130,9 +130,9 @@ typedef struct mca_allocator_base_component_1_0_0_t mca_allocator_base_component
|
||||
* Macro for use in components that are of type allocator v1.0.0
|
||||
*/
|
||||
#define MCA_ALLOCATOR_BASE_VERSION_1_0_0 \
|
||||
/* mpool v1.0 is chained to MCA v1.0 */ \
|
||||
/* allocator v1.0 is chained to MCA v1.0 */ \
|
||||
MCA_BASE_VERSION_1_0_0, \
|
||||
/* ptl v1.0 */ \
|
||||
/* allocator v1.0 */ \
|
||||
"allocator", 1, 0, 0
|
||||
|
||||
/**
|
||||
@ -144,22 +144,3 @@ OMPI_DECLSPEC extern int mca_allocator_base_output;
|
||||
#endif
|
||||
#endif /* MCA_ALLOCATOR_H */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -97,7 +97,7 @@ void * mca_allocator_bucket_alloc(mca_allocator_base_module_t * mem,
|
||||
/* go past the header */
|
||||
chunk += 1;
|
||||
/*release the lock */
|
||||
OMPI_THREAD_UNLOCK(&(mem_options->buckets[bucket_num].lock));
|
||||
OMPI_THREAD_UNLOCK(&(mem_options->buckets[bucket_num].lock));
|
||||
return((void *) chunk);
|
||||
}
|
||||
/* figure out the size of bucket we need */
|
||||
@ -165,7 +165,7 @@ void * mca_allocator_bucket_alloc_align(mca_allocator_base_module_t * mem,
|
||||
* 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;
|
||||
bucket_size = size + sizeof(mca_allocator_bucket_chunk_header_t);
|
||||
allocated_size = aligned_max_size;
|
||||
/* get some memory */
|
||||
ptr = mem_options->get_mem_fn(&allocated_size, mem_options->super.user_in, user_out);
|
||||
@ -182,8 +182,8 @@ void * mca_allocator_bucket_alloc_align(mca_allocator_base_module_t * mem,
|
||||
/* figure out how much the alignment is off by */
|
||||
alignment_off = ((size_t) aligned_memory) % alignment;
|
||||
aligned_memory += (alignment - alignment_off);
|
||||
/* we now have an aligned piece of memory. Now we have to put the chunk header
|
||||
* right before the aligned memory */
|
||||
/* 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;
|
||||
@ -251,6 +251,7 @@ void * mca_allocator_bucket_realloc(mca_allocator_base_module_t * mem,
|
||||
/* we need a new space in memory, so let's get it */
|
||||
ret_ptr = mca_allocator_bucket_alloc((mca_allocator_base_module_t *) mem_options, size, user_out);
|
||||
if(NULL == ret_ptr) {
|
||||
/* we were unable to get a larger area of memory */
|
||||
return(NULL);
|
||||
}
|
||||
/* copy what they have in memory to the new spot */
|
||||
|
@ -32,7 +32,8 @@ libmca_mpool_base_la_SOURCES = \
|
||||
mpool_base_open.c \
|
||||
mpool_base_close.c \
|
||||
mpool_base_init.c \
|
||||
mpool_base_lookup.c
|
||||
mpool_base_lookup.c \
|
||||
mpool_base_alloc.c
|
||||
|
||||
# Conditionally install the header files
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "ompi_config.h"
|
||||
|
||||
#include "class/ompi_list.h"
|
||||
#include "class/ompi_rb_tree.h"
|
||||
#include "mca/mca.h"
|
||||
#include "mca/mpool/mpool.h"
|
||||
|
||||
@ -38,6 +39,49 @@ typedef struct mca_mpool_base_selected_module_t mca_mpool_base_selected_module_t
|
||||
|
||||
OBJ_CLASS_DECLARATION(mca_mpool_base_selected_module_t);
|
||||
|
||||
/*
|
||||
* Data structures for the tree of allocated memory
|
||||
*/
|
||||
|
||||
/**
|
||||
* The maximum number of mpools a chunk of memorry can be registered with
|
||||
*/
|
||||
#define MCA_MPOOL_BASE_MAX_REG 10
|
||||
|
||||
/**
|
||||
* Holds the key for the tree
|
||||
*/
|
||||
struct mca_mpool_base_key_t
|
||||
{
|
||||
void * bottom; /**< the bottom of the memory range */
|
||||
void * top; /**< the top of the memory range */
|
||||
};
|
||||
typedef struct mca_mpool_base_key_t mca_mpool_base_key_t;
|
||||
|
||||
/**
|
||||
* Holds a pointer to the mpool the memory is registered with and
|
||||
* a user pointer for mpool specific information
|
||||
*/
|
||||
struct mca_mpool_base_reg_mpool_t
|
||||
{
|
||||
mca_mpool_base_module_t * mpool; /**< the registered memory pool */
|
||||
void * user; /**< user specific information */
|
||||
};
|
||||
typedef struct mca_mpool_base_reg_mpool_t mca_mpool_base_reg_mpool_t;
|
||||
|
||||
/**
|
||||
* Holds all the information about a chunk of registered memory. The whole
|
||||
* structure serves as a value in the tree
|
||||
*/
|
||||
struct mca_mpool_base_chunk_t
|
||||
{
|
||||
ompi_list_item_t super; /**< the parent class */
|
||||
mca_mpool_base_key_t key; /**< the key which holds the memory pointers */
|
||||
mca_mpool_base_reg_mpool_t mpools[MCA_MPOOL_BASE_MAX_REG];
|
||||
/**< the mpools the memory is registered with */
|
||||
};
|
||||
typedef struct mca_mpool_base_chunk_t mca_mpool_base_chunk_t;
|
||||
|
||||
/*
|
||||
* Global functions for MCA: overall mpool open and close
|
||||
*/
|
||||
@ -57,6 +101,8 @@ OMPI_DECLSPEC mca_mpool_base_module_t* mca_mpool_base_module_init(const char* na
|
||||
OMPI_DECLSPEC extern int mca_mpool_base_output;
|
||||
OMPI_DECLSPEC extern ompi_list_t mca_mpool_base_components;
|
||||
OMPI_DECLSPEC extern ompi_list_t mca_mpool_base_modules;
|
||||
OMPI_DECLSPEC extern ompi_free_list_t mca_mpool_base_mem_list;
|
||||
OMPI_DECLSPEC extern ompi_rb_tree_t mca_mpool_base_tree;
|
||||
|
||||
#if defined(c_plusplus) || defined(__cplusplus)
|
||||
}
|
||||
|
292
src/mca/mpool/base/mpool_base_alloc.c
Обычный файл
292
src/mca/mpool/base/mpool_base_alloc.c
Обычный файл
@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 The Trustees of Indiana University.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Trustees of the University of Tennessee.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "ompi_config.h"
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif /* HAVE_STRING_H */
|
||||
#include "mca/mpool/mpool.h"
|
||||
#include "mca/mpool/base/base.h"
|
||||
|
||||
ompi_rb_tree_t mca_mpool_base_tree;
|
||||
ompi_free_list_t mca_mpool_base_mem_list;
|
||||
|
||||
/**
|
||||
* Function for the red black tree to compare 2 keys
|
||||
*
|
||||
* @param key1 a pointer to the 1st key
|
||||
* @param key2 a pointer to the second key
|
||||
*
|
||||
* @retval -1 if key1 is below key2
|
||||
* @retval 1 if key 1 is above key2
|
||||
* @retval 0 if the keys are the same
|
||||
*/
|
||||
int mca_mpool_base_tree_node_compare(void * key1, void * key2)
|
||||
{
|
||||
if(((mca_mpool_base_key_t *) key1)->bottom <
|
||||
((mca_mpool_base_key_t *) key2)->bottom)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if(((mca_mpool_base_key_t *) key1)->bottom >
|
||||
((mca_mpool_base_key_t *) key2)->top)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to allocate special memory according to what the user requests in
|
||||
* the info object.
|
||||
*
|
||||
* If the user passes in a valid info structure then the function will
|
||||
* try to allocate the memory and register it with every mpool that there is a
|
||||
* key for it in the info struct. If it fails at registering the memory with
|
||||
* one of the requested mpools, an error will be returned. Also, if there is a
|
||||
* key in info that does not match any mpool, an error will be returned.
|
||||
*
|
||||
* If the info parameter is MPI_INFO_NULL, then this function will try to allocate
|
||||
* the memory and register it wih as many mpools as possible. However,
|
||||
* if any of the registratons fail the mpool will simply be ignored.
|
||||
*
|
||||
* @param size the size of the memory area to allocate
|
||||
* @param info an info object which tells us what kind of memory to allocate
|
||||
*
|
||||
* @retval pointer to the allocated memory
|
||||
* @retval NULL on failure
|
||||
*/
|
||||
void * mca_mpool_base_alloc(size_t size, ompi_info_t * info)
|
||||
{
|
||||
ompi_list_item_t * item;
|
||||
int num_modules = ompi_list_get_size(&mca_mpool_base_modules);
|
||||
int reg_module_num = 0;
|
||||
int i, num_keys;
|
||||
mca_mpool_base_module_t * current;
|
||||
mca_mpool_base_module_t * no_reg_function = NULL;
|
||||
mca_mpool_base_module_t ** has_reg_function = (mca_mpool_base_module_t **)
|
||||
malloc(num_modules * sizeof(mca_mpool_base_module_t *));
|
||||
void * mem = NULL;
|
||||
void * user;
|
||||
char * key;
|
||||
bool match_found;
|
||||
|
||||
if(&ompi_mpi_info_null == info)
|
||||
{
|
||||
for(item = ompi_list_get_first(&mca_mpool_base_modules);
|
||||
item != ompi_list_get_end(&mca_mpool_base_modules);
|
||||
item = ompi_list_get_next(item))
|
||||
{
|
||||
current = ((mca_mpool_base_selected_module_t *) item)->mpool_module;
|
||||
if(NULL == current->mpool_register)
|
||||
{
|
||||
no_reg_function = current;
|
||||
}
|
||||
else
|
||||
{
|
||||
has_reg_function[reg_module_num++] = current;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ompi_info_get_nkeys(info, &num_keys);
|
||||
key = malloc(MPI_MAX_INFO_KEY + 1);
|
||||
for(i = 0; i < num_keys; i++)
|
||||
{
|
||||
match_found = false;
|
||||
ompi_info_get_nthkey(info, i, key);
|
||||
for(item = ompi_list_get_first(&mca_mpool_base_modules);
|
||||
item != ompi_list_get_end(&mca_mpool_base_modules);
|
||||
item = ompi_list_get_next(item))
|
||||
{
|
||||
current = ((mca_mpool_base_selected_module_t *)item)->mpool_module;
|
||||
if(0 == strcmp(key,
|
||||
current->mpool_component->mpool_version.mca_component_name))
|
||||
{
|
||||
match_found = true;
|
||||
if(NULL == current->mpool_register)
|
||||
{
|
||||
if(NULL != no_reg_function)
|
||||
{
|
||||
/* there was more than one requested mpool that lacks
|
||||
* a registration function, so return failure */
|
||||
free(key);
|
||||
free(has_reg_function);
|
||||
return NULL;
|
||||
}
|
||||
no_reg_function = current;
|
||||
}
|
||||
else
|
||||
{
|
||||
has_reg_function[reg_module_num++] = current;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!match_found)
|
||||
{
|
||||
/* one of the keys given to us by the user did not match any
|
||||
* mpools, so return an error */
|
||||
free(key);
|
||||
free(has_reg_function);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
free(key);
|
||||
}
|
||||
|
||||
OMPI_FREE_LIST_GET(&mca_mpool_base_mem_list, item, i);
|
||||
|
||||
if(NULL == no_reg_function && 0 == reg_module_num)
|
||||
{
|
||||
free(has_reg_function);
|
||||
if(&ompi_mpi_info_null == info)
|
||||
{
|
||||
/* if the info argument was NULL and there were no useable mpools,
|
||||
* just malloc the memory and return it */
|
||||
((mca_mpool_base_chunk_t *) item)->mpools[0].mpool = NULL;
|
||||
mem = malloc(size);
|
||||
if(NULL != mem)
|
||||
{
|
||||
((mca_mpool_base_chunk_t *) item)->key.bottom = mem;
|
||||
((mca_mpool_base_chunk_t *) item)->key.top = (void *)
|
||||
((char *) mem + size - 1);
|
||||
ompi_rb_tree_insert(&mca_mpool_base_tree,
|
||||
&((mca_mpool_base_chunk_t *)item)->key, item);
|
||||
return mem;
|
||||
}
|
||||
}
|
||||
OMPI_FREE_LIST_RETURN(&mca_mpool_base_mem_list, item);
|
||||
/* the user passed info but we were not able to use any of the mpools
|
||||
* specified */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
i = 0;
|
||||
num_modules = 0;
|
||||
if(NULL != no_reg_function)
|
||||
{
|
||||
mem = no_reg_function->mpool_alloc(no_reg_function, size, 0, &user);
|
||||
((mca_mpool_base_chunk_t *) item)->key.bottom = mem;
|
||||
((mca_mpool_base_chunk_t *) item)->key.top = (void *)
|
||||
((char *) mem + size - 1);
|
||||
((mca_mpool_base_chunk_t *) item)->mpools[num_modules].mpool =
|
||||
no_reg_function;
|
||||
((mca_mpool_base_chunk_t *) item)->mpools[num_modules++].user = user;
|
||||
num_modules++;
|
||||
}
|
||||
else
|
||||
{
|
||||
mem = has_reg_function[i]->mpool_alloc(has_reg_function[i], size, 0, &user);
|
||||
((mca_mpool_base_chunk_t *) item)->key.bottom = mem;
|
||||
((mca_mpool_base_chunk_t *) item)->key.top = (void *) ((char *) mem + size - 1);
|
||||
((mca_mpool_base_chunk_t *) item)->mpools[num_modules].mpool = has_reg_function[i++];
|
||||
((mca_mpool_base_chunk_t *) item)->mpools[num_modules++].user = user;
|
||||
num_modules++;
|
||||
}
|
||||
|
||||
while(i < reg_module_num && MCA_MPOOL_BASE_MAX_REG > num_modules)
|
||||
{
|
||||
if(OMPI_SUCCESS != has_reg_function[i]->mpool_register(has_reg_function[i],
|
||||
mem, size, &user))
|
||||
{
|
||||
if(info == &ompi_mpi_info_null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
((mca_mpool_base_chunk_t *) item)->mpools[i].mpool = NULL;
|
||||
mca_mpool_base_free(mem);
|
||||
OMPI_FREE_LIST_RETURN(&mca_mpool_base_mem_list, item);
|
||||
free(has_reg_function);
|
||||
return NULL;
|
||||
}
|
||||
((mca_mpool_base_chunk_t *) item)->mpools[num_modules].mpool = has_reg_function[i++];
|
||||
((mca_mpool_base_chunk_t *) item)->mpools[num_modules++].user = user;
|
||||
}
|
||||
|
||||
if(MCA_MPOOL_BASE_MAX_REG > num_modules)
|
||||
{
|
||||
((mca_mpool_base_chunk_t *) item)->mpools[num_modules].mpool = NULL;
|
||||
}
|
||||
ompi_rb_tree_insert(&mca_mpool_base_tree,
|
||||
&((mca_mpool_base_chunk_t *)item)->key, item);
|
||||
free(has_reg_function);
|
||||
return mem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to free memory previously allocated by mca_mpool_base_alloc
|
||||
*
|
||||
* @param base pointer to the memory to free
|
||||
*
|
||||
* @retval OMPI_SUCCESS
|
||||
* @retval OMPI_ERR_BAD_PARAM if the passed base pointer was invalid
|
||||
*/
|
||||
int mca_mpool_base_free(void * base)
|
||||
{
|
||||
mca_mpool_base_chunk_t * chunk = mca_mpool_base_find(base);
|
||||
int i = 0;
|
||||
|
||||
if(NULL == chunk)
|
||||
{
|
||||
return OMPI_ERR_BAD_PARAM;
|
||||
}
|
||||
|
||||
/* if no special mpool was used to allocate the memory, call free */
|
||||
if(chunk->mpools[0].mpool == NULL)
|
||||
{
|
||||
free(chunk->key.bottom);
|
||||
OMPI_FREE_LIST_RETURN(&mca_mpool_base_mem_list, (ompi_list_item_t*) chunk);
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
while(MCA_MPOOL_BASE_MAX_REG > i && NULL != chunk->mpools[i].mpool) { i++; };
|
||||
|
||||
i -= 1;
|
||||
for( ; i > 0; i--)
|
||||
{
|
||||
chunk->mpools[i].mpool->mpool_deregister(chunk->mpools[i].mpool,
|
||||
chunk->key.bottom,
|
||||
((char *) chunk->key.top - (char *) chunk->key.bottom + 1));
|
||||
}
|
||||
chunk->mpools[i].mpool->mpool_free(chunk->mpools[i].mpool, chunk->key.bottom);
|
||||
OMPI_FREE_LIST_RETURN(&mca_mpool_base_mem_list, (ompi_list_item_t *) chunk);
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the mpool to see if it has allocated the memory that is passed in.
|
||||
* If so it returns an array of mpools the memory is registered with.
|
||||
*
|
||||
* @param base pointer to the memory to lookup
|
||||
*
|
||||
* @retval NULL if the memory is not in any mpool
|
||||
* @retval pointer to an array of type mca_mpool_base_reg_mpool_t
|
||||
*/
|
||||
struct mca_mpool_base_chunk_t * mca_mpool_base_find(void * base)
|
||||
{
|
||||
return (mca_mpool_base_chunk_t *)
|
||||
ompi_rb_tree_find(&mca_mpool_base_tree, &base);
|
||||
}
|
||||
|
@ -22,11 +22,14 @@
|
||||
#include "mca/base/base.h"
|
||||
#include "mca/mpool/mpool.h"
|
||||
#include "mca/mpool/base/base.h"
|
||||
|
||||
#include "class/ompi_rb_tree.h"
|
||||
#include "class/ompi_free_list.h"
|
||||
|
||||
OBJ_CLASS_INSTANCE(mca_mpool_base_selected_module_t, ompi_list_item_t, NULL, NULL);
|
||||
static bool mca_mpool_enable_progress_threads = true;
|
||||
static bool mca_mpool_enable_mpi_threads = true;
|
||||
|
||||
OBJ_CLASS_INSTANCE(mca_mpool_base_chunk_t, ompi_list_item_t, NULL, NULL);
|
||||
|
||||
/**
|
||||
* Function for weeding out mpool modules that don't want to run.
|
||||
@ -40,7 +43,11 @@ int mca_mpool_base_init(bool enable_progress_threads, bool enable_mpi_threads)
|
||||
{
|
||||
mca_mpool_enable_progress_threads = enable_progress_threads;
|
||||
mca_mpool_enable_mpi_threads = enable_mpi_threads;
|
||||
return OMPI_SUCCESS;
|
||||
OBJ_CONSTRUCT(&mca_mpool_base_mem_list, ompi_free_list_t);
|
||||
ompi_free_list_init(&mca_mpool_base_mem_list, sizeof(mca_mpool_base_chunk_t),
|
||||
OBJ_CLASS(mca_mpool_base_chunk_t), 0, -1 , 128, NULL);
|
||||
OBJ_CONSTRUCT(&mca_mpool_base_tree, ompi_rb_tree_t);
|
||||
return ompi_rb_tree_init(&mca_mpool_base_tree, mca_mpool_base_tree_node_compare);
|
||||
}
|
||||
|
||||
mca_mpool_base_module_t* mca_mpool_base_module_init(const char* name)
|
||||
|
@ -58,7 +58,7 @@ mca_mpool_base_module_t* mca_mpool_base_module_lookup(const char* name)
|
||||
}
|
||||
}
|
||||
/* if not create it */
|
||||
return mca_mpool_base_module_init(name);;
|
||||
return mca_mpool_base_module_init(name);
|
||||
}
|
||||
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
#ifndef MCA_MPOOL_H
|
||||
#define MCA_MPOOL_H
|
||||
#include "mca/mca.h"
|
||||
|
||||
#include "info/info.h"
|
||||
struct mca_mpool_t;
|
||||
|
||||
|
||||
@ -110,13 +110,68 @@ struct mca_mpool_base_module_t {
|
||||
*/
|
||||
typedef struct mca_mpool_base_module_t mca_mpool_base_module_t;
|
||||
|
||||
/**
|
||||
* Function to allocate special memory according to what the user requests in
|
||||
* the info object.
|
||||
*
|
||||
* If the user passes in a valid info structure then the function will
|
||||
* try to allocate the memory and register it with every mpool that there is a
|
||||
* key for it in the info struct. If it fails at registering the memory with
|
||||
* one of the requested mpools, an error will be returned. Also, if there is a
|
||||
* key in info that does not match any mpool, an error will be returned.
|
||||
*
|
||||
* If the info parameter is MPI_INFO_NULL, then this function will try to allocate
|
||||
* the memory and register it wih as many mpools as possible. However,
|
||||
* if any of the registratons fail the mpool will simply be ignored.
|
||||
*
|
||||
* @param size the size of the memory area to allocate
|
||||
* @param info an info object which tells us what kind of memory to allocate
|
||||
*
|
||||
* @retval pointer to the allocated memory
|
||||
* @retval NULL on failure
|
||||
*/
|
||||
OMPI_DECLSPEC void * mca_mpool_base_alloc(size_t size, ompi_info_t * info);
|
||||
|
||||
/**
|
||||
* Function to free memory previously allocated by mca_mpool_base_alloc
|
||||
*
|
||||
* @param base pointer to the memory to free
|
||||
*
|
||||
* @retval OMPI_SUCCESS
|
||||
* @retval OMPI_ERR_BAD_PARAM if the passed base pointer was invalid
|
||||
*/
|
||||
OMPI_DECLSPEC int mca_mpool_base_free(void * base);
|
||||
|
||||
/**
|
||||
* Function for the red black tree to compare 2 keys
|
||||
*
|
||||
* @param key1 a pointer to the 1st key
|
||||
* @param key2 a pointer to the second key
|
||||
*
|
||||
* @retval -1 if key1 is below key2
|
||||
* @retval 1 if key 1 is above key2
|
||||
* @retval 0 if the keys are the same
|
||||
*/
|
||||
OMPI_DECLSPEC int mca_mpool_base_tree_node_compare(void * key1, void * key2);
|
||||
|
||||
/**
|
||||
* Searches the mpool to see if it has allocated the memory that is passed in.
|
||||
* If so it returns an array of mpools the memory is registered with.
|
||||
*
|
||||
* @param base pointer to the memory to lookup
|
||||
*
|
||||
* @retval NULL if the memory is not in any mpool
|
||||
* @retval pointer to an array of type mca_mpool_base_reg_mpool_t
|
||||
*/
|
||||
OMPI_DECLSPEC struct mca_mpool_base_chunk_t * mca_mpool_base_find(void * base);
|
||||
|
||||
/**
|
||||
* Macro for use in components that are of type mpool v1.0.0
|
||||
*/
|
||||
#define MCA_MPOOL_BASE_VERSION_1_0_0 \
|
||||
/* mpool v1.0 is chained to MCA v1.0 */ \
|
||||
MCA_BASE_VERSION_1_0_0, \
|
||||
/* ptl v1.0 */ \
|
||||
/* mpool v1.0 */ \
|
||||
"mpool", 1, 0, 0
|
||||
|
||||
#endif /* MCA_MPOOL_H */
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "communicator/communicator.h"
|
||||
#include "errhandler/errhandler.h"
|
||||
#include "info/info.h"
|
||||
#include "mca/mpool/mpool.h"
|
||||
|
||||
#if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
|
||||
#pragma weak MPI_Alloc_mem = PMPI_Alloc_mem
|
||||
@ -48,10 +49,8 @@ int MPI_Alloc_mem(MPI_Aint size, MPI_Info info, void *baseptr)
|
||||
FUNC_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/* For this release, we're just calling malloc(). */
|
||||
|
||||
*((void **) baseptr) = malloc(size);
|
||||
|
||||
*((void **) baseptr) = mca_mpool_base_alloc((size_t) size, info);
|
||||
if (NULL == *((void **) baseptr)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_NO_MEM,
|
||||
FUNC_NAME);
|
||||
@ -61,3 +60,4 @@ int MPI_Alloc_mem(MPI_Aint size, MPI_Info info, void *baseptr)
|
||||
|
||||
return MPI_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "mpi/c/bindings.h"
|
||||
#include "communicator/communicator.h"
|
||||
#include "errhandler/errhandler.h"
|
||||
#include "mca/mpool/mpool.h"
|
||||
|
||||
#if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
|
||||
#pragma weak MPI_Free_mem = PMPI_Free_mem
|
||||
@ -44,10 +45,11 @@ int MPI_Free_mem(void *baseptr)
|
||||
}
|
||||
}
|
||||
|
||||
/* For this release, we're just calling malloc(). */
|
||||
free( baseptr );
|
||||
|
||||
/* All done */
|
||||
if(OMPI_SUCCESS != mca_mpool_base_free(baseptr))
|
||||
{
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_NO_MEM, FUNC_NAME);
|
||||
}
|
||||
|
||||
return MPI_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,11 @@
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <sys/_time.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include "support.h"
|
||||
#include "class/ompi_rb_tree.h"
|
||||
@ -172,13 +177,148 @@ void test1(void)
|
||||
OBJ_DESTRUCT(&tree);
|
||||
}
|
||||
|
||||
/* the following test is based on memory lookups in the mpool */
|
||||
int mem_node_compare(void * key1, void * key2);
|
||||
void test2(void);
|
||||
|
||||
/* the maximum number of memory pools a piece of memory can be registered with */
|
||||
#define MAX_REGISTRATIONS 10
|
||||
|
||||
/* the number of memory segments to allocate */
|
||||
#define NUM_ALLOCATIONS 500
|
||||
|
||||
struct ompi_test_rb_key_t
|
||||
{
|
||||
void * bottom; /* the bottom of the memory range */
|
||||
void * top; /* the top of the memory range */
|
||||
};
|
||||
typedef struct ompi_test_rb_key_t ompi_test_rb_key_t;
|
||||
|
||||
struct ompi_test_rb_value_t
|
||||
{
|
||||
ompi_list_item_t super; /* the parent class */
|
||||
ompi_test_rb_key_t key; /* the key which holds the memory pointers */
|
||||
mca_mpool_base_module_t* registered_mpools[MAX_REGISTRATIONS];
|
||||
/* the mpools the memory is registered with */
|
||||
};
|
||||
typedef struct ompi_test_rb_value_t ompi_test_rb_value_t;
|
||||
|
||||
OBJ_CLASS_INSTANCE(ompi_test_rb_value_t, ompi_list_item_t, NULL, NULL);
|
||||
|
||||
int mem_node_compare(void * key1, void * key2)
|
||||
{
|
||||
if(((ompi_test_rb_key_t *) key1)->bottom <
|
||||
((ompi_test_rb_key_t *) key2)->bottom)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if(((ompi_test_rb_key_t *) key1)->bottom >
|
||||
((ompi_test_rb_key_t *) key2)->top)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test2(void)
|
||||
{
|
||||
ompi_free_list_t key_list;
|
||||
ompi_list_item_t * new_value;
|
||||
ompi_rb_tree_t tree;
|
||||
int rc, i, size;
|
||||
void * result, * lookup;
|
||||
void * mem[NUM_ALLOCATIONS];
|
||||
ompi_list_item_t * key_array[NUM_ALLOCATIONS];
|
||||
struct timeval start, end;
|
||||
|
||||
OBJ_CONSTRUCT(&key_list, ompi_free_list_t);
|
||||
ompi_free_list_init(&key_list, sizeof(ompi_test_rb_value_t),
|
||||
OBJ_CLASS(ompi_test_rb_value_t), 0, -1 , 128, NULL);
|
||||
|
||||
OBJ_CONSTRUCT(&tree, ompi_rb_tree_t);
|
||||
rc = ompi_rb_tree_init(&tree, mem_node_compare);
|
||||
if(!test_verify_int(OMPI_SUCCESS, rc)) {
|
||||
test_failure("failed to properly initialize the tree");
|
||||
}
|
||||
|
||||
size = 1;
|
||||
for(i = 0; i < NUM_ALLOCATIONS; i++)
|
||||
{
|
||||
mem[i] = malloc(size);
|
||||
if(NULL == mem[i])
|
||||
{
|
||||
test_failure("system out of memory");
|
||||
return;
|
||||
}
|
||||
OMPI_FREE_LIST_GET(&key_list, new_value, rc);
|
||||
if(OMPI_SUCCESS != rc)
|
||||
{
|
||||
test_failure("failed to get memory from free list");
|
||||
}
|
||||
key_array[i] = new_value;
|
||||
((ompi_test_rb_value_t *) new_value)->key.bottom = mem[i];
|
||||
((ompi_test_rb_value_t *) new_value)->key.top =
|
||||
(void *) ((size_t) mem[i] + size - 1);
|
||||
((ompi_test_rb_value_t *) new_value)->registered_mpools[0] = (void *) i;
|
||||
rc = ompi_rb_tree_insert(&tree, &((ompi_test_rb_value_t *)new_value)->key,
|
||||
new_value);
|
||||
if(OMPI_SUCCESS != rc)
|
||||
{
|
||||
test_failure("failed to properly insert a new node");
|
||||
}
|
||||
size += 1;
|
||||
}
|
||||
|
||||
gettimeofday(&start, NULL);
|
||||
for(i = 0; i < NUM_ALLOCATIONS; i++)
|
||||
{
|
||||
lookup = (void *) ((size_t) mem[i] + i);
|
||||
result = ompi_rb_tree_find(&tree, &lookup);
|
||||
if(NULL == result)
|
||||
{
|
||||
test_failure("lookup returned null!");
|
||||
} else if(i != ((int) ((ompi_test_rb_value_t *) result)->registered_mpools[0]))
|
||||
{
|
||||
test_failure("lookup returned wrong node!");
|
||||
}
|
||||
result = ompi_rb_tree_find(&tree, &lookup);
|
||||
if(NULL == result)
|
||||
{
|
||||
test_failure("lookup returned null!");
|
||||
} else if(i != ((int) ((ompi_test_rb_value_t *) result)->registered_mpools[0]))
|
||||
{
|
||||
test_failure("lookup returned wrong node!");
|
||||
}
|
||||
}
|
||||
|
||||
gettimeofday(&end, NULL);
|
||||
|
||||
#if 0
|
||||
i = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
|
||||
printf("In a %d node tree, %d lookups took %f microseonds each\n",
|
||||
NUM_ALLOCATIONS, NUM_ALLOCATIONS * 2,
|
||||
(float) i / (float) (NUM_ALLOCATIONS * 2));
|
||||
#endif
|
||||
|
||||
for(i = 0; i < NUM_ALLOCATIONS; i++)
|
||||
{
|
||||
if(NULL != mem[i])
|
||||
{
|
||||
free(mem[i]);
|
||||
}
|
||||
OMPI_FREE_LIST_RETURN(&(key_list), key_array[i]);
|
||||
}
|
||||
|
||||
OBJ_DESTRUCT(&tree);
|
||||
OBJ_DESTRUCT(&key_list);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* local variables */
|
||||
test_init("ompi_rb_tree_t");
|
||||
|
||||
test1();
|
||||
|
||||
test2();
|
||||
return test_finalize();
|
||||
}
|
||||
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user