first checkin of the memory allocation framework. It should work fine
except the align and realloc functions are not yet allocated. This commit was SVN r1251.
Этот коммит содержится в:
родитель
b2281a7ecf
Коммит
8f7b128941
@ -630,6 +630,7 @@ MCA_registry_NO_CONFIGURE_SUBDIRS=""
|
||||
|
||||
MCA_coll_NO_CONFIGURE_SUBDIRS=""
|
||||
MCA_io_NO_CONFIGURE_SUBDIRS=""
|
||||
MCA_mem_NO_CONFIGURE_SUBDIRS=""
|
||||
MCA_one_NO_CONFIGURE_SUBDIRS=""
|
||||
MCA_pml_NO_CONFIGURE_SUBDIRS=""
|
||||
MCA_ptl_NO_CONFIGURE_SUBDIRS=""
|
||||
|
@ -43,7 +43,7 @@ unset msg
|
||||
# The list of MCA types (it's fixed)
|
||||
|
||||
AC_MSG_CHECKING([for MCA types])
|
||||
found_types="oob pcm registry coll io one pml ptl topo"
|
||||
found_types="oob pcm registry coll io mem one pml ptl topo"
|
||||
AC_MSG_RESULT([$found_types])
|
||||
|
||||
# Get the list of all the non-configure MCA modules that were found by
|
||||
@ -257,6 +257,11 @@ AC_SUBST(MCA_io_STATIC_SUBDIRS)
|
||||
AC_SUBST(MCA_io_DYNAMIC_SUBDIRS)
|
||||
AC_SUBST(MCA_io_STATIC_LTLIBS)
|
||||
|
||||
AC_SUBST(MCA_mem_ALL_SUBDIRS)
|
||||
AC_SUBST(MCA_mem_STATIC_SUBDIRS)
|
||||
AC_SUBST(MCA_mem_DYNAMIC_SUBDIRS)
|
||||
AC_SUBST(MCA_mem_STATIC_LTLIBS)
|
||||
|
||||
AC_SUBST(MCA_one_ALL_SUBDIRS)
|
||||
AC_SUBST(MCA_one_STATIC_SUBDIRS)
|
||||
AC_SUBST(MCA_one_DYNAMIC_SUBDIRS)
|
||||
|
@ -814,6 +814,8 @@ AC_CONFIG_FILES([
|
||||
src/mca/pml/base/Makefile
|
||||
src/mca/ptl/Makefile
|
||||
src/mca/ptl/base/Makefile
|
||||
src/mca/mem/Makefile
|
||||
src/mca/mem/base/Makefile
|
||||
src/mca/gpr/Makefile
|
||||
|
||||
src/mpi/Makefile
|
||||
@ -837,6 +839,6 @@ AC_CONFIG_FILES([
|
||||
test/threads/Makefile
|
||||
test/util/Makefile
|
||||
test/rte/Makefile
|
||||
|
||||
test/mem/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
@ -9,6 +9,7 @@ SUBDIRS = \
|
||||
coll \
|
||||
common \
|
||||
io \
|
||||
mem \
|
||||
one \
|
||||
oob \
|
||||
pcm \
|
||||
@ -29,6 +30,7 @@ libmca_la_SOURCES =
|
||||
libmca_la_LIBADD = \
|
||||
base/libmca_base.la \
|
||||
coll/libmca_coll.la \
|
||||
mem/libmca_mem.la \
|
||||
oob/libmca_oob.la \
|
||||
pcm/libmca_pcm.la \
|
||||
pml/libmca_pml.la \
|
||||
|
28
src/mca/mem/Makefile.am
Обычный файл
28
src/mca/mem/Makefile.am
Обычный файл
@ -0,0 +1,28 @@
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
include $(top_srcdir)/config/Makefile.options
|
||||
|
||||
SUBDIRS = base $(MCA_mem_STATIC_SUBDIRS)
|
||||
DIST_SUBDIRS = base $(MCA_mem_ALL_SUBDIRS)
|
||||
|
||||
# Source code files
|
||||
|
||||
headers = mem.h
|
||||
|
||||
noinst_LTLIBRARIES = libmca_mem.la
|
||||
libmca_mem_la_SOURCES =
|
||||
libmca_mem_la_LIBADD = \
|
||||
base/libmca_mem_base.la \
|
||||
$(MCA_mem_STATIC_LTLIBS)
|
||||
libmca_mem_la_DEPENDENCIES = $(libmca_mem_la_LIBADD)
|
||||
|
||||
# Conditionally install the header files
|
||||
|
||||
if WANT_INSTALL_HEADERS
|
||||
ompidir = $(includedir)/ompi/mca/mem
|
||||
ompi_HEADERS = $(headers)
|
||||
else
|
||||
ompidir = $(includedir)
|
||||
endif
|
34
src/mca/mem/base/Makefile.am
Обычный файл
34
src/mca/mem/base/Makefile.am
Обычный файл
@ -0,0 +1,34 @@
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
include $(top_srcdir)/config/Makefile.options
|
||||
|
||||
noinst_LTLIBRARIES = libmca_mem_base.la
|
||||
|
||||
# For VPATH builds, have to specify where static-modules.h will be found
|
||||
|
||||
AM_CPPFLAGS = -I$(top_builddir)/src
|
||||
|
||||
# Source code files
|
||||
|
||||
headers = \
|
||||
base.h \
|
||||
mem_base_allocator.h
|
||||
|
||||
libmca_mem_base_la_SOURCES = \
|
||||
$(headers) \
|
||||
mem_base_open.c \
|
||||
mem_base_close.c \
|
||||
mem_base_allocator.c \
|
||||
mem_base_select.c
|
||||
|
||||
# Conditionally install the header files
|
||||
|
||||
if WANT_INSTALL_HEADERS
|
||||
ompidir = $(includedir)/mca/mem/base
|
||||
ompi_HEADERS = $(headers)
|
||||
else
|
||||
ompidir = $(includedir)
|
||||
endif
|
||||
|
48
src/mca/mem/base/base.h
Обычный файл
48
src/mca/mem/base/base.h
Обычный файл
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* $HEADER$
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*/
|
||||
#ifndef MCA_MEM_BASE_H
|
||||
#define MCA_MEM_BASE_H
|
||||
|
||||
#include "ompi_config.h"
|
||||
|
||||
#include "class/ompi_list.h"
|
||||
#include "mca/mca.h"
|
||||
#include "mca/mem/mem.h"
|
||||
|
||||
|
||||
struct mca_mem_base_selected_module_t {
|
||||
ompi_list_item_t super;
|
||||
mca_mem_base_module_t *pbsm_module;
|
||||
mca_mem_t *pbsm_actions;
|
||||
};
|
||||
typedef struct mca_mem_base_selected_module_t mca_mem_base_selected_module_t;
|
||||
|
||||
|
||||
/*
|
||||
* Global functions for MCA: overall PTL open and close
|
||||
*/
|
||||
|
||||
#if defined(c_plusplus) || defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
int mca_mem_base_open(void);
|
||||
int mca_mem_base_select(bool *allow_multi_user_threads,
|
||||
bool *have_hidden_threads);
|
||||
int mca_mem_base_close(void);
|
||||
#if defined(c_plusplus) || defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Globals
|
||||
*/
|
||||
extern int mca_mem_base_output;
|
||||
extern ompi_list_t mca_mem_base_modules_available;
|
||||
extern ompi_list_t mca_mem_base_modules_initialized;
|
||||
|
||||
#endif /* MCA_MEM_BASE_H */
|
211
src/mca/mem/base/mem_base_allocator.c
Обычный файл
211
src/mca/mem/base/mem_base_allocator.c
Обычный файл
@ -0,0 +1,211 @@
|
||||
/*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "mca/mem/base/mem_base_allocator.h"
|
||||
|
||||
/**
|
||||
* The define controls the size in bytes of the 1st bucket and hence every one
|
||||
* afterwards.
|
||||
*/
|
||||
#define MCA_MEM_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_MEM_BUCKET_1_BITSHIFTS 3
|
||||
|
||||
/*
|
||||
* Initializes the mca_mem_options_t data structure for the passed
|
||||
* parameters.
|
||||
*/
|
||||
mca_mem_options_t * mca_mem_init(int num_buckets,
|
||||
mca_mem_get_mem_fn_t get_mem_funct,
|
||||
mca_mem_free_mem_fn_t free_mem_funct)
|
||||
{
|
||||
int i;
|
||||
/* Create a new mca_mem_options struct */
|
||||
size_t size = sizeof(mca_mem_options_t);
|
||||
mca_mem_options_t * mem_options =
|
||||
(mca_mem_options_t *)get_mem_funct(&size);
|
||||
if(NULL == mem_options) {
|
||||
return(NULL);
|
||||
}
|
||||
/* 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_mem_bucket_t) * num_buckets;
|
||||
mem_options->buckets = (mca_mem_bucket_t*) get_mem_funct(&size);
|
||||
if(NULL == mem_options->buckets) {
|
||||
free_mem_funct(mem_options);
|
||||
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_mem_options_t struct and returns a pointer to memory in that
|
||||
* region or NULL if there was an error
|
||||
*
|
||||
*/
|
||||
void * mca_mem_alloc(mca_mem_options_t * mem_options, size_t size)
|
||||
{
|
||||
int bucket_num = 0;
|
||||
/* initialize for the later bit shifts */
|
||||
size_t bucket_size = 1;
|
||||
size_t allocated_size;
|
||||
mca_mem_chunk_header_t * chunk;
|
||||
mca_mem_chunk_header_t * first_chunk;
|
||||
mca_mem_segment_head_t * segment_header;
|
||||
/* add the size of the header into the amount we need to request */
|
||||
size += sizeof(mca_mem_chunk_header_t);
|
||||
/* figure out which bucket it will come from. */
|
||||
while(size > MCA_MEM_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_MEM_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_mem_segment_head_t);
|
||||
/* attempt to get the memory */
|
||||
segment_header = (mca_mem_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_mem_segment_head_t) + bucket_size);
|
||||
chunk = first_chunk = segment_header->first_chunk =
|
||||
(mca_mem_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_mem_chunk_header_t *) ((char *) chunk + bucket_size);
|
||||
chunk->next_in_segment = (mca_mem_chunk_header_t *)
|
||||
((char *)chunk + bucket_size);
|
||||
while(allocated_size >= bucket_size) {
|
||||
chunk = (mca_mem_chunk_header_t *) ((char *) chunk + bucket_size);
|
||||
chunk->u.next_free = (mca_mem_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));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Frees the passed region of memory
|
||||
*
|
||||
*/
|
||||
void mca_mem_free(mca_mem_options_t * mem_options, void * ptr)
|
||||
{
|
||||
mca_mem_chunk_header_t * chunk = (mca_mem_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_mem_free().
|
||||
*
|
||||
*/
|
||||
void mca_mem_cleanup(mca_mem_options_t * mem_options)
|
||||
{
|
||||
int i;
|
||||
mca_mem_chunk_header_t * next_chunk;
|
||||
mca_mem_chunk_header_t * chunk;
|
||||
mca_mem_chunk_header_t * first_chunk;
|
||||
mca_mem_segment_head_t ** segment_header;
|
||||
mca_mem_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));
|
||||
}
|
||||
}
|
208
src/mca/mem/base/mem_base_allocator.h
Обычный файл
208
src/mca/mem/base/mem_base_allocator.h
Обычный файл
@ -0,0 +1,208 @@
|
||||
/**
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* A generic memory allocator.
|
||||
*
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef MEM_BASE_ALLOCATOR_H
|
||||
#define MEM_BASE_ALLOCATOR_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "threads/mutex.h"
|
||||
#include "class/ompi_object.h"
|
||||
|
||||
|
||||
/**
|
||||
* Typedef for a pointer to a function to get more memory. This function
|
||||
* accepts a pointer to the minimum size that is needed. This function is free
|
||||
* to allocate more memory than is necessary, but it must return the amount
|
||||
* allocated in the size_t variable. If it cannot allocate at least the
|
||||
* amount requested, it MUST return NULL.
|
||||
*/
|
||||
typedef void*(*mca_mem_get_mem_fn_t)(size_t *);
|
||||
|
||||
/**
|
||||
* Typedef for a pointer to a function to free memory
|
||||
*/
|
||||
typedef void(*mca_mem_free_mem_fn_t)(void *);
|
||||
|
||||
/**
|
||||
* Typedef so we can add a pointer to mca_mem_chunk_header_t in
|
||||
* mca_mem_chunk_header_t
|
||||
*/
|
||||
typedef struct mca_mem_chunk_header_t * mca_mem_chunk_header_ptr_t;
|
||||
|
||||
/**
|
||||
* Structure for the header of each memory chunk
|
||||
*/
|
||||
struct mca_mem_chunk_header_t {
|
||||
mca_mem_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_mem_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_mem_chunk_header_t mca_mem_chunk_header_t;
|
||||
|
||||
/**
|
||||
* Typedef so we can reference a pointer to mca_mem_segment_head_t from itself
|
||||
*/
|
||||
typedef struct mca_mem_segment_head_t * mca_mem_segment_head_ptr;
|
||||
|
||||
/**
|
||||
* Structure that heads each segment
|
||||
*/
|
||||
struct mca_mem_segment_head_t {
|
||||
mca_mem_chunk_header_t * first_chunk; /**< the first chunk of the header */
|
||||
mca_mem_segment_head_ptr next_segment; /**< the next segment in the
|
||||
bucket */
|
||||
};
|
||||
/**
|
||||
* Typedef so we don't have to use struct
|
||||
*/
|
||||
typedef struct mca_mem_segment_head_t mca_mem_segment_head_t;
|
||||
|
||||
/**
|
||||
* Structure for each bucket
|
||||
*/
|
||||
struct mca_mem_bucket_t {
|
||||
mca_mem_chunk_header_t * free_chunk; /**< the first free chunk of memory */
|
||||
ompi_mutex_t lock; /**< the lock on the bucket */
|
||||
mca_mem_segment_head_t * segment_head; /**< the list of segment headers */
|
||||
};
|
||||
/**
|
||||
* Typedef so we don't have to use struct
|
||||
*/
|
||||
typedef struct mca_mem_bucket_t mca_mem_bucket_t;
|
||||
|
||||
/**
|
||||
* Structure that holds the necessary information for each area of memory
|
||||
*/
|
||||
struct mca_mem_options_t {
|
||||
mca_mem_bucket_t * buckets; /**< the array of buckets */
|
||||
int num_buckets; /**< the number of buckets */
|
||||
mca_mem_get_mem_fn_t get_mem_fn; /**< pointer to the function to get
|
||||
more memory */
|
||||
mca_mem_free_mem_fn_t free_mem_fn; /**< pointer to the function to free
|
||||
memory */
|
||||
};
|
||||
/**
|
||||
* Typedef so we don't have to use struct
|
||||
*/
|
||||
typedef struct mca_mem_options_t mca_mem_options_t;
|
||||
|
||||
#if defined(c_plusplus) || defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
/**
|
||||
* Initializes the mca_mem_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_mem_options_t structure
|
||||
* @retval NULL if there was an error
|
||||
*/
|
||||
mca_mem_options_t * mca_mem_init(int num_buckets,
|
||||
mca_mem_get_mem_fn_t get_mem_funct,
|
||||
mca_mem_free_mem_fn_t free_mem_funct);
|
||||
/**
|
||||
* Accepts a request for memory in a specific region defined by the
|
||||
* mca_mem_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_mem_alloc(mca_mem_options_t * mem_options, size_t size);
|
||||
|
||||
/**
|
||||
* NOT YET IMPLEMENTED.
|
||||
* Accepts a request for memory in a specific region defined by the
|
||||
* mca_mem_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_mem_alloc_align(mca_mem_options_t * mem_options, size_t size,
|
||||
int alignment);
|
||||
|
||||
/**
|
||||
* NOT YET IMPLEMENTED.
|
||||
* Attempts to resize the passed region of memory into a larger or a smaller
|
||||
* region.
|
||||
*
|
||||
* @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_mem_realloc(mca_mem_options_t * mem_options, size_t size,
|
||||
void * ptr);
|
||||
|
||||
/**
|
||||
* 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_mem_free(mca_mem_options_t * mem_options, 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_mem_free().
|
||||
*
|
||||
* @param mem_options A pointer to the appropriate struct for the area of
|
||||
* memory.
|
||||
*
|
||||
* @retval None
|
||||
*
|
||||
*/
|
||||
void mca_mem_cleanup(mca_mem_options_t * mem_options);
|
||||
|
||||
#if defined(c_plusplus) || defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MEM_BASE_ALLOCATOR */
|
45
src/mca/mem/base/mem_base_close.c
Обычный файл
45
src/mca/mem/base/mem_base_close.c
Обычный файл
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "ompi_config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "include/constants.h"
|
||||
#include "mca/mca.h"
|
||||
#include "mca/base/base.h"
|
||||
#include "mca/mem/mem.h"
|
||||
#include "mca/mem/base/base.h"
|
||||
|
||||
|
||||
int mca_mem_base_close(void)
|
||||
{
|
||||
ompi_list_item_t *item;
|
||||
mca_mem_base_selected_module_t *sm;
|
||||
|
||||
/* Finalize all the mem modules and free their list items */
|
||||
|
||||
for (item = ompi_list_remove_first(&mca_mem_base_modules_initialized);
|
||||
NULL != item;
|
||||
item = ompi_list_remove_first(&mca_mem_base_modules_initialized)) {
|
||||
sm = (mca_mem_base_selected_module_t *) item;
|
||||
|
||||
/* Blatently ignore the return code (what would we do to recover,
|
||||
anyway? This module is going away, so errors don't matter
|
||||
anymore) */
|
||||
|
||||
sm->pbsm_actions->mem_finalize(sm->pbsm_actions);
|
||||
free(sm);
|
||||
}
|
||||
|
||||
/* Close all remaining available modules (may be one if this is a
|
||||
OMPI RTE program, or [possibly] multiple if this is ompi_info) */
|
||||
|
||||
mca_base_modules_close(mca_mem_base_output,
|
||||
&mca_mem_base_modules_available, NULL);
|
||||
|
||||
/* All done */
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
55
src/mca/mem/base/mem_base_open.c
Обычный файл
55
src/mca/mem/base/mem_base_open.c
Обычный файл
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "ompi_config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "mca/mca.h"
|
||||
#include "mca/base/base.h"
|
||||
#include "mca/mem/mem.h"
|
||||
#include "mca/mem/base/base.h"
|
||||
|
||||
|
||||
/*
|
||||
* The following file was created by configure. It contains extern
|
||||
* statements and the definition of an array of pointers to each
|
||||
* module's public mca_base_module_t struct.
|
||||
*/
|
||||
|
||||
#include "mca/mem/base/static-modules.h"
|
||||
|
||||
|
||||
/*
|
||||
* Global variables
|
||||
*/
|
||||
int mca_mem_base_output = -1;
|
||||
ompi_list_t mca_mem_base_modules_available;
|
||||
ompi_list_t mca_mem_base_modules_initialized;
|
||||
|
||||
|
||||
/**
|
||||
* Function for finding and opening either all MCA modules, or the one
|
||||
* that was specifically requested via a MCA parameter.
|
||||
*/
|
||||
int mca_mem_base_open(void)
|
||||
{
|
||||
/* Open up all available modules */
|
||||
|
||||
if (OMPI_SUCCESS !=
|
||||
mca_base_modules_open("mem", 0, mca_mem_base_static_modules,
|
||||
&mca_mem_base_modules_available)) {
|
||||
return OMPI_ERROR;
|
||||
}
|
||||
|
||||
/* Initialize the list so that in mca_mem_base_close(), we can
|
||||
iterate over it (even if it's empty, as in the case of
|
||||
ompi_info) */
|
||||
|
||||
OBJ_CONSTRUCT(&mca_mem_base_modules_initialized, ompi_list_t);
|
||||
|
||||
/* All done */
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
100
src/mca/mem/base/mem_base_select.c
Обычный файл
100
src/mca/mem/base/mem_base_select.c
Обычный файл
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "ompi_config.h"
|
||||
|
||||
#include "runtime/runtime.h"
|
||||
#include "mca/mca.h"
|
||||
#include "mca/base/base.h"
|
||||
#include "mca/ptl/ptl.h"
|
||||
#include "mca/ptl/base/base.h"
|
||||
|
||||
|
||||
/**
|
||||
* Function for weeding out ptl modules that don't want to run.
|
||||
*
|
||||
* Call the init function on all available modules to find out if they
|
||||
* want to run. Select all modules that don't fail. Failing modules
|
||||
* will be closed and unloaded. The selected modules will be returned
|
||||
* to the caller in a ompi_list_t.
|
||||
*/
|
||||
int mca_ptl_base_select(bool *allow_multi_user_threads,
|
||||
bool *have_hidden_threads)
|
||||
{
|
||||
int i, num_ptls;
|
||||
bool user_threads, hidden_threads;
|
||||
ompi_list_item_t *item;
|
||||
mca_base_module_list_item_t *mli;
|
||||
mca_ptl_base_module_t *module;
|
||||
mca_ptl_t **actions;
|
||||
mca_ptl_base_selected_module_t *sm;
|
||||
|
||||
/* Traverse the list of available modules; call their init
|
||||
functions. */
|
||||
|
||||
for (item = ompi_list_get_first(&mca_ptl_base_modules_available);
|
||||
ompi_list_get_end(&mca_ptl_base_modules_available) != item;
|
||||
item = ompi_list_get_next(item)) {
|
||||
mli = (mca_base_module_list_item_t *) item;
|
||||
module = (mca_ptl_base_module_t *) mli->mli_module;
|
||||
|
||||
ompi_output_verbose(10, mca_ptl_base_output,
|
||||
"select: initializing %s module %s",
|
||||
module->ptlm_version.mca_type_name,
|
||||
module->ptlm_version.mca_module_name);
|
||||
if (NULL == module->ptlm_init) {
|
||||
ompi_output_verbose(10, mca_ptl_base_output,
|
||||
"select: no init function; ignoring module");
|
||||
} else {
|
||||
actions = module->ptlm_init(&num_ptls, &user_threads,
|
||||
&hidden_threads);
|
||||
|
||||
/* If the module didn't initialize, unload it */
|
||||
|
||||
if (NULL == actions) {
|
||||
ompi_output_verbose(10, mca_ptl_base_output,
|
||||
"select: init returned failure");
|
||||
|
||||
mca_base_module_repository_release((mca_base_module_t *) module);
|
||||
ompi_output_verbose(10, mca_ptl_base_output,
|
||||
"select: module %s unloaded",
|
||||
module->ptlm_version.mca_module_name);
|
||||
}
|
||||
|
||||
/* Otherwise, it initialized properly. Save it. */
|
||||
|
||||
else {
|
||||
*allow_multi_user_threads |= user_threads;
|
||||
*have_hidden_threads |= hidden_threads;
|
||||
|
||||
ompi_output_verbose(10, mca_ptl_base_output,
|
||||
"select: init returned success");
|
||||
|
||||
for (i = 0; i < num_ptls; ++i) {
|
||||
sm = malloc(sizeof(mca_ptl_base_selected_module_t));
|
||||
if (NULL == sm) {
|
||||
return OMPI_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
OBJ_CONSTRUCT(sm, ompi_list_item_t);
|
||||
sm->pbsm_module = module;
|
||||
sm->pbsm_actions = actions[i];
|
||||
ompi_list_append(&mca_ptl_base_modules_initialized,
|
||||
(ompi_list_item_t*) sm);
|
||||
}
|
||||
free(actions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Finished querying all modules. Check for the bozo case. */
|
||||
|
||||
if (0 == ompi_list_get_size(&mca_ptl_base_modules_initialized)) {
|
||||
/* JMS Replace with show_help */
|
||||
ompi_abort(1, "No ptl module available. This shouldn't happen.");
|
||||
}
|
||||
|
||||
/* All done */
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
67
src/mca/mem/mem.h
Обычный файл
67
src/mca/mem/mem.h
Обычный файл
@ -0,0 +1,67 @@
|
||||
/**
|
||||
* $HEADER$
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*/
|
||||
#ifndef MCA_MEM_H
|
||||
#define MCA_MEM_H
|
||||
#include "mca/mca.h"
|
||||
|
||||
|
||||
/**
|
||||
* allocate function typedef
|
||||
*/
|
||||
typedef void*(*mca_mem_alloc_fn_t)(size_t);
|
||||
|
||||
/**
|
||||
* allocate align function typedef
|
||||
*/
|
||||
typedef void*(*mca_mem_alloc_align_fn_t)(size_t, size_t);
|
||||
|
||||
/**
|
||||
* free function typedef
|
||||
*/
|
||||
typedef void(*mca_mem_free_fn_t)(void *);
|
||||
|
||||
/**
|
||||
* register memory
|
||||
*/
|
||||
typedef void(*mca_mem_register_fn_t)(void *, size_t);
|
||||
|
||||
/**
|
||||
* deregister memory
|
||||
*/
|
||||
typedef void(*mca_mem_deregister_fn_t)(void *);
|
||||
|
||||
typedef int (*mca_mem_base_finalize_fn_t)(
|
||||
struct mca_mem_t* mem
|
||||
);
|
||||
|
||||
struct mca_mem_t {
|
||||
/* interface functions */
|
||||
mca_mem_alloc_fn_t mem_alloc;
|
||||
mca_mem_alloc_align_fn_t mem_alloc_align;
|
||||
mca_mem_free_fn_t mem_free;
|
||||
mca_mem_register_fn_t mem_register;
|
||||
mca_mem_deregister_fn_t mem_deregister;
|
||||
mca_mem_base_finalize_fn_t mem_finalize;
|
||||
};
|
||||
typedef struct mca_mem_t mca_mem_t;
|
||||
|
||||
/**
|
||||
* module initialization function
|
||||
*/
|
||||
typedef struct mca_mem_t* (*mca_mem_base_module_init_fn_t)(
|
||||
bool *allow_multi_user_threads
|
||||
);
|
||||
|
||||
struct mca_mem_base_module_1_0_0_t {
|
||||
mca_base_module_t mem_version;
|
||||
mca_base_module_data_1_0_0_t mem_data;
|
||||
mca_mem_base_module_init_fn_t mem_init;
|
||||
};
|
||||
typedef struct mca_mem_base_module_1_0_0_t mca_mem_base_module_t;
|
||||
|
||||
#endif /* MCA_MEM_H */
|
||||
|
@ -17,7 +17,7 @@ headers = \
|
||||
mem_globals.h \
|
||||
mem_pool.h \
|
||||
seg_list.h \
|
||||
sharedmem_util.h
|
||||
sharedmem_util.h
|
||||
|
||||
libmem_la_SOURCES = \
|
||||
$(headers) \
|
||||
@ -28,7 +28,7 @@ libmem_la_SOURCES = \
|
||||
mem_globals.c \
|
||||
mem_pool.c \
|
||||
seg_list.c \
|
||||
sharedmem_util.c
|
||||
sharedmem_util.c
|
||||
|
||||
# Conditionally install the header files
|
||||
|
||||
|
@ -5,4 +5,4 @@
|
||||
|
||||
include $(top_srcdir)/config/Makefile.options
|
||||
|
||||
SUBDIRS = support class util threads
|
||||
SUBDIRS = support mem class util threads
|
||||
|
21
test/mem/Makefile.am
Обычный файл
21
test/mem/Makefile.am
Обычный файл
@ -0,0 +1,21 @@
|
||||
# -*- makefile -*-
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
include $(top_srcdir)/config/Makefile.options
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/test/support -I. -DOMPI_ENABLE_DEBUG_OVERRIDE=1
|
||||
|
||||
noinst_PROGRAMS = \
|
||||
alloc_test
|
||||
|
||||
alloc_test_SOURCES = alloc_test.c
|
||||
alloc_test_LDADD = \
|
||||
$(top_builddir)/src/mca/mem/base/mem_base_allocator.lo \
|
||||
$(top_builddir)/src/threads/mutex.lo \
|
||||
$(top_builddir)/src/threads/mutex_pthread.lo \
|
||||
$(top_builddir)/src/threads/mutex_spinlock.lo \
|
||||
$(top_builddir)/src/class/ompi_object.lo \
|
||||
$(top_builddir)/src/mem/malloc.lo \
|
||||
$(top_builddir)/src/util/output.lo
|
||||
|
41
test/mem/alloc_test.c
Обычный файл
41
test/mem/alloc_test.c
Обычный файл
@ -0,0 +1,41 @@
|
||||
#include "mca/mem/base/mem_base_allocator.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* the multiple to allocate -- for testing purposes */
|
||||
#define NUM_TIMES_ALLOC 5
|
||||
|
||||
void * allocate(size_t *);
|
||||
|
||||
|
||||
void* allocate(size_t * size) {
|
||||
*size *= NUM_TIMES_ALLOC;
|
||||
return((void *)malloc(*size));
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
void * orig = (void *) 1;
|
||||
int choice;
|
||||
mca_mem_options_t * mem_options = mca_mem_init(30, allocate, free);
|
||||
printf("Address of mem_options_t: %p \n", (void *)mem_options);
|
||||
while(choice)
|
||||
{
|
||||
printf("allocate: 1 free: 2 cleanup: 3 exit: 0 ");
|
||||
scanf("%d", &choice);
|
||||
if(1 == choice) {
|
||||
printf("enter size: ");
|
||||
scanf("%d", &choice);
|
||||
orig = mca_mem_alloc(mem_options, choice);
|
||||
printf("the pointer of the allocated region: %p\n", orig);
|
||||
} else if (2 == choice) {
|
||||
printf("enter pointer to free: ");
|
||||
scanf("%p", &orig);
|
||||
mca_mem_free(mem_options, orig);
|
||||
} else if (3 == choice) {
|
||||
mca_mem_cleanup(mem_options);
|
||||
} else if (0 != choice) {
|
||||
printf("invalid option\n");
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
Загрузка…
x
Ссылка в новой задаче
Block a user