1
1

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.
Этот коммит содержится в:
Jeff Squyres 2004-08-12 16:56:24 +00:00
родитель 2b64fdd0dd
Коммит 726af9ea85
32 изменённых файлов: 590 добавлений и 286 удалений

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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 */