Revamp MPI_Info handling a bit:
- fix a few bugs - convert/add doxygen comments for internal info functions in src/info/info.h (some comments were originally in src/info/info.c) - make it thread safe - make MPI_INFO_NULL be a real object (vs ((struct ompi_info_t*) 0)) - add error checking into top-level MPI functions - add support in MPI_Info for "never freeing MPI handles" as a form of debugging i.e., check if see if you accidentally use a freed handle) - add support for "print out a list of un-freed MPI_Info handles during MPI_FINALIZE" This commit was SVN r2089.
Этот коммит содержится в:
родитель
2b64fdd0dd
Коммит
726af9ea85
@ -276,7 +276,7 @@ enum {
|
||||
#define MPI_REQUEST_NULL ((MPI_Request) 0)
|
||||
#define MPI_OP_NULL (&ompi_mpi_op_null)
|
||||
#define MPI_ERRHANDLER_NULL (&ompi_mpi_errhandler_null)
|
||||
#define MPI_INFO_NULL ((MPI_Info) 0)
|
||||
#define MPI_INFO_NULL (&ompi_mpi_info_null)
|
||||
#define MPI_WIN_NULL ((MPI_Win) 0)
|
||||
#define MPI_FILE_NULL ((MPI_File) 0)
|
||||
|
||||
@ -399,6 +399,8 @@ extern struct ompi_errhandler_t ompi_mpi_errhandler_null;
|
||||
extern struct ompi_errhandler_t ompi_mpi_errors_are_fatal;
|
||||
extern struct ompi_errhandler_t ompi_mpi_errors_return;
|
||||
|
||||
extern struct ompi_info_t ompi_mpi_info_null;
|
||||
|
||||
extern MPI_Fint *MPI_F_STATUS_IGNORE;
|
||||
extern MPI_Fint *MPI_F_STATUSES_IGNORE;
|
||||
|
||||
|
465
src/info/info.c
465
src/info/info.c
@ -1,134 +1,189 @@
|
||||
/**
|
||||
/*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "info/info.h"
|
||||
#include "include/constants.h"
|
||||
#include "mpi/runtime/mpiruntime.h"
|
||||
#include "util/output.h"
|
||||
|
||||
|
||||
/*
|
||||
* Global variables
|
||||
*/
|
||||
ompi_info_t ompi_mpi_info_null;
|
||||
|
||||
|
||||
/*
|
||||
* Local functions
|
||||
*/
|
||||
static void ompi_info_construct(ompi_info_t *info);
|
||||
static void ompi_info_destruct(ompi_info_t *info);
|
||||
static void ompi_info_entry_construct(ompi_info_entry_t *entry);
|
||||
static void ompi_info_entry_destruct(ompi_info_entry_t *entry);
|
||||
static ompi_info_entry_t *ompi_info_find_key (ompi_info_t *info, char *key);
|
||||
|
||||
|
||||
/*
|
||||
* ompi_info_t classes
|
||||
*/
|
||||
ompi_class_t ompi_info_t_class = {
|
||||
"ompi_info_t",
|
||||
OBJ_CLASS(ompi_list_t),
|
||||
(ompi_construct_t)ompi_info_construct,
|
||||
(ompi_destruct_t)ompi_info_destruct
|
||||
};
|
||||
OBJ_CLASS_INSTANCE(ompi_info_t,
|
||||
ompi_list_t,
|
||||
ompi_info_construct,
|
||||
ompi_info_destruct);
|
||||
|
||||
/*
|
||||
* ompi_info_entry_t classes
|
||||
*/
|
||||
ompi_class_t ompi_info_entry_t_class = {
|
||||
"ompi_info_entry_t",
|
||||
OBJ_CLASS(ompi_list_item_t),
|
||||
(ompi_construct_t)ompi_info_entry_construct,
|
||||
(ompi_destruct_t)ompi_info_entry_destruct
|
||||
};
|
||||
OBJ_CLASS_INSTANCE(ompi_info_entry_t,
|
||||
ompi_list_item_t,
|
||||
ompi_info_entry_construct,
|
||||
ompi_info_entry_destruct);
|
||||
|
||||
/**
|
||||
/*
|
||||
* The global fortran <-> C translation table
|
||||
*/
|
||||
ompi_pointer_array_t *ompi_info_f_to_c_table;
|
||||
|
||||
/*
|
||||
* ompi_info_t interface functions
|
||||
* @param info ompi_info_t pointer
|
||||
*
|
||||
* This function is invoked when OBJ_NEW() is called. Here, we add this
|
||||
* info pointer to the table and then store its index as the handle
|
||||
*/
|
||||
void ompi_info_construct(ompi_info_t *info) {
|
||||
info->i_fhandle = ompi_pointer_array_add(ompi_info_f_to_c_table, info);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* ompi_info_t interface function
|
||||
* @param info ompi_info_t pointer
|
||||
*
|
||||
* This function is called during OBJ_DESTRUCT of "info". When this
|
||||
* done, we need to remove the entry from the ompi fortran to C
|
||||
* translation table
|
||||
/*
|
||||
* This function is called during ompi_init and initializes the
|
||||
* fortran to C translation table.
|
||||
*/
|
||||
void ompi_info_destruct(ompi_info_t *info) {
|
||||
/*
|
||||
* reset the ompi_info_f_to_c_table entry - make sure that the
|
||||
* entry is in the table
|
||||
*/
|
||||
if (NULL != ompi_pointer_array_get_item(ompi_info_f_to_c_table, info->i_fhandle)){
|
||||
ompi_pointer_array_set_item(ompi_info_f_to_c_table, info->i_fhandle, NULL);
|
||||
int ompi_info_init(void)
|
||||
{
|
||||
/* initialize table */
|
||||
|
||||
ompi_info_f_to_c_table = OBJ_NEW(ompi_pointer_array_t);
|
||||
if (NULL == ompi_info_f_to_c_table) {
|
||||
return OMPI_ERROR;
|
||||
}
|
||||
return;
|
||||
|
||||
/* Create MPI_INFO_NULL */
|
||||
|
||||
OBJ_CONSTRUCT(&ompi_mpi_info_null, ompi_info_t);
|
||||
ompi_mpi_info_null.i_fhandle = 0;
|
||||
|
||||
/* All done */
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ompi_info_entry_t interface functions
|
||||
* Shut down MPI_Info handling
|
||||
*/
|
||||
void ompi_info_entry_construct(ompi_info_entry_t *entry) {
|
||||
memset(entry->ie_key, 0, sizeof(entry->ie_key));
|
||||
entry->ie_key[MPI_MAX_INFO_KEY] = 0;
|
||||
}
|
||||
int ompi_info_finalize(void)
|
||||
{
|
||||
size_t i, max;
|
||||
ompi_info_t *info;
|
||||
ompi_list_item_t *item;
|
||||
ompi_info_entry_t *entry;
|
||||
bool found = false;
|
||||
|
||||
void ompi_info_entry_destruct(ompi_info_entry_t *entry) {
|
||||
if (NULL != entry->ie_value) {
|
||||
free(entry->ie_value);
|
||||
/* Destroy MPI_INFO_NULL */
|
||||
|
||||
OBJ_DESTRUCT(&ompi_mpi_info_null);
|
||||
|
||||
/* Go through the f2c table and see if anything is left. Free them
|
||||
all. */
|
||||
|
||||
max = ompi_pointer_array_get_size(ompi_info_f_to_c_table);
|
||||
for (i = 0; i < max; ++i) {
|
||||
info = ompi_pointer_array_get_item(ompi_info_f_to_c_table, i);
|
||||
|
||||
/* If the info was freed but still exists because the user told us
|
||||
to never free handles, then do an OBJ_RELEASE it and all is
|
||||
well. Then get the value again and see if it's actually been
|
||||
freed. */
|
||||
|
||||
if (NULL != info && ompi_debug_handle_never_free && info->i_freed) {
|
||||
OBJ_RELEASE(info);
|
||||
info = ompi_pointer_array_get_item(ompi_info_f_to_c_table, i);
|
||||
}
|
||||
|
||||
/* If it still exists here and was never freed, then it's an
|
||||
orphan */
|
||||
|
||||
if (NULL != info) {
|
||||
|
||||
/* If the user wanted warnings about MPI object leaks, print out
|
||||
a message */
|
||||
|
||||
if (!info->i_freed && ompi_debug_show_handle_leaks) {
|
||||
if (ompi_debug_show_handle_leaks) {
|
||||
ompi_output(0, "WARNING: MPI_Info still allocated at MPI_FINALIZE");
|
||||
for (item = ompi_list_get_first(&(info->super));
|
||||
ompi_list_get_end(&(info->super)) != item;
|
||||
item = ompi_list_get_next(item)) {
|
||||
entry = (ompi_info_entry_t *) item;
|
||||
ompi_output(0, "WARNING: key=\"%s\", value=\"%s\"",
|
||||
entry->ie_key,
|
||||
NULL != entry->ie_value ? entry->ie_value : "(null)");
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
OBJ_RELEASE(info);
|
||||
}
|
||||
|
||||
/* Don't bother setting each element back down to NULL; it would
|
||||
just take a lot of thread locks / unlocks and since we're
|
||||
destroying everything, it isn't worth it */
|
||||
|
||||
if (!found) {
|
||||
ompi_output(0, "WARNING: (no keys)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* All done -- release the table */
|
||||
|
||||
OBJ_RELEASE(ompi_info_f_to_c_table);
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* MPI_Info_dup - Duplicate an 'MPI_Info' object
|
||||
*
|
||||
* @param info source info object (handle)
|
||||
* @param newinfo pointer to the new info object (handle)
|
||||
*
|
||||
* @retval MPI_SUCCESS
|
||||
* @retval MPI_ERR_SYSRESOURCE
|
||||
*
|
||||
* Not only will the (key, value) pairs be duplicated, the order of keys
|
||||
* will be the same in 'newinfo' as it is in 'info'.
|
||||
* When an info object is no longer being used, it should be freed with
|
||||
* 'MPI_Info_free'.
|
||||
|
||||
/*
|
||||
* Duplicate an info
|
||||
*/
|
||||
int ompi_info_dup (ompi_info_t *info, ompi_info_t **newinfo) {
|
||||
int ompi_info_dup (ompi_info_t *info, ompi_info_t **newinfo)
|
||||
{
|
||||
int err;
|
||||
ompi_list_item_t *item;
|
||||
ompi_info_entry_t *iterator;
|
||||
|
||||
for (iterator = (ompi_info_entry_t *)ompi_list_get_first(&(info->super));
|
||||
NULL != iterator;
|
||||
iterator = (ompi_info_entry_t *)ompi_list_get_next(iterator)) {
|
||||
OMPI_THREAD_LOCK(info->i_lock);
|
||||
for (item = ompi_list_get_first(&(info->super));
|
||||
item != ompi_list_get_end(&(info->super));
|
||||
item = ompi_list_get_next(iterator)) {
|
||||
iterator = (ompi_info_entry_t *) item;
|
||||
err = ompi_info_set(*newinfo, iterator->ie_key, iterator->ie_value);
|
||||
if (MPI_SUCCESS != err) {
|
||||
OMPI_THREAD_UNLOCK(info->i_lock);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
OMPI_THREAD_UNLOCK(info->i_lock);
|
||||
return MPI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set a new key,value pair on info
|
||||
*
|
||||
* @param info pointer to ompi_info_t object
|
||||
* @param key pointer to the new key object
|
||||
* @param value pointer to the new value object
|
||||
*
|
||||
* @retval MPI_SUCCESS
|
||||
* @retval MPI_ERR_SYSRESOURCE
|
||||
* Set a value on the info
|
||||
*/
|
||||
int ompi_info_set (ompi_info_t *info, char *key, char *value) {
|
||||
int ompi_info_set (ompi_info_t *info, char *key, char *value)
|
||||
{
|
||||
char *new_value;
|
||||
ompi_info_entry_t *new_info;
|
||||
ompi_info_entry_t *old_info;
|
||||
int value_length;
|
||||
|
||||
value_length = strlen(value);
|
||||
new_value = malloc(value_length * sizeof(char));
|
||||
new_value = strdup(value);
|
||||
if (NULL == new_value) {
|
||||
return MPI_ERR_SYSRESOURCE;
|
||||
return MPI_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
strcpy (new_value, value);
|
||||
OMPI_THREAD_LOCK(info->i_lock);
|
||||
old_info = ompi_info_find_key (info, key);
|
||||
|
||||
if (NULL != old_info) {
|
||||
/*
|
||||
* key already exists. remove the value associated with it
|
||||
@ -138,69 +193,41 @@ int ompi_info_set (ompi_info_t *info, char *key, char *value) {
|
||||
} else {
|
||||
new_info = OBJ_NEW(ompi_info_entry_t);
|
||||
if (NULL == new_info) {
|
||||
return MPI_ERR_SYSRESOURCE;
|
||||
OMPI_THREAD_UNLOCK(info->i_lock);
|
||||
return MPI_ERR_NO_MEM;
|
||||
}
|
||||
strcpy (new_info->ie_key, key);
|
||||
new_info->ie_value = new_value;
|
||||
ompi_list_append (&(info->super), (ompi_list_item_t *) new_info);
|
||||
}
|
||||
OMPI_THREAD_UNLOCK(info->i_lock);
|
||||
return MPI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* ompi_info_free - Free an 'MPI_Info' object.
|
||||
*
|
||||
* @param info pointer to info (ompi_info_t *) object to be freed (handle)
|
||||
*
|
||||
* @retval MPI_SUCCESS
|
||||
* @retval MPI_ERR_ARG
|
||||
*
|
||||
* Upon successful completion, 'info' will be set to 'MPI_INFO_NULL'.
|
||||
|
||||
/*
|
||||
* Free an info handle and all of its keys and values.
|
||||
*/
|
||||
int ompi_info_free (ompi_info_t **info) {
|
||||
ompi_info_entry_t *iterator;
|
||||
ompi_info_entry_t *trailer_iterator;
|
||||
|
||||
/*
|
||||
* We could just get each element from the list and then call
|
||||
* MPI_Info_delete. But this causes unnecessary delay because
|
||||
* MPI_Info_delete has extra logic to it. So, do the simple
|
||||
* remove operation to save time.
|
||||
*/
|
||||
for (iterator = (ompi_info_entry_t *)ompi_list_get_first(&((*info)->super));
|
||||
NULL != iterator;
|
||||
iterator = (ompi_info_entry_t *)ompi_list_get_next(iterator)) {
|
||||
trailer_iterator = (ompi_info_entry_t *)ompi_list_get_prev(iterator);
|
||||
OBJ_RELEASE(trailer_iterator);
|
||||
}
|
||||
|
||||
OBJ_RELEASE(*info);
|
||||
*info = MPI_INFO_NULL;
|
||||
return MPI_SUCCESS;
|
||||
int ompi_info_free (ompi_info_t **info)
|
||||
{
|
||||
(*info)->i_freed = true;
|
||||
OBJ_RELEASE(*info);
|
||||
*info = MPI_INFO_NULL;
|
||||
return MPI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* ompi_info_get- Get a (key, value) pair from an 'MPI_Info' object
|
||||
*
|
||||
* @param info Pointer to ompi_info_t object
|
||||
* @param key null-terminated character string of the index key
|
||||
* @param valuelen maximum length of 'value' (integer)
|
||||
* @param value null-terminated character string of the value
|
||||
* @param flag true (1) if 'key' defined on 'info', false (0) if not
|
||||
* (logical)
|
||||
*
|
||||
* @retval MPI_SUCCESS
|
||||
*
|
||||
* In C and C++, 'valuelen' should be one less than the allocated space
|
||||
* to allow for for the null terminator.
|
||||
|
||||
/*
|
||||
* Get a value from an info
|
||||
*/
|
||||
int ompi_info_get (ompi_info_t *info, char *key, int valuelen,
|
||||
char *value, int *flag) {
|
||||
char *value, int *flag)
|
||||
{
|
||||
ompi_info_entry_t *search;
|
||||
int value_length;
|
||||
|
||||
OMPI_THREAD_LOCK(info->i_lock);
|
||||
search = ompi_info_find_key (info, key);
|
||||
|
||||
if (NULL == search){
|
||||
*flag = 0;
|
||||
} else {
|
||||
@ -222,26 +249,23 @@ int ompi_info_get (ompi_info_t *info, char *key, int valuelen,
|
||||
value[valuelen] = 0;
|
||||
}
|
||||
}
|
||||
OMPI_THREAD_UNLOCK(info->i_lock);
|
||||
return MPI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a (key,value) pair from "info"
|
||||
*
|
||||
* @param info ompi_info_t pointer on which we need to operate
|
||||
* @param key The key portion of the (key,value) pair that
|
||||
* needs to be deleted
|
||||
*
|
||||
* @retval MPI_SUCCESS
|
||||
* @retval MPI_ERR_NOKEY
|
||||
|
||||
/*
|
||||
* Delete a key from an info
|
||||
*/
|
||||
int ompi_info_delete (ompi_info_t *info, char *key) {
|
||||
int ompi_info_delete (ompi_info_t *info, char *key)
|
||||
{
|
||||
ompi_info_entry_t *search;
|
||||
ompi_info_entry_t *found;
|
||||
|
||||
OMPI_THREAD_LOCK(info->i_lock);
|
||||
search = ompi_info_find_key (info, key);
|
||||
|
||||
if (NULL == search){
|
||||
OMPI_THREAD_UNLOCK(info->i_lock);
|
||||
return MPI_ERR_INFO_NOKEY;
|
||||
} else {
|
||||
/*
|
||||
@ -249,32 +273,24 @@ int ompi_info_delete (ompi_info_t *info, char *key) {
|
||||
* and free the memory allocated to it
|
||||
*/
|
||||
found = (ompi_info_entry_t *)
|
||||
ompi_list_remove_item (&(info->super),
|
||||
(ompi_list_item_t *)search);
|
||||
ompi_list_remove_item (&(info->super),
|
||||
(ompi_list_item_t *)search);
|
||||
OBJ_RELEASE(search);
|
||||
}
|
||||
OMPI_THREAD_UNLOCK(info->i_lock);
|
||||
return MPI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param info - ompi_info_t pointer object (handle)
|
||||
* @param key - null-terminated character string of the index key
|
||||
* @param valuelen - length of the value associated with 'key' (integer)
|
||||
* @param flag - true (1) if 'key' defined on 'info', false (0) if not
|
||||
* (logical)
|
||||
*
|
||||
* @retval MPI_SUCCESS
|
||||
* @retval MPI_ERR_ARG
|
||||
* @retval MPI_ERR_INFO_KEY
|
||||
*
|
||||
* The length returned in C and C++ does not include the end-of-string
|
||||
* character. If the 'key' is not found on 'info', 'valuelen' is left
|
||||
* alone.
|
||||
|
||||
/*
|
||||
* Return the length of a value
|
||||
*/
|
||||
int ompi_info_get_valuelen (ompi_info_t *info, char *key, int *valuelen,
|
||||
int *flag) {
|
||||
int *flag)
|
||||
{
|
||||
ompi_info_entry_t *search;
|
||||
|
||||
OMPI_THREAD_LOCK(info->i_lock);
|
||||
search = ompi_info_find_key (info, key);
|
||||
if (NULL == search){
|
||||
*flag = 0;
|
||||
@ -286,32 +302,135 @@ int ompi_info_get_valuelen (ompi_info_t *info, char *key, int *valuelen,
|
||||
*flag = 1;
|
||||
*valuelen = strlen(search->ie_value);
|
||||
}
|
||||
OMPI_THREAD_UNLOCK(info->i_lock);
|
||||
return MPI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* function: ompi_info_init
|
||||
*
|
||||
* This function is called during ompi_init and initializes the fortran to C
|
||||
|
||||
/*
|
||||
* Get the nth key
|
||||
*/
|
||||
int ompi_info_get_nthkey (ompi_info_t *info, int n, char *key)
|
||||
{
|
||||
ompi_info_entry_t *iterator;
|
||||
|
||||
/*
|
||||
* Iterate over and over till we get to the nth key
|
||||
*/
|
||||
OMPI_THREAD_LOCK(info->i_lock);
|
||||
for (iterator = (ompi_info_entry_t *)ompi_list_get_first(&(info->super));
|
||||
n > 0;
|
||||
--n) {
|
||||
iterator = (ompi_info_entry_t *)ompi_list_get_next(iterator);
|
||||
if (ompi_list_get_end(&(info->super)) ==
|
||||
(ompi_list_item_t *) iterator) {
|
||||
OMPI_THREAD_UNLOCK(info->i_lock);
|
||||
return MPI_ERR_ARG;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* iterator is of the type ompi_list_item_t. We have to
|
||||
* cast it to ompi_info_entry_t before we can use it to
|
||||
* access the value
|
||||
*/
|
||||
strcpy(key, iterator->ie_key);
|
||||
OMPI_THREAD_UNLOCK(info->i_lock);
|
||||
return MPI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function is invoked when OBJ_NEW() is called. Here, we add this
|
||||
* info pointer to the table and then store its index as the handle
|
||||
*/
|
||||
static void ompi_info_construct(ompi_info_t *info)
|
||||
{
|
||||
info->i_fhandle = ompi_pointer_array_add(ompi_info_f_to_c_table, info);
|
||||
info->i_lock = OBJ_NEW(ompi_mutex_t);
|
||||
info->i_freed = false;
|
||||
|
||||
/* If the user doesn't want us to ever free it, then add an extra
|
||||
RETAIN here */
|
||||
|
||||
if (ompi_debug_handle_never_free) {
|
||||
OBJ_RETAIN(&(info->super));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function is called during OBJ_DESTRUCT of "info". When this
|
||||
* done, we need to remove the entry from the ompi fortran to C
|
||||
* translation table
|
||||
*/
|
||||
int ompi_info_init(void) {
|
||||
/* initialize table */
|
||||
ompi_info_f_to_c_table = OBJ_NEW(ompi_pointer_array_t);
|
||||
if (NULL == ompi_info_f_to_c_table) {
|
||||
return OMPI_ERROR;
|
||||
}
|
||||
return OMPI_SUCCESS;
|
||||
static void ompi_info_destruct(ompi_info_t *info)
|
||||
{
|
||||
ompi_list_item_t *item;
|
||||
ompi_info_entry_t *iterator;
|
||||
|
||||
/* Remove every key in the list */
|
||||
|
||||
for (item = ompi_list_remove_first(&(info->super));
|
||||
NULL != item;
|
||||
item = ompi_list_remove_first(&(info->super))) {
|
||||
iterator = (ompi_info_entry_t *) item;
|
||||
OBJ_RELEASE(iterator);
|
||||
}
|
||||
|
||||
/* reset the ompi_info_f_to_c_table entry - make sure that the
|
||||
entry is in the table */
|
||||
|
||||
if (NULL != ompi_pointer_array_get_item(ompi_info_f_to_c_table,
|
||||
info->i_fhandle)){
|
||||
ompi_pointer_array_set_item(ompi_info_f_to_c_table,
|
||||
info->i_fhandle, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* function: ompi_info_finalize
|
||||
*
|
||||
* This functions is called during MPI Finalize
|
||||
|
||||
/*
|
||||
* ompi_info_entry_t interface functions
|
||||
*/
|
||||
int ompi_info_finalize(void) {
|
||||
/* finalize */
|
||||
OBJ_RELEASE(ompi_info_f_to_c_table);
|
||||
return OMPI_SUCCESS;
|
||||
static void ompi_info_entry_construct(ompi_info_entry_t *entry)
|
||||
{
|
||||
memset(entry->ie_key, 0, sizeof(entry->ie_key));
|
||||
entry->ie_key[MPI_MAX_INFO_KEY] = 0;
|
||||
}
|
||||
|
||||
|
||||
static void ompi_info_entry_destruct(ompi_info_entry_t *entry)
|
||||
{
|
||||
if (NULL != entry->ie_value) {
|
||||
free(entry->ie_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Find a key
|
||||
*
|
||||
* Do NOT thread lock in here -- the calling function is responsible
|
||||
* for that.
|
||||
*/
|
||||
static ompi_info_entry_t *ompi_info_find_key (ompi_info_t *info, char *key)
|
||||
{
|
||||
ompi_info_entry_t *iterator;
|
||||
|
||||
/* No thread locking in here! */
|
||||
|
||||
/* Iterate over all the entries. If the key is found, then
|
||||
* return immediately. Else, the loop will fall of the edge
|
||||
* and NULL is returned
|
||||
*/
|
||||
for (iterator = (ompi_info_entry_t *)ompi_list_get_first(&(info->super));
|
||||
ompi_list_get_end(&(info->super)) != (ompi_list_item_t*) iterator;
|
||||
iterator = (ompi_info_entry_t *)ompi_list_get_next(iterator)) {
|
||||
if (0 == strcmp(key, iterator->ie_key)) {
|
||||
return iterator;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
254
src/info/info.h
254
src/info/info.h
@ -11,21 +11,35 @@
|
||||
#include "util/strncpy.h"
|
||||
#include "class/ompi_list.h"
|
||||
#include "class/ompi_pointer_array.h"
|
||||
#include "threads/mutex.h"
|
||||
#include "include/ompi.h"
|
||||
|
||||
|
||||
/**
|
||||
* \internal
|
||||
* ompi_info_t structure. MPI_Info is a pointer to this structure
|
||||
*/
|
||||
struct ompi_info_t {
|
||||
ompi_list_t super; /**< generic list pointer which is
|
||||
* the container for (key,value) pairs */
|
||||
int i_fhandle; /**< fortran handle for info. This is needed
|
||||
* for translation from fortran to C and vice versa */
|
||||
ompi_list_t super;
|
||||
/**< generic list pointer which is the container for (key,value)
|
||||
pairs */
|
||||
int i_fhandle;
|
||||
/**< fortran handle for info. This is needed for translation from
|
||||
fortran to C and vice versa */
|
||||
ompi_mutex_t *i_lock;
|
||||
/**< Mutex for thread safety */
|
||||
bool i_freed;
|
||||
/**< Whether this info has been freed or not */
|
||||
};
|
||||
/**
|
||||
* \internal
|
||||
* Convenience typedef
|
||||
*/
|
||||
typedef struct ompi_info_t ompi_info_t;
|
||||
|
||||
/**
|
||||
* \internal
|
||||
*
|
||||
* ompi_info_entry_t object. Each item in ompi_info_list is of this
|
||||
* type. It contains (key,value) pairs
|
||||
*/
|
||||
@ -36,6 +50,10 @@ struct ompi_info_entry_t {
|
||||
char ie_key[MPI_MAX_INFO_KEY + 1]; /**< "key" part of the (key, value)
|
||||
* pair */
|
||||
};
|
||||
/**
|
||||
* \internal
|
||||
* Convenience typedef
|
||||
*/
|
||||
typedef struct ompi_info_entry_t ompi_info_entry_t;
|
||||
|
||||
/**
|
||||
@ -44,68 +62,165 @@ typedef struct ompi_info_entry_t ompi_info_entry_t;
|
||||
extern ompi_pointer_array_t *ompi_info_f_to_c_table;
|
||||
|
||||
/**
|
||||
* Global instance for MPI_INFO_NULL
|
||||
*/
|
||||
extern ompi_info_t ompi_mpi_info_null;
|
||||
|
||||
/**
|
||||
* \internal
|
||||
* Some declarations needed to use OBJ_NEW and OBJ_DESTRUCT macros
|
||||
*/
|
||||
extern ompi_class_t ompi_info_t_class;
|
||||
extern ompi_class_t ompi_info_entry_t_class;
|
||||
OBJ_CLASS_DECLARATION(ompi_info_t);
|
||||
|
||||
/**
|
||||
* \internal
|
||||
* Some declarations needed to use OBJ_NEW and OBJ_DESTRUCT macros
|
||||
*/
|
||||
OBJ_CLASS_DECLARATION(ompi_info_entry_t);
|
||||
|
||||
|
||||
#if defined(c_plusplus) || defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
int ompi_info_init(void);
|
||||
int ompi_info_finalize(void);
|
||||
void ompi_info_construct(ompi_info_t *info);
|
||||
void ompi_info_destruct(ompi_info_t *info);
|
||||
/**
|
||||
* This function is invoked during ompi_mpi_init() and sets up
|
||||
* MPI_Info handling.
|
||||
*/
|
||||
int ompi_info_init(void);
|
||||
|
||||
void ompi_info_entry_construct(ompi_info_entry_t *entry);
|
||||
void ompi_info_entry_destruct(ompi_info_entry_t *entry);
|
||||
int ompi_info_dup (ompi_info_t *info, ompi_info_t **newinfo);
|
||||
int ompi_info_set (ompi_info_t *info, char *key, char *value);
|
||||
int ompi_info_free (ompi_info_t **info);
|
||||
int ompi_info_get (ompi_info_t *info, char *key, int valuelen,
|
||||
char *value, int *flag);
|
||||
int ompi_info_delete (ompi_info_t *info, char *key);
|
||||
int ompi_info_get_valuelen (ompi_info_t *info, char *key, int *valuelen,
|
||||
int *flag);
|
||||
/**
|
||||
* This functions is called during ompi_mpi_finalize() and shuts
|
||||
* down MPI_Info handling.
|
||||
*/
|
||||
int ompi_info_finalize(void);
|
||||
|
||||
/**
|
||||
* ompi_info_dup - Duplicate an 'MPI_Info' object
|
||||
*
|
||||
* @param info source info object (handle)
|
||||
* @param newinfo pointer to the new info object (handle)
|
||||
*
|
||||
* @retval MPI_SUCCESS upon success
|
||||
* @retval MPI_ERR_NO_MEM if out of memory
|
||||
*
|
||||
* Not only will the (key, value) pairs be duplicated, the order
|
||||
* of keys will be the same in 'newinfo' as it is in 'info'. When
|
||||
* an info object is no longer being used, it should be freed with
|
||||
* 'MPI_Info_free'.
|
||||
*/
|
||||
int ompi_info_dup (ompi_info_t *info, ompi_info_t **newinfo);
|
||||
|
||||
/*
|
||||
* Set a new key,value pair on info.
|
||||
*
|
||||
* @param info pointer to ompi_info_t object
|
||||
* @param key pointer to the new key object
|
||||
* @param value pointer to the new value object
|
||||
*
|
||||
* @retval MPI_SUCCESS upon success
|
||||
* @retval MPI_ERR_NO_MEM if out of memory
|
||||
*/
|
||||
int ompi_info_set (ompi_info_t *info, char *key, char *value);
|
||||
|
||||
/**
|
||||
* ompi_info_free - Free an 'MPI_Info' object.
|
||||
*
|
||||
* @param info pointer to info (ompi_info_t *) object to be freed (handle)
|
||||
*
|
||||
* @retval MPI_SUCCESS
|
||||
* @retval MPI_ERR_ARG
|
||||
*
|
||||
* Upon successful completion, 'info' will be set to
|
||||
* 'MPI_INFO_NULL'. Free the info handle and all of its keys and
|
||||
* values.
|
||||
*/
|
||||
int ompi_info_free (ompi_info_t **info);
|
||||
|
||||
/**
|
||||
* Get a (key, value) pair from an 'MPI_Info' object
|
||||
*
|
||||
* @param info Pointer to ompi_info_t object
|
||||
* @param key null-terminated character string of the index key
|
||||
* @param valuelen maximum length of 'value' (integer)
|
||||
* @param value null-terminated character string of the value
|
||||
* @param flag true (1) if 'key' defined on 'info', false (0) if not
|
||||
* (logical)
|
||||
*
|
||||
* @retval MPI_SUCCESS
|
||||
*
|
||||
* In C and C++, 'valuelen' should be one less than the allocated
|
||||
* space to allow for for the null terminator.
|
||||
*/
|
||||
int ompi_info_get (ompi_info_t *info, char *key, int valuelen,
|
||||
char *value, int *flag);
|
||||
|
||||
/**
|
||||
* Delete a (key,value) pair from "info"
|
||||
*
|
||||
* @param info ompi_info_t pointer on which we need to operate
|
||||
* @param key The key portion of the (key,value) pair that
|
||||
* needs to be deleted
|
||||
*
|
||||
* @retval MPI_SUCCESS
|
||||
* @retval MPI_ERR_NOKEY
|
||||
*/
|
||||
int ompi_info_delete (ompi_info_t *info, char *key);
|
||||
|
||||
/**
|
||||
* @param info - ompi_info_t pointer object (handle)
|
||||
* @param key - null-terminated character string of the index key
|
||||
* @param valuelen - length of the value associated with 'key' (integer)
|
||||
* @param flag - true (1) if 'key' defined on 'info', false (0) if not
|
||||
* (logical)
|
||||
*
|
||||
* @retval MPI_SUCCESS
|
||||
* @retval MPI_ERR_ARG
|
||||
* @retval MPI_ERR_INFO_KEY
|
||||
*
|
||||
* The length returned in C and C++ does not include the end-of-string
|
||||
* character. If the 'key' is not found on 'info', 'valuelen' is left
|
||||
* alone.
|
||||
*/
|
||||
int ompi_info_get_valuelen (ompi_info_t *info, char *key, int *valuelen,
|
||||
int *flag);
|
||||
|
||||
/**
|
||||
* ompi_info_get_nthkey - Get a key indexed by integer from an 'MPI_Info' o
|
||||
*
|
||||
* @param info Pointer to ompi_info_t object
|
||||
* @param n index of key to retrieve (integer)
|
||||
* @param key character string of at least 'MPI_MAX_INFO_KEY' characters
|
||||
*
|
||||
* @retval MPI_SUCCESS
|
||||
* @retval MPI_ERR_ARG
|
||||
*/
|
||||
int ompi_info_get_nthkey (ompi_info_t *info, int n, char *key);
|
||||
#if defined(c_plusplus) || defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Iterate through the list and search for "key"
|
||||
*
|
||||
* @param info pointer to ompi_info_t handle
|
||||
* @param key Key value to search for
|
||||
*
|
||||
* @retval (ompi_info_entry_t *) to the object having the same key
|
||||
* NULL if no matching item is found
|
||||
*
|
||||
* We need a function to go through the entries and find whether
|
||||
* a given key is already present in the list. If so, this function
|
||||
* returns the item which matches this key. It was required
|
||||
* often enough to make it into a function. No error checking on
|
||||
* info is performed.
|
||||
* Assumptions:
|
||||
* "info" is a valid key
|
||||
*/
|
||||
static inline ompi_info_entry_t *ompi_info_find_key (ompi_info_t *info,
|
||||
char *key) {
|
||||
ompi_info_entry_t *iterator;
|
||||
|
||||
/* Iterate over all the entries. If the key is found, then
|
||||
* return immediately. Else, the loop will fall of the edge
|
||||
* and NULL is returned
|
||||
*/
|
||||
for (iterator = (ompi_info_entry_t *)ompi_list_get_first(&(info->super));
|
||||
NULL != iterator;
|
||||
iterator = (ompi_info_entry_t *)ompi_list_get_next(iterator)) {
|
||||
if (0 == strcmp(key, iterator->ie_key)) {
|
||||
return iterator;
|
||||
}
|
||||
}
|
||||
return (ompi_info_entry_t *)0;
|
||||
/**
|
||||
* Return whether this info has been freed already or not.
|
||||
*
|
||||
* @param info Pointer to ompi_info_t object.
|
||||
*
|
||||
* @retval true If the info has already been freed
|
||||
* @retval false If the info has not yet been freed
|
||||
*
|
||||
* If the info has been freed, return true. This will likely only
|
||||
* happen in a reliable manner if ompi_debug_handle_never_free is
|
||||
* true, in which case an extra OBJ_RETAIN is set on the object during
|
||||
* OBJ_NEW, meaning that the user will never be able to actually free
|
||||
* the underlying object. It's a good way to find out if a process is
|
||||
* unintentionally using a freed handle.
|
||||
*/
|
||||
static inline bool ompi_info_is_freed(ompi_info_t *info)
|
||||
{
|
||||
return info->i_freed;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the number of keys defined on on an MPI_Info object
|
||||
* @param info Pointer to ompi_info_t object.
|
||||
@ -114,42 +229,11 @@ static inline ompi_info_entry_t *ompi_info_find_key (ompi_info_t *info,
|
||||
* @retval The number of keys defined on info
|
||||
*/
|
||||
static inline int
|
||||
ompi_info_get_nkeys(ompi_info_t *info, int *nkeys) {
|
||||
ompi_info_get_nkeys(ompi_info_t *info, int *nkeys)
|
||||
{
|
||||
*nkeys = (int) ompi_list_get_size(&(info->super));
|
||||
return MPI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* ompi_info_get_nthkey - Get a key indexed by integer from an 'MPI_Info' o
|
||||
*
|
||||
* @param info Pointer to ompi_info_t object
|
||||
* @param n index of key to retrieve (integer)
|
||||
* @param key character string of at least 'MPI_MAX_INFO_KEY' characters
|
||||
*
|
||||
* @retval MPI_SUCCESS
|
||||
* @retval MPI_ERR_ARG
|
||||
*/
|
||||
static inline int
|
||||
ompi_info_get_nthkey (ompi_info_t *info, int n, char *key) {
|
||||
ompi_info_entry_t *iterator;
|
||||
/*
|
||||
* Iterate over and over till we get to the nth key
|
||||
*/
|
||||
for (iterator = (ompi_info_entry_t *)ompi_list_get_first(&(info->super));
|
||||
n > 0;
|
||||
n--) {
|
||||
iterator = (ompi_info_entry_t *)ompi_list_get_next(iterator);
|
||||
if ( NULL == iterator) {
|
||||
return MPI_ERR_ARG;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* iterator is of the type ompi_list_item_t. We have to
|
||||
* cast it to ompi_info_entry_t before we can use it to
|
||||
* access the value
|
||||
*/
|
||||
strcpy(key, iterator->ie_key);
|
||||
return MPI_SUCCESS;
|
||||
}
|
||||
|
||||
#endif /* OMPI_INFO_H */
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "mpi/c/bindings.h"
|
||||
#include "communicator/communicator.h"
|
||||
#include "errhandler/errhandler.h"
|
||||
#include "info/info.h"
|
||||
|
||||
#if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
|
||||
#pragma weak MPI_Alloc_mem = PMPI_Alloc_mem
|
||||
@ -29,6 +30,9 @@ int MPI_Alloc_mem(MPI_Aint size, MPI_Info info, void *baseptr)
|
||||
if (size < 0 || NULL == baseptr) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_ARG,
|
||||
FUNC_NAME);
|
||||
} else if (NULL == info || ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,10 @@ int MPI_Comm_accept(char *port_name, MPI_Info info, int root,
|
||||
return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_ARG,
|
||||
FUNC_NAME);
|
||||
}
|
||||
if (NULL == info || ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
rank = ompi_comm_rank ( comm );
|
||||
|
@ -49,6 +49,10 @@ int MPI_Comm_connect(char *port_name, MPI_Info info, int root,
|
||||
return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_ARG,
|
||||
FUNC_NAME);
|
||||
}
|
||||
if (NULL == info || ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
rank = ompi_comm_rank ( comm );
|
||||
|
@ -53,6 +53,10 @@ int MPI_Comm_spawn(char *command, char **argv, int maxprocs, MPI_Info info,
|
||||
return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_ARG,
|
||||
FUNC_NAME);
|
||||
}
|
||||
if (NULL == info || ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
rank = ompi_comm_rank ( comm );
|
||||
|
@ -54,6 +54,17 @@ int MPI_Comm_spawn_multiple(int count, char **array_of_commands, char ***array_o
|
||||
return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_ARG,
|
||||
FUNC_NAME);
|
||||
}
|
||||
if (NULL == array_of_info) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
for (i = 0; i < count; ++i) {
|
||||
if (NULL == array_of_info[i] ||
|
||||
ompi_info_is_freed(array_of_info[i])) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rank = ompi_comm_rank ( comm );
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "mpi/c/bindings.h"
|
||||
#include "communicator/communicator.h"
|
||||
#include "errhandler/errhandler.h"
|
||||
#include "info/info.h"
|
||||
|
||||
#if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
|
||||
#pragma weak MPI_File_delete = PMPI_File_delete
|
||||
@ -24,6 +25,10 @@ int MPI_File_delete(char *filename, MPI_Info info)
|
||||
{
|
||||
if (MPI_PARAM_CHECK) {
|
||||
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
|
||||
if (NULL == info || ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is not yet implemented */
|
||||
|
@ -24,6 +24,10 @@ int MPI_File_get_info(MPI_File fh, MPI_Info *info_used)
|
||||
{
|
||||
if (MPI_PARAM_CHECK) {
|
||||
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
|
||||
if (NULL == info_used) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is not yet implemented */
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "mpi/c/bindings.h"
|
||||
#include "communicator/communicator.h"
|
||||
#include "errhandler/errhandler.h"
|
||||
#include "info/info.h"
|
||||
|
||||
#if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
|
||||
#pragma weak MPI_File_open = PMPI_File_open
|
||||
@ -25,6 +26,10 @@ int MPI_File_open(MPI_Comm comm, char *filename, int amode,
|
||||
{
|
||||
if (MPI_PARAM_CHECK) {
|
||||
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
|
||||
if (NULL == info || ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is not yet implemented */
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "mpi/c/bindings.h"
|
||||
#include "communicator/communicator.h"
|
||||
#include "errhandler/errhandler.h"
|
||||
#include "info/info.h"
|
||||
|
||||
#if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
|
||||
#pragma weak MPI_File_set_info = PMPI_File_set_info
|
||||
@ -24,6 +25,10 @@ int MPI_File_set_info(MPI_File fh, MPI_Info info)
|
||||
{
|
||||
if (MPI_PARAM_CHECK) {
|
||||
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
|
||||
if (NULL == info || ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is not yet implemented */
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "mpi/c/bindings.h"
|
||||
#include "communicator/communicator.h"
|
||||
#include "errhandler/errhandler.h"
|
||||
#include "info/info.h"
|
||||
|
||||
#if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
|
||||
#pragma weak MPI_File_set_view = PMPI_File_set_view
|
||||
@ -25,6 +26,10 @@ int MPI_File_set_view(MPI_File fh, MPI_Offset disp, MPI_Datatype etype,
|
||||
{
|
||||
if (MPI_PARAM_CHECK) {
|
||||
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
|
||||
if (NULL == info || ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is not yet implemented */
|
||||
|
@ -36,7 +36,8 @@ MPI_Fint MPI_Info_c2f(MPI_Info info)
|
||||
/* check the arguments */
|
||||
if (MPI_PARAM_CHECK) {
|
||||
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
|
||||
if (NULL == info || MPI_INFO_NULL == info) {
|
||||
if (NULL == info || MPI_INFO_NULL == info ||
|
||||
ompi_info_is_freed(info)) {
|
||||
return (MPI_Fint) OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD,
|
||||
MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
|
@ -27,19 +27,14 @@ static const char FUNC_NAME[] = "MPI_Info_create";
|
||||
* @param info Pointer to the MPI_Info handle
|
||||
*
|
||||
* @retval MPI_SUCCESS
|
||||
* @retval MPI_ERR_ARG
|
||||
* @retval MPI_ERR_SYSRESOURCE
|
||||
* @retval MPI_ERR_INFO
|
||||
* @retval MPI_ERR_NO_MEM
|
||||
*
|
||||
* When an MPI_Info object is not being used, it should be freed using
|
||||
* MPI_Info_free
|
||||
*/
|
||||
int MPI_Info_create(MPI_Info *info) {
|
||||
/* list of invalid conditions
|
||||
* 1. MPI_ERR_ARG - If info is NULL
|
||||
* 2. MPI_ERR_SYSRESOURCE - If OMPI_MALLOC fails
|
||||
* NOTE:
|
||||
* Yet to add stuff for fortran handles
|
||||
*/
|
||||
int MPI_Info_create(MPI_Info *info)
|
||||
{
|
||||
if (MPI_PARAM_CHECK) {
|
||||
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
|
||||
if (NULL == info) {
|
||||
|
@ -32,8 +32,8 @@ static const char FUNC_NAME[] = "MPI_Info_delete";
|
||||
* needs to be deleted
|
||||
*
|
||||
* @retval MPI_SUCCESS If the (key,val) pair was deleted
|
||||
* @retval MPI_ERR_ARG
|
||||
* @retval MPI_ERR_NOKEY
|
||||
* @retval MPI_ERR_INFO
|
||||
* @retval MPI_ERR_INFO_KEYY
|
||||
*/
|
||||
int MPI_Info_delete(MPI_Info info, char *key) {
|
||||
int key_length;
|
||||
@ -43,7 +43,8 @@ int MPI_Info_delete(MPI_Info info, char *key) {
|
||||
*/
|
||||
if (MPI_PARAM_CHECK) {
|
||||
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
|
||||
if (NULL == info || MPI_INFO_NULL == info) {
|
||||
if (NULL == info || MPI_INFO_NULL == info ||
|
||||
ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
|
@ -29,8 +29,8 @@ static const char FUNC_NAME[] = "MPI_Info_dup";
|
||||
* @param newinfo pointer to the new info object (handle)
|
||||
*
|
||||
* @retval MPI_SUCCESS
|
||||
* @retval MPI_ERR_ARG
|
||||
* @retval MPI_ERR_SYSRESOURCE
|
||||
* @retval MPI_ERR_INFO
|
||||
* @retval MPI_ERR_NO_MEM
|
||||
*
|
||||
* Not only will the (key, value) pairs be duplicated, the order of keys
|
||||
* will be the same in 'newinfo' as it is in 'info'.
|
||||
@ -51,7 +51,8 @@ int MPI_Info_dup(MPI_Info info, MPI_Info *newinfo) {
|
||||
|
||||
if (MPI_PARAM_CHECK) {
|
||||
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
|
||||
if (NULL == info || MPI_INFO_NULL == info || NULL == newinfo) {
|
||||
if (NULL == info || MPI_INFO_NULL == info || NULL == newinfo ||
|
||||
ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ static const char FUNC_NAME[] = "MPI_Info_f2c";
|
||||
* Converts the MPI_Fint info into a valid C MPI_Info handle
|
||||
*
|
||||
* @param info Integer handle to an MPI_INFO object
|
||||
* @retval C handle corresponding to MPI_INFOO object
|
||||
* @retval C handle corresponding to MPI_INFO object
|
||||
*/
|
||||
MPI_Info MPI_Info_f2c(MPI_Fint info)
|
||||
{
|
||||
|
@ -28,7 +28,7 @@ static const char FUNC_NAME[] = "MPI_Info_free";
|
||||
* @param info pointer to info object to be freed (handle)
|
||||
*
|
||||
* @retval MPI_SUCCESS
|
||||
* @retval MPI_ERR_ARG
|
||||
* @retval MPI_ERR_INFO
|
||||
*
|
||||
* Upon successful completion, 'info' will be set to 'MPI_INFO_NULL'.
|
||||
*/
|
||||
@ -42,8 +42,9 @@ int MPI_Info_free(MPI_Info *info)
|
||||
*/
|
||||
if (MPI_PARAM_CHECK) {
|
||||
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
|
||||
if (NULL == info) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_ARG,
|
||||
if (NULL == info || MPI_INFO_NULL == *info ||
|
||||
ompi_info_is_freed(*info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,9 @@ static const char FUNC_NAME[] = "MPI_Info_get";
|
||||
*
|
||||
* @retval MPI_SUCCESS
|
||||
* @retval MPI_ERR_ARG
|
||||
* @retval MPI_ERR_INFO
|
||||
* @retval MPI_ERR_INFO_KEY
|
||||
* @retval MPI_ERR_INFO_VALUE
|
||||
*
|
||||
* In C and C++, 'valuelen' should be one less than the allocated space
|
||||
* to allow for for the null terminator.
|
||||
@ -54,7 +56,8 @@ int MPI_Info_get(MPI_Info info, char *key, int valuelen,
|
||||
*/
|
||||
if (MPI_PARAM_CHECK) {
|
||||
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
|
||||
if (NULL == info || MPI_INFO_NULL == info) {
|
||||
if (NULL == info || MPI_INFO_NULL == info ||
|
||||
ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ static const char FUNC_NAME[] = "MPI_Info_get_nkeys";
|
||||
*
|
||||
* @retval MPI_SUCCESS
|
||||
* @retval MPI_ERR_ARG
|
||||
* @retval MPI_ERR_INFO
|
||||
*
|
||||
* This function returns the number of elements in the list
|
||||
* containing the key-value pairs
|
||||
@ -41,7 +42,8 @@ int MPI_Info_get_nkeys(MPI_Info info, int *nkeys)
|
||||
|
||||
if (MPI_PARAM_CHECK) {
|
||||
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
|
||||
if (NULL == info || MPI_INFO_NULL == info) {
|
||||
if (NULL == info || MPI_INFO_NULL == info ||
|
||||
ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
|
@ -32,6 +32,8 @@ static const char FUNC_NAME[] = "MPI_Info_get_nthkey";
|
||||
*
|
||||
* @retval MPI_SUCCESS
|
||||
* @retval MPI_ERR_ARG
|
||||
* @retval MPI_ERR_INFO
|
||||
* @retval MPI_ERR_INFO_KEY
|
||||
*/
|
||||
int MPI_Info_get_nthkey(MPI_Info info, int n, char *key)
|
||||
{
|
||||
@ -45,7 +47,8 @@ int MPI_Info_get_nthkey(MPI_Info info, int n, char *key)
|
||||
*/
|
||||
if (MPI_PARAM_CHECK) {
|
||||
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
|
||||
if (NULL == info || MPI_INFO_NULL == info) {
|
||||
if (NULL == info || MPI_INFO_NULL == info ||
|
||||
ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE (MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ static const char FUNC_NAME[] = "MPI_Info_get_valuelen";
|
||||
*
|
||||
* @retval MPI_SUCCESS
|
||||
* @retval MPI_ERR_ARG
|
||||
* @retval MPI_ERR_INFO
|
||||
* @retval MPI_ERR_INFO_KEY
|
||||
*
|
||||
* The length returned in C and C++ does not include the end-of-string
|
||||
@ -53,7 +54,8 @@ int MPI_Info_get_valuelen(MPI_Info info, char *key, int *valuelen,
|
||||
*/
|
||||
if (MPI_PARAM_CHECK) {
|
||||
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
|
||||
if (NULL == info || MPI_INFO_NULL == info) {
|
||||
if (NULL == info || MPI_INFO_NULL == info ||
|
||||
ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ static const char FUNC_NAME[] = "MPI_Info_set";
|
||||
* @retval MPI_ERR_INFO_KEY
|
||||
* @retval MPI_ERR_INFO_VAL
|
||||
* @retval MPI_ERR_INFO_NOKEY
|
||||
* @retval MPI_ERR_INTERN
|
||||
* @retval MPI_ERR_NO_MEM
|
||||
*
|
||||
* MPI_Info_set adds the (key,value) pair to info, and overrides
|
||||
* teh value if for the same key a previsou value was set. key and
|
||||
@ -61,7 +61,8 @@ int MPI_Info_set(MPI_Info info, char *key, char *value)
|
||||
|
||||
if (MPI_PARAM_CHECK) {
|
||||
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
|
||||
if (NULL == info || MPI_INFO_NULL == info) {
|
||||
if (NULL == info || MPI_INFO_NULL == info ||
|
||||
ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE (MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
|
@ -36,6 +36,10 @@ int MPI_Lookup_name(char *service_name, MPI_Info info, char *port_name)
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_ARG,
|
||||
FUNC_NAME);
|
||||
}
|
||||
if (NULL == info || ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -36,6 +36,10 @@ int MPI_Open_port(MPI_Info info, char *port_name)
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_ARG,
|
||||
FUNC_NAME);
|
||||
}
|
||||
if (NULL == info || ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
if ( MPI_INFO_NULL != info ) {
|
||||
|
@ -37,6 +37,10 @@ int MPI_Publish_name(char *service_name, MPI_Info info,
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_ARG,
|
||||
FUNC_NAME);
|
||||
}
|
||||
if (NULL == info || ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -38,6 +38,10 @@ int MPI_Unpublish_name(char *service_name, MPI_Info info,
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_ARG,
|
||||
FUNC_NAME);
|
||||
}
|
||||
if (NULL == info || ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "mpi/c/bindings.h"
|
||||
#include "communicator/communicator.h"
|
||||
#include "errhandler/errhandler.h"
|
||||
#include "info/info.h"
|
||||
|
||||
#if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
|
||||
#pragma weak MPI_Win_create = PMPI_Win_create
|
||||
@ -25,6 +26,10 @@ int MPI_Win_create(void *base, MPI_Aint size, int disp_unit,
|
||||
{
|
||||
if (MPI_PARAM_CHECK) {
|
||||
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
|
||||
if (NULL == info || ompi_info_is_freed(info)) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO,
|
||||
FUNC_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is not yet implemented */
|
||||
|
@ -19,7 +19,10 @@
|
||||
|
||||
extern bool ompi_mpi_initialized;
|
||||
extern bool ompi_mpi_finalized;
|
||||
|
||||
extern bool ompi_mpi_param_check;
|
||||
extern bool ompi_debug_show_handle_leaks;
|
||||
extern bool ompi_debug_handle_never_free;
|
||||
|
||||
extern bool ompi_mpi_thread_multiple;
|
||||
extern int ompi_mpi_thread_requested;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "communicator/communicator.h"
|
||||
#include "datatype/datatype.h"
|
||||
#include "op/op.h"
|
||||
#include "info/info.h"
|
||||
#include "runtime/runtime.h"
|
||||
#include "mca/base/base.h"
|
||||
#include "mca/ptl/ptl.h"
|
||||
@ -69,6 +70,9 @@ int ompi_mpi_finalize(void)
|
||||
}
|
||||
|
||||
/* free info resources */
|
||||
if (OMPI_SUCCESS != (ret = ompi_info_finalize())) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Close down MCA modules */
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "runtime/runtime.h"
|
||||
#include "communicator/communicator.h"
|
||||
#include "group/group.h"
|
||||
#include "info/info.h"
|
||||
#include "util/common_cmd_line.h"
|
||||
#include "errhandler/errhandler.h"
|
||||
#include "errhandler/errcode.h"
|
||||
@ -40,10 +41,13 @@
|
||||
|
||||
bool ompi_mpi_initialized = false;
|
||||
bool ompi_mpi_finalized = false;
|
||||
/* As a deviation from the norm, this variable is extern'ed in
|
||||
|
||||
/* As a deviation from the norm, ompi_mpi_param_check is extern'ed in
|
||||
src/mpi/interface/c/bindings.h because it is already included in
|
||||
all MPI function imlementation files */
|
||||
bool ompi_mpi_param_check = true;
|
||||
bool ompi_debug_show_handle_leaks = false;
|
||||
bool ompi_debug_handle_never_free = false;
|
||||
|
||||
bool ompi_mpi_thread_multiple = false;
|
||||
int ompi_mpi_thread_requested = MPI_THREAD_SINGLE;
|
||||
@ -143,6 +147,12 @@ int ompi_mpi_init(int argc, char **argv, int requested, int *provided)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* initialize info */
|
||||
if (OMPI_SUCCESS != (ret = ompi_info_init())) {
|
||||
/* JMS show_help */
|
||||
printf("show_help: ompi_mpi_init failed in ompi_info_init\n");
|
||||
return ret;
|
||||
}
|
||||
/* initialize error handlers */
|
||||
if (OMPI_SUCCESS != (ret = ompi_errhandler_init())) {
|
||||
/* JMS show_help */
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user