diff --git a/include/mpi.h b/include/mpi.h index babe293042..15d6d48781 100644 --- a/include/mpi.h +++ b/include/mpi.h @@ -278,7 +278,7 @@ enum { #define MPI_ERRHANDLER_NULL (&ompi_mpi_errhandler_null) #define MPI_INFO_NULL (&ompi_mpi_info_null) #define MPI_WIN_NULL ((MPI_Win) 0) -#define MPI_FILE_NULL ((MPI_File) 0) +#define MPI_FILE_NULL (&ompi_mpi_file_null) #define MPI_STATUS_IGNORE ((MPI_Status *) 0) #define MPI_STATUSES_IGNORE ((MPI_Status *) 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_file_t ompi_file_null; + extern struct ompi_info_t ompi_mpi_info_null; extern MPI_Fint *MPI_F_STATUS_IGNORE; diff --git a/src/Makefile.am b/src/Makefile.am index 61474e83f5..8bbe28145d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -89,12 +89,14 @@ libmpi_la_LIBADD = \ datatype/libdatatype.la \ errhandler/liberrhandler.la \ event/libevent.la \ + file/libfile.la \ group/libgroup.la \ info/libinfo.la \ mca/base/libmca_base.la \ mca/allocator/base/libmca_allocator_base.la $(MCA_allocator_STATIC_LTLIBS) \ mca/coll/base/libmca_coll_base.la $(MCA_coll_STATIC_LTLIBS) \ $(MCA_common_STATIC_LTLIBS) \ + mca/io/base/libmca_io_base.la $(MCA_coll_STATIC_LTLIBS) \ mca/llm/base/libmca_llm_base.la $(MCA_llm_STATIC_LTLIBS) \ mca/mpool/base/libmca_mpool_base.la $(MCA_mpool_STATIC_LTLIBS) \ mca/ns/base/libmca_ns_base.la $(MCA_ns_STATIC_LTLIBS) \ @@ -114,8 +116,3 @@ libmpi_la_LIBADD = \ threads/libthreads.la \ util/libutil.la libmpi_la_DEPENDENCIES = $(libmpi_la_LIBADD) - -not_implemented_yet =\ - ctnetwork/libctnetwork.la \ - file/libfile.la \ - win/libwin.la diff --git a/src/communicator/comm_init.c b/src/communicator/comm_init.c index bc31c678e4..7a3395c0c9 100644 --- a/src/communicator/comm_init.c +++ b/src/communicator/comm_init.c @@ -17,6 +17,7 @@ #include "mca/topo/topo.h" #include "mca/topo/base/base.h" #include "mca/ns/base/base.h" +#include "mpi/runtime/params.h" /* diff --git a/src/file/Makefile.am b/src/file/Makefile.am index 36fe02dc1a..706adaa446 100644 --- a/src/file/Makefile.am +++ b/src/file/Makefile.am @@ -1,19 +1,20 @@ -# -*- makefile -*- # # $HEADER$ # include $(top_srcdir)/config/Makefile.options -# JMS Remove this when we actually start building a library in here -# and $(headers) gets included in a SOURCES somewhere -EXTRA_DIST = $(headers) +noinst_LTLIBRARIES = libfile.la # Source code files headers = \ file.h +libfile_la_SOURCES = \ + $(headers) \ + file.c + # Conditionally install the header files if WANT_INSTALL_HEADERS diff --git a/src/file/file.c b/src/file/file.c new file mode 100644 index 0000000000..8bbcaf82bf --- /dev/null +++ b/src/file/file.c @@ -0,0 +1,267 @@ +/* + * $HEADER$ + */ + +#include "ompi_config.h" + +#include "file/file.h" +#include "class/ompi_list.h" +#include "mpi/runtime/params.h" + + +/* + * Table for Fortran <-> C file handle conversion + */ +ompi_pointer_array_t ompi_file_f_to_c_table; + +/* + * MPI_FILE_NULL + */ +ompi_file_t ompi_mpi_file_null; + + +/* + * Local functions + */ +static void file_constructor(ompi_file_t *obj); +static void file_destructor(ompi_file_t *obj); + + +/* + * Class instance for ompi_file_t + */ +OBJ_CLASS_INSTANCE(ompi_file_t, + ompi_object_t, + file_constructor, + file_destructor); + + +/* + * Initialize file handling bookeeping + */ +int ompi_file_init(void) +{ + /* Setup file array */ + + OBJ_CONSTRUCT(&ompi_file_f_to_c_table, ompi_pointer_array_t); + + /* Setup MPI_FILE_NULL. Note that it will have the default error + handler of MPI_ERRORS_RETURN, per MPI-2:9.7 (p265). */ + + OBJ_CONSTRUCT(&ompi_mpi_file_null, ompi_file_t); + ompi_mpi_file_null.f_comm = &ompi_mpi_comm_null; + OBJ_RETAIN(ompi_mpi_file_null.f_comm); + ompi_mpi_file_null.f_f_to_c_index = 0; + ompi_pointer_array_set_item(&ompi_file_f_to_c_table, 0, + &ompi_mpi_file_null); + + /* All done */ + + return OMPI_SUCCESS; +} + + +/* + * Create a file handle + */ +int ompi_file_open(ompi_communicator_t *comm, char *filename, + int amode, ompi_info_t *info, ompi_file_t **fh) +{ + ompi_file_t *file; + + file = OBJ_NEW(ompi_file_t); + if (NULL == file) { + return OMPI_ERR_OUT_OF_RESOURCE; + } + + /* Save the params */ + + file->f_comm = comm; + OBJ_RETAIN(comm); + file->f_filename = strdup(filename); + file->f_amode = amode; + + /* Select a module and actually open the file */ + + /* JMS fill in here */ + + /* All done */ + + *fh = file; + return OMPI_SUCCESS; +} + + +/* + * Close a file handle + */ +int ompi_file_close(ompi_file_t **file) +{ + (*file)->f_flags |= OMPI_FILE_ISCLOSED; + OBJ_RELEASE(*file); + *file = MPI_FILE_NULL; + return OMPI_SUCCESS; +} + + +/* + * Shut down the MPI_File bookkeeping + */ +int ompi_file_finalize(void) +{ + size_t i, max; + size_t num_unnamed; + ompi_file_t *file; + + /* Release MPI_FILE_NULL. Do this so that we don't get a bogus leak + report on it. Plus, it's statically allocated, so we don't want + to call OBJ_RELEASE on it. */ + + OBJ_DESTRUCT(&ompi_mpi_file_null); + ompi_pointer_array_set_item(&ompi_file_f_to_c_table, 0, NULL); + + /* Iterate through all the file handles and destroy them. Note + that this also takes care of destroying MPI_FILE_NULL. */ + + max = ompi_pointer_array_get_size(&ompi_file_f_to_c_table); + for (num_unnamed = i = 0; i < max; ++i) { + file = ompi_pointer_array_get_item(&ompi_file_f_to_c_table, i); + + /* If the file was closed 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 != file && ompi_debug_no_free_handles && + 0 == (file->f_flags & OMPI_FILE_ISCLOSED)) { + OBJ_RELEASE(file); + file = ompi_pointer_array_get_item(&ompi_file_f_to_c_table, i); + } + + if (NULL != file) { + + /* If the user wanted warnings about MPI object leaks, + print out a message */ + + if (ompi_debug_show_handle_leaks) { + ++num_unnamed; + } + + OBJ_RELEASE(file); + } + /* 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 (num_unnamed > 0) { + ompi_output(0, "WANRING: %d unnamed MPI_File handles still allocated at MPI_FINALIZE", num_unnamed); + } + OBJ_DESTRUCT(&ompi_file_f_to_c_table); + + /* All done */ + + return OMPI_SUCCESS; +} + + +/* + * Constructor + */ +static void file_constructor(ompi_file_t *file) +{ + /* Initialize the MPI_FILE_OPEN params */ + + file->f_comm = NULL; + file->f_filename = NULL; + file->f_amode = 0; + + /* Initialize flags */ + + file->f_flags = 0; + + /* Initialize the fortran <--> C translation index */ + + file->f_f_to_c_index = ompi_pointer_array_add(&ompi_file_f_to_c_table, + file); + + /* Initialize the error handler. Per MPI-2:9.7 (p265), the + default error handler on file handles is the error handler on + MPI_FILE_NULL, which starts out as MPI_ERRORS_RETURN (but can + be changed by invoking MPI_FILE_SET_ERRHANDLER on + MPI_FILE_NULL). */ + + file->error_handler = ompi_mpi_file_null.error_handler; + OBJ_RETAIN(file->error_handler); + + /* Initialize the module */ + + file->f_io_version = OMPI_IO_VERSION_NONE; + memset(&(file->f_io_selected_module), 0, + sizeof(file->f_io_selected_module)); + file->f_selected_data = NULL; + + /* If the user doesn't want us to ever free it, then add an extra + RETAIN here */ + + if (ompi_debug_no_free_handles) { + OBJ_RETAIN(&(file->super)); + } +} + + +/* + * Destructor + */ +static void file_destructor(ompi_file_t *file) +{ + /* Finalize the module */ + + switch (file->f_io_version) { + case OMPI_IO_VERSION_1_0_0: +#if 0 + /* JMS need to implement */ + file->f_io_selected_module.v1_0_0.iom_finalize(file); +#endif + break; + + case OMPI_IO_VERSION_2_0_0: + /* JMS fill in here */ + break; + + default: + /* All other cases are uninitialized or MPI_FILE_NULL */ + break; + } + + /* Finalize the data members */ + + if (NULL != file->f_comm) { + OBJ_RELEASE(file->f_comm); +#if OMPI_ENABLE_DEBUG + file->f_comm = NULL; +#endif + } + + if (NULL != file->f_filename) { + free(file->f_filename); +#if OMPI_ENABLE_DEBUG + file->f_filename = NULL; +#endif + } + + if (NULL != file->error_handler) { + OBJ_RELEASE(file->error_handler); +#if OMPI_ENABLE_DEBUG + file->error_handler = NULL; +#endif + } + + /* Reset the f_to_c table entry */ + + if (MPI_UNDEFINED != file->f_f_to_c_index && + NULL != ompi_pointer_array_get_item(&ompi_file_f_to_c_table, + file->f_f_to_c_index)) { + ompi_pointer_array_set_item(&ompi_file_f_to_c_table, + file->f_f_to_c_index, NULL); + } +} diff --git a/src/file/file.h b/src/file/file.h index 521cec03f6..83949b72d7 100644 --- a/src/file/file.h +++ b/src/file/file.h @@ -7,34 +7,189 @@ #include "mpi.h" #include "errhandler/errhandler.h" +#include "communicator/communicator.h" +#include "threads/mutex.h" +#include "info/info.h" #include "mca/io/io.h" -typedef enum { - OMPI_IO_1_0_0, - OMPI_IO_2_0_0 -} ompi_io_version_t; +/** + * Version of IO component interface that we're using. + * + * The IO component is being designed to ensure that it can + * simultaneously support multiple component versions in a single + * executable. This is because ROMIO will always be v1.x that + * supports pretty much a 1-to-1 MPI-API-to-module-function mapping, + * but we plan to have a v2.x series that will be "something + * different" (as yet undefined). + */ +enum ompi_io_version_t { + OMPI_IO_VERSION_NONE, + OMPI_IO_VERSION_1_0_0, + OMPI_IO_VERSION_2_0_0, - -struct ompi_file_t { - char f_name[MPI_MAX_OBJECT_NAME]; - ompi_io_version_t ompi_io_version; - - /* Hooks for io modules to hang things */ - - union { - mca_io_base_module_1_0_0_t f_io; - } mca_io_functions; - - /* index in Fortran <-> C translation array */ - - int f_f_to_c_index; - - /* Error handling. This field does not have the "f_" prefix so that - the OMPI_ERRHDL_* macros can find it, regardless of whether it's a - comm, window, or file. */ - - ompi_errhandler_t *error_handler; + OMPI_IO_VERSION_MAX }; +/** + * Convenience typedef + */ +typedef enum ompi_io_version_t ompi_io_version_t; + + +/* + * Flags + */ +#define OMPI_FILE_ISCLOSED 0x00000001 +#define OMPI_FILE_HIDDEN 0x00000002 + + +/** + * Back-end structure for MPI_File + */ +struct ompi_file_t { + ompi_object_t super; + /**< Base of OBJ_* interface */ + + ompi_communicator_t *f_comm; + /**< Communicator that this file was created with */ + + char *f_filename; + /**< Filename that this file was created with */ + + int f_amode; + /**< Amode that this file was created with */ + + int32_t f_flags; + /**< Bit flags */ + + int f_f_to_c_index; + /**< Index in Fortran <-> C translation array */ + + ompi_errhandler_t *error_handler; + /**< Error handler. This field does not have the "f_" prefix so + that the OMPI_ERRHDL_* macros can find it, regardless of + whether it's a comm, window, or file. */ + + ompi_io_version_t f_io_version; + /**< Indicate what version of the IO component we're using (this + indicates what member to look at in the union, below) */ + + union { + mca_io_base_module_1_0_0_t v1_0_0; + /**< IO v1.0.0 module */ + } f_io_selected_module; + /**< The selected module */ + + struct mca_io_base_file_t *f_selected_data; + /**< Allow the selected module to cache data on the file */ +}; +/** + * Convenience typedef + */ typedef struct ompi_file_t ompi_file_t; + +/** + * Back-end instances for MPI_FILE_NULL + */ +extern ompi_file_t ompi_mpi_file_null; + + +/** + * Fortran to C conversion table + */ +extern ompi_pointer_array_t ompi_file_f_to_c_table; + + + +#if defined(c_plusplus) || defined(__cplusplus) +extern "C" { +#endif + /** + * Initialize MPI_File handling. + * + * @retval OMPI_SUCCESS Always. + * + * Invoked during ompi_mpi_init(). + */ + int ompi_file_init(void); + + /** + * Open a file handle. + * + * @param comm Communicator + * @param filename String filename + * @param amode Mode flags + * @param info Info + * @param fh Output file handle + * + * @retval OMPI_SUCCESS Upon success + * @retval OMPI_ERR* Upon error + * + * Create a file handle and select an io module to be paired with + * it. + */ + int ompi_file_open(ompi_communicator_t *comm, char *filename, + int amode, ompi_info_t *info, + ompi_file_t **fh); + + /** + * Atomicly set a name on a file handle. + * + * @param file MPI_File handle to set the name on + * @param name NULL-terminated string to use + * + * @returns OMPI_SUCCESS Always. + * + * At most (MPI_MAX_OBJECT_NAME-1) characters will be copied over to + * the file name's name. This function is performed atomically -- a + * lock is used to ensure that there are not multiple writers to the + * name to ensure that we don't end up with an erroneous name (e.g., + * a name without a \0 at the end). After invoking this function, + * ompi_file_is_name_set() will return true. + */ + int ompi_file_set_name(ompi_file_t *file, char *name); + + /** + * Close a file handle + * + * @param file MPI_File handle to set the name on + * + * @returns OMPI_SUCCESS Always. + * + * Close a file handle and free all resources associated with it. + */ + int ompi_file_close(ompi_file_t **file); + + /** + * Tear down MPI_File handling. + * + * @retval OMPI_SUCCESS Always. + * + * Invoked during ompi_mpi_finalize(). + */ + int ompi_file_finalize(void); + +#if defined(c_plusplus) || defined(__cplusplus) +} +#endif + + +/** + * Check to see if an MPI_File handle is valid. + * + * @param file The MPI file handle + * + * @retval true If the file handle is not valid + * @retval false If the file handle is valid + * + * This is a convenience function, mainly for error checking in + * top-level MPI API functions. + */ +static inline bool ompi_file_invalid(ompi_file_t *file) +{ + return (NULL == file || + &ompi_mpi_file_null == file || + 0 != (file->f_flags & OMPI_FILE_ISCLOSED)); +} + #endif /* OMPI_FILE_H */ diff --git a/src/info/info.c b/src/info/info.c index e688b40f47..d41ed4a84d 100644 --- a/src/info/info.c +++ b/src/info/info.c @@ -4,7 +4,7 @@ #include "info/info.h" #include "include/constants.h" -#include "mpi/runtime/mpiruntime.h" +#include "mpi/runtime/params.h" #include "util/output.h" @@ -17,11 +17,11 @@ 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); +static void info_constructor(ompi_info_t *info); +static void info_destructor(ompi_info_t *info); +static void info_entry_constructor(ompi_info_entry_t *entry); +static void info_entry_destructor(ompi_info_entry_t *entry); +static ompi_info_entry_t *info_find_key (ompi_info_t *info, char *key); /* @@ -29,21 +29,21 @@ static ompi_info_entry_t *ompi_info_find_key (ompi_info_t *info, char *key); */ OBJ_CLASS_INSTANCE(ompi_info_t, ompi_list_t, - ompi_info_construct, - ompi_info_destruct); + info_constructor, + info_destructor); /* * ompi_info_entry_t classes */ OBJ_CLASS_INSTANCE(ompi_info_entry_t, ompi_list_item_t, - ompi_info_entry_construct, - ompi_info_entry_destruct); + info_entry_constructor, + info_entry_destructor); /* * The global fortran <-> C translation table */ -ompi_pointer_array_t *ompi_info_f_to_c_table; +ompi_pointer_array_t ompi_info_f_to_c_table; /* @@ -54,15 +54,12 @@ 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; - } + OBJ_CONSTRUCT(&ompi_info_f_to_c_table, ompi_pointer_array_t); /* Create MPI_INFO_NULL */ OBJ_CONSTRUCT(&ompi_mpi_info_null, ompi_info_t); - ompi_mpi_info_null.i_fhandle = 0; + ompi_mpi_info_null.i_f_to_c_index = 0; /* All done */ @@ -70,79 +67,6 @@ int ompi_info_init(void) } -/* - * Shut down MPI_Info handling - */ -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; - - /* 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_debug_show_handle_leaks) { - ompi_output(0, "WARNING: (no keys)"); - } - } - } - - /* All done -- release the table */ - - OBJ_RELEASE(ompi_info_f_to_c_table); - return OMPI_SUCCESS; -} - - /* * Duplicate an info */ @@ -183,7 +107,7 @@ int ompi_info_set (ompi_info_t *info, char *key, char *value) } OMPI_THREAD_LOCK(info->i_lock); - old_info = ompi_info_find_key (info, key); + old_info = info_find_key (info, key); if (NULL != old_info) { /* * key already exists. remove the value associated with it @@ -227,7 +151,7 @@ int ompi_info_get (ompi_info_t *info, char *key, int valuelen, int value_length; OMPI_THREAD_LOCK(info->i_lock); - search = ompi_info_find_key (info, key); + search = info_find_key (info, key); if (NULL == search){ *flag = 0; } else { @@ -263,7 +187,7 @@ int ompi_info_delete (ompi_info_t *info, char *key) ompi_info_entry_t *found; OMPI_THREAD_LOCK(info->i_lock); - search = ompi_info_find_key (info, key); + search = info_find_key (info, key); if (NULL == search){ OMPI_THREAD_UNLOCK(info->i_lock); return MPI_ERR_INFO_NOKEY; @@ -291,7 +215,7 @@ int ompi_info_get_valuelen (ompi_info_t *info, char *key, int *valuelen, ompi_info_entry_t *search; OMPI_THREAD_LOCK(info->i_lock); - search = ompi_info_find_key (info, key); + search = info_find_key (info, key); if (NULL == search){ *flag = 0; } else { @@ -339,21 +263,98 @@ int ompi_info_get_nthkey (ompi_info_t *info, int n, char *key) } +/* + * Shut down MPI_Info handling + */ +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; + + /* Release MPI_INFO_NULL. Do this so that we don't get a bogus + leak report on it. Plus, it's statically allocated, so we + don't want to call OBJ_RELEASE on it. */ + + OBJ_DESTRUCT(&ompi_mpi_info_null); + ompi_pointer_array_set_item(&ompi_info_f_to_c_table, 0, 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_no_free_handles && 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_debug_show_handle_leaks) { + ompi_output(0, "WARNING: (no keys)"); + } + } + } + + /* All done -- destroy the table */ + + OBJ_DESTRUCT(&ompi_info_f_to_c_table); + return OMPI_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) +static void info_constructor(ompi_info_t *info) { - info->i_fhandle = ompi_pointer_array_add(ompi_info_f_to_c_table, info); + info->i_f_to_c_index = 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)); + if (ompi_debug_no_free_handles) { + OBJ_RETAIN(&(info->super)); } } @@ -363,45 +364,50 @@ static void ompi_info_construct(ompi_info_t *info) * done, we need to remove the entry from the ompi fortran to C * translation table */ -static void ompi_info_destruct(ompi_info_t *info) +static void info_destructor(ompi_info_t *info) { - ompi_list_item_t *item; - ompi_info_entry_t *iterator; + ompi_list_item_t *item; + ompi_info_entry_t *iterator; - /* Remove every key in the list */ + /* 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); - } + 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 */ + /* reset the &ompi_info_f_to_c_table entry - make sure that the + entry is in the table */ + + if (MPI_UNDEFINED != info->i_f_to_c_index && + NULL != ompi_pointer_array_get_item(&ompi_info_f_to_c_table, + info->i_f_to_c_index)){ + ompi_pointer_array_set_item(&ompi_info_f_to_c_table, + info->i_f_to_c_index, NULL); + } - 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); - } + /* Release the lock */ + + OBJ_RELEASE(info->i_lock); } /* * ompi_info_entry_t interface functions */ -static void ompi_info_entry_construct(ompi_info_entry_t *entry) +static void info_entry_constructor(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) +static void info_entry_destructor(ompi_info_entry_t *entry) { if (NULL != entry->ie_value) { - free(entry->ie_value); + free(entry->ie_value); } } @@ -412,7 +418,7 @@ static void ompi_info_entry_destruct(ompi_info_entry_t *entry) * 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) +static ompi_info_entry_t *info_find_key (ompi_info_t *info, char *key) { ompi_info_entry_t *iterator; @@ -431,6 +437,3 @@ static ompi_info_entry_t *ompi_info_find_key (ompi_info_t *info, char *key) } return NULL; } - - - diff --git a/src/info/info.h b/src/info/info.h index dd7a1db832..25015b27b8 100644 --- a/src/info/info.h +++ b/src/info/info.h @@ -23,7 +23,7 @@ struct ompi_info_t { ompi_list_t super; /**< generic list pointer which is the container for (key,value) pairs */ - int i_fhandle; + int i_f_to_c_index; /**< fortran handle for info. This is needed for translation from fortran to C and vice versa */ ompi_mutex_t *i_lock; @@ -59,7 +59,7 @@ typedef struct ompi_info_entry_t ompi_info_entry_t; /** * Table for Fortran <-> C translation table */ -extern ompi_pointer_array_t *ompi_info_f_to_c_table; +extern ompi_pointer_array_t ompi_info_f_to_c_table; /** * Global instance for MPI_INFO_NULL diff --git a/src/mca/io/base/Makefile.am b/src/mca/io/base/Makefile.am index 34c0ea958b..0721c4e5bf 100644 --- a/src/mca/io/base/Makefile.am +++ b/src/mca/io/base/Makefile.am @@ -4,7 +4,21 @@ include $(top_srcdir)/config/Makefile.options -# For VPATH builds, have to specify where static-modules.h will be found +noinst_LTLIBRARIES = libmca_io_base.la -AM_CPPFLAGS = -I$(top_builddir)/src +headers = \ + base.h +libmca_io_base_la_SOURCES = \ + $(headers) \ + io_base_close.c \ + io_base_open.c + +# Conditionally install the header files + +if WANT_INSTALL_HEADERS +ompidir = $(includedir)/openmpi/mca/io/base +ompi_HEADERS = $(headers) +else +ompidir = $(includedir) +endif diff --git a/src/mca/io/base/base.h b/src/mca/io/base/base.h new file mode 100644 index 0000000000..66452c3842 --- /dev/null +++ b/src/mca/io/base/base.h @@ -0,0 +1,25 @@ +/* + * $HEADER$ + */ + +#ifndef OMPI_MCA_IO_BASE_H +#define OMPI_MCA_IO_BASE_H + +#if defined(c_plusplus) || defined(__cplusplus) +extern "C" { +#endif + /** + * To be filled in soon + */ + int mca_io_base_open(void); + + /** + * To be filled in soon + */ + int mca_io_base_close(void); + +#if defined(c_plusplus) || defined(__cplusplus) +} +#endif + +#endif /* OMPI_MCA_IO_BASE_H */ diff --git a/src/mca/io/base/io_base_close.c b/src/mca/io/base/io_base_close.c new file mode 100644 index 0000000000..ed5ab76a73 --- /dev/null +++ b/src/mca/io/base/io_base_close.c @@ -0,0 +1,15 @@ +/* + * $HEADER$ + */ + +#include "ompi_config.h" + +#include "include/constants.h" +#include "mca/io/base/base.h" + + +int mca_io_base_close(void) +{ + /* JMS More coming here soon */ + return OMPI_SUCCESS; +} diff --git a/src/mca/io/base/io_base_open.c b/src/mca/io/base/io_base_open.c new file mode 100644 index 0000000000..627c9501fb --- /dev/null +++ b/src/mca/io/base/io_base_open.c @@ -0,0 +1,15 @@ +/* + * $HEADER$ + */ + +#include "ompi_config.h" + +#include "include/constants.h" +#include "mca/io/base/base.h" + + +int mca_io_base_open(void) +{ + /* JMS More coming here soon */ + return OMPI_SUCCESS; +} diff --git a/src/mpi/c/file_c2f.c b/src/mpi/c/file_c2f.c index 107d1f64a7..a981332920 100644 --- a/src/mpi/c/file_c2f.c +++ b/src/mpi/c/file_c2f.c @@ -8,6 +8,7 @@ #include "mpi/c/bindings.h" #include "communicator/communicator.h" #include "errhandler/errhandler.h" +#include "file/file.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_File_c2f = PMPI_File_c2f @@ -22,11 +23,14 @@ static const char FUNC_NAME[] = "MPI_File_c2f"; MPI_Fint MPI_File_c2f(MPI_File file) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - } - - /* This function is not yet implemented */ - - return (MPI_Fint) OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INTERN, FUNC_NAME); + if (MPI_PARAM_CHECK) { + OMPI_ERR_INIT_FINALIZE(FUNC_NAME); + if (ompi_file_invalid(file)) { + return (MPI_Fint) OMPI_ERRHANDLER_INVOKE(MPI_FILE_NULL, + MPI_ERR_FILE, + FUNC_NAME); + } + } + + return (MPI_Fint) file->f_f_to_c_index; } diff --git a/src/mpi/c/file_close.c b/src/mpi/c/file_close.c index 8436f928e9..b5e1af181b 100644 --- a/src/mpi/c/file_close.c +++ b/src/mpi/c/file_close.c @@ -8,6 +8,7 @@ #include "mpi/c/bindings.h" #include "communicator/communicator.h" #include "errhandler/errhandler.h" +#include "file/file.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_File_close = PMPI_File_close @@ -22,11 +23,21 @@ static const char FUNC_NAME[] = "MPI_File_close"; int MPI_File_close(MPI_File *fh) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - } + int rc; - /* This function is not yet implemented */ + if (MPI_PARAM_CHECK) { + OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INTERN, FUNC_NAME); + /* Note that MPI-2:9.7 (p265) says that errors in + MPI_FILE_CLOSE should invoke the default error handler on + MPI_FILE_NULL */ + + if (NULL == fh || ompi_file_invalid(*fh)) { + return OMPI_ERRHANDLER_INVOKE(MPI_FILE_NULL, MPI_ERR_FILE, + FUNC_NAME); + } + } + + rc = ompi_file_close(fh); + OMPI_ERRHANDLER_RETURN(rc, *fh, rc, FUNC_NAME); } diff --git a/src/mpi/c/file_delete.c b/src/mpi/c/file_delete.c index f03906268e..e3ae2b3621 100644 --- a/src/mpi/c/file_delete.c +++ b/src/mpi/c/file_delete.c @@ -9,6 +9,7 @@ #include "communicator/communicator.h" #include "errhandler/errhandler.h" #include "info/info.h" +#include "file/file.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_File_delete = PMPI_File_delete @@ -23,15 +24,18 @@ static const char FUNC_NAME[] = "MPI_File_delete"; 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); + 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 */ + /* Note that MPI-2:9.7 (p265) says that errors in MPI_FILE_DELETE + should invoke the default error handler on MPI_FILE_NULL */ - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INTERN, FUNC_NAME); + /* This function is not yet implemented */ + + return OMPI_ERRHANDLER_INVOKE(MPI_FILE_NULL, MPI_ERR_INTERN, FUNC_NAME); } diff --git a/src/mpi/c/file_f2c.c b/src/mpi/c/file_f2c.c index 618e8401cb..62c47e6dfd 100644 --- a/src/mpi/c/file_f2c.c +++ b/src/mpi/c/file_f2c.c @@ -8,6 +8,7 @@ #include "mpi/c/bindings.h" #include "communicator/communicator.h" #include "errhandler/errhandler.h" +#include "file/file.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_File_f2c = PMPI_File_f2c @@ -20,13 +21,19 @@ static const char FUNC_NAME[] = "MPI_File_f2c"; -MPI_File MPI_File_f2c(MPI_Fint file) +MPI_File MPI_File_f2c(MPI_Fint file_f) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - } + size_t file_index = (size_t) file_f; - /* This function is not yet implemented */ + if (MPI_PARAM_CHECK) { + OMPI_ERR_INIT_FINALIZE(FUNC_NAME); + if (file_index < 0 || + file_index >= ompi_pointer_array_get_size(&ompi_file_f_to_c_table)) { + (void) OMPI_ERRHANDLER_INVOKE(MPI_FILE_NULL, MPI_ERR_FILE, + FUNC_NAME); + return MPI_FILE_NULL; + } + } - return (MPI_File) OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INTERN, FUNC_NAME); + return ompi_file_f_to_c_table.addr[file_index]; } diff --git a/src/mpi/c/file_open.c b/src/mpi/c/file_open.c index 5db7b7cd56..4f20f4f63e 100644 --- a/src/mpi/c/file_open.c +++ b/src/mpi/c/file_open.c @@ -9,6 +9,7 @@ #include "communicator/communicator.h" #include "errhandler/errhandler.h" #include "info/info.h" +#include "file/file.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_File_open = PMPI_File_open @@ -24,15 +25,26 @@ static const char FUNC_NAME[] = "MPI_File_open"; int MPI_File_open(MPI_Comm comm, char *filename, int amode, MPI_Info info, MPI_File *fh) { - 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); + int rc; + + 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); + } else if (ompi_comm_invalid(comm)) { + return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_COMM, + FUNC_NAME); + } } - } - /* This function is not yet implemented */ + /* Note that MPI-2:9.7 (p265) says that errors in MPI_FILE_OPEN + (before the file handle is created) should invoke the default + error handler on MPI_FILE_NULL. Hence, if we get a file handle + out of ompi_file_open(), invoke the error handler on that. If + not, invoke the error handler on MPI_FILE_NULL. */ - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INTERN, FUNC_NAME); + *fh = MPI_FILE_NULL; + rc = ompi_file_open(comm, filename, amode, info, fh); + OMPI_ERRHANDLER_RETURN(rc, *fh, rc, FUNC_NAME); } diff --git a/src/mpi/c/file_read.c b/src/mpi/c/file_read.c index f3a39e269e..49c27cd733 100644 --- a/src/mpi/c/file_read.c +++ b/src/mpi/c/file_read.c @@ -8,6 +8,7 @@ #include "mpi/c/bindings.h" #include "communicator/communicator.h" #include "errhandler/errhandler.h" +#include "file/file.h" #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES #pragma weak MPI_File_read = PMPI_File_read @@ -23,11 +24,15 @@ static const char FUNC_NAME[] = "MPI_File_read"; int MPI_File_read(MPI_File fh, void *buf, int count, MPI_Datatype datatype, MPI_Status *status) { - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - } + if (MPI_PARAM_CHECK) { + OMPI_ERR_INIT_FINALIZE(FUNC_NAME); + if (ompi_file_invalid(fh)) { + return OMPI_ERRHANDLER_INVOKE(MPI_FILE_NULL, MPI_ERR_FILE, + FUNC_NAME); + } + } - /* This function is not yet implemented */ - - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INTERN, FUNC_NAME); + /* This function is not yet implemented */ + + return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INTERN, FUNC_NAME); } diff --git a/src/mpi/c/file_set_errhandler.c b/src/mpi/c/file_set_errhandler.c index 257619babc..fe9e5da66a 100644 --- a/src/mpi/c/file_set_errhandler.c +++ b/src/mpi/c/file_set_errhandler.c @@ -23,31 +23,34 @@ static const char FUNC_NAME[] = "MPI_File_set_errhandler"; int MPI_File_set_errhandler( MPI_File file, MPI_Errhandler errhandler) { - /* Error checking */ + /* Error checking */ - if (MPI_PARAM_CHECK) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - if (NULL == file || - MPI_FILE_NULL == file) { - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_FILE, - FUNC_NAME); - } else if (NULL == errhandler || - MPI_ERRHANDLER_NULL == errhandler || - OMPI_ERRHANDLER_TYPE_FILE != errhandler->eh_mpi_object_type) { - return OMPI_ERRHANDLER_INVOKE(file, MPI_ERR_ARG, FUNC_NAME); + if (MPI_PARAM_CHECK) { + OMPI_ERR_INIT_FINALIZE(FUNC_NAME); + + /* Note that MPI-2:9.7 (p265) explicitly says that you are + allowed to set the error handler on MPI_FILE_NULL */ + + if (NULL == file) { + return OMPI_ERRHANDLER_INVOKE(MPI_FILE_NULL, MPI_ERR_FILE, + FUNC_NAME); + } else if (NULL == errhandler || + MPI_ERRHANDLER_NULL == errhandler || + OMPI_ERRHANDLER_TYPE_FILE != errhandler->eh_mpi_object_type) { + return OMPI_ERRHANDLER_INVOKE(file, MPI_ERR_ARG, FUNC_NAME); + } } - } - /* Ditch the old errhandler, and decrement its refcount */ + /* Ditch the old errhandler, and decrement its refcount */ - OBJ_RELEASE(file->error_handler); + OBJ_RELEASE(file->error_handler); - /* We have a valid comm and errhandler, so increment its refcount */ + /* We have a valid comm and errhandler, so increment its refcount */ - file->error_handler = errhandler; - OBJ_RETAIN(file->error_handler); + file->error_handler = errhandler; + OBJ_RETAIN(file->error_handler); - /* All done */ + /* All done */ - return MPI_SUCCESS; + return MPI_SUCCESS; } diff --git a/src/mpi/c/info_c2f.c b/src/mpi/c/info_c2f.c index ffc4c0f4f4..80de8763c1 100644 --- a/src/mpi/c/info_c2f.c +++ b/src/mpi/c/info_c2f.c @@ -45,5 +45,5 @@ MPI_Fint MPI_Info_c2f(MPI_Info info) } /* return the index */ - return (MPI_Fint)(info->i_fhandle); + return (MPI_Fint)(info->i_f_to_c_index); } diff --git a/src/mpi/c/info_f2c.c b/src/mpi/c/info_f2c.c index 6c0a30118d..3838a88a08 100644 --- a/src/mpi/c/info_f2c.c +++ b/src/mpi/c/info_f2c.c @@ -30,15 +30,20 @@ static const char FUNC_NAME[] = "MPI_Info_f2c"; */ MPI_Info MPI_Info_f2c(MPI_Fint info) { + size_t info_index = (size_t) info; + /* check the arguments */ + if (MPI_PARAM_CHECK) { OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - if (0 > info || - info >= ompi_pointer_array_get_size(ompi_info_f_to_c_table)) { + if (info_index < 0 || + info_index >= ompi_pointer_array_get_size(&ompi_info_f_to_c_table)) { + (void) OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_INFO, + FUNC_NAME); return MPI_INFO_NULL; } } /* return the index */ - return ompi_info_f_to_c_table->addr[info]; + return ompi_info_f_to_c_table.addr[info_index]; } diff --git a/src/mpi/runtime/Makefile.am b/src/mpi/runtime/Makefile.am index b344dcb8f3..c616ee762a 100644 --- a/src/mpi/runtime/Makefile.am +++ b/src/mpi/runtime/Makefile.am @@ -12,12 +12,14 @@ noinst_LTLIBRARIES = libmpiruntime.la # Source code files headers = \ - mpiruntime.h + mpiruntime.h \ + params.h libmpiruntime_la_SOURCES = \ $(headers) \ ompi_mpi_init.c \ - ompi_mpi_finalize.c + ompi_mpi_finalize.c \ + ompi_mpi_params.c # Conditionally install the header files diff --git a/src/mpi/runtime/mpiruntime.h b/src/mpi/runtime/mpiruntime.h index 82d670d734..fdf188ed47 100644 --- a/src/mpi/runtime/mpiruntime.h +++ b/src/mpi/runtime/mpiruntime.h @@ -8,8 +8,8 @@ * Interface into the MPI portion of the Open MPI Run Time Environment */ -#ifndef OMPI_MPIRUNTIME_H -#define OMPI_MPIRUNTIME_H +#ifndef OMPI_MPI_MPIRUNTIME_H +#define OMPI_MPI_MPIRUNTIME_H #include "ompi_config.h" @@ -20,10 +20,6 @@ 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; extern int ompi_mpi_thread_provided; @@ -36,16 +32,29 @@ extern "C" { /** * Initialize the Open MPI MPI environment * + * @param argc argc, typically from main() (IN) + * @param argv argv, typically from main() (IN) + * @param requested Thread support that is requested (IN) + * @param provided Thread support that is provided (OUT) + * + * @returns MPI_SUCCESS if successful + * @returns Error code if unsuccessful + * * Intialize all support code needed for MPI applications. This * function should only be called by MPI applications (including - * singletons). If this function is called, ompi_init and - * ompi_rte_init should *not* be called. + * singletons). If this function is called, ompi_init() and + * ompi_rte_init() should *not* be called. + * + * It is permissable to pass in (0, NULL) for (argc, argv). */ int ompi_mpi_init(int argc, char **argv, int requested, int *provided); /** * Finalize the Open MPI MPI environment * + * @returns MPI_SUCCESS if successful + * @returns Error code if unsuccessful + * * Should be called after all MPI functionality is complete (usually * during MPI_FINALIZE). */ @@ -55,4 +64,4 @@ extern "C" { } #endif -#endif /* OMPI_MPIRUNTIME_H */ +#endif /* OMPI_MPI_MPIRUNTIME_H */ diff --git a/src/mpi/runtime/ompi_mpi_finalize.c b/src/mpi/runtime/ompi_mpi_finalize.c index 0a4419033f..627dfa3d18 100644 --- a/src/mpi/runtime/ompi_mpi_finalize.c +++ b/src/mpi/runtime/ompi_mpi_finalize.c @@ -12,8 +12,10 @@ #include "communicator/communicator.h" #include "datatype/datatype.h" #include "op/op.h" +#include "file/file.h" #include "info/info.h" #include "runtime/runtime.h" + #include "mca/base/base.h" #include "mca/ptl/ptl.h" #include "mca/ptl/base/base.h" @@ -21,6 +23,10 @@ #include "mca/pml/base/base.h" #include "mca/coll/coll.h" #include "mca/coll/base/base.h" +#include "mca/topo/topo.h" +#include "mca/topo/base/base.h" +#include "mca/io/io.h" +#include "mca/io/base/base.h" int ompi_mpi_finalize(void) @@ -34,15 +40,18 @@ int ompi_mpi_finalize(void) /* Free communication objects */ + /* free window resources */ + + /* free file resources */ + if (OMPI_SUCCESS != (ret = ompi_file_finalize())) { + return ret; + } + /* free communicator resources */ if (OMPI_SUCCESS != (ret = ompi_comm_finalize())) { return ret; } - /* free window resources */ - - /* free file resources */ - /* Free secondary resources */ /* free group resources */ @@ -76,6 +85,12 @@ int ompi_mpi_finalize(void) /* Close down MCA modules */ + if (OMPI_SUCCESS != (ret = mca_io_base_close())) { + return ret; + } + if (OMPI_SUCCESS != (ret = mca_topo_base_close())) { + return ret; + } if (OMPI_SUCCESS != (ret = mca_coll_base_close())) { return ret; } diff --git a/src/mpi/runtime/ompi_mpi_init.c b/src/mpi/runtime/ompi_mpi_init.c index cc87bc6cb6..8dbb97626d 100644 --- a/src/mpi/runtime/ompi_mpi_init.c +++ b/src/mpi/runtime/ompi_mpi_init.c @@ -5,11 +5,12 @@ #include "ompi_config.h" #include "include/constants.h" +#include "mpi/runtime/mpiruntime.h" +#include "mpi/runtime/params.h" #include "runtime/runtime.h" #include "util/sys_info.h" #include "util/proc_info.h" #include "mpi.h" -#include "runtime/runtime.h" #include "communicator/communicator.h" #include "group/group.h" #include "info/info.h" @@ -19,6 +20,8 @@ #include "errhandler/errclass.h" #include "errhandler/errcode-internal.h" #include "op/op.h" +#include "file/file.h" + #include "mca/base/base.h" #include "mca/base/base.h" #include "mca/allocator/base/base.h" @@ -33,6 +36,8 @@ #include "mca/coll/base/base.h" #include "mca/topo/topo.h" #include "mca/topo/base/base.h" +#include "mca/io/io.h" +#include "mca/io/base/base.h" /* @@ -42,13 +47,6 @@ bool ompi_mpi_initialized = false; bool ompi_mpi_finalized = false; -/* 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; int ompi_mpi_thread_provided = MPI_THREAD_SINGLE; @@ -56,7 +54,7 @@ int ompi_mpi_thread_provided = MPI_THREAD_SINGLE; int ompi_mpi_init(int argc, char **argv, int requested, int *provided) { - int ret, param, value; + int ret, param; bool allow_multi_user_threads; bool have_hidden_threads; ompi_proc_t** procs; @@ -94,6 +92,15 @@ int ompi_mpi_init(int argc, char **argv, int requested, int *provided) return ret; } + /* Once we've joined the RTE, see if any MCA parameters were + passed to the MPI level */ + + if (OMPI_SUCCESS != (ret = ompi_mpi_register_params())) { + /* JMS show_help */ + printf("show_help: ompi_mpi_init failed in mca_mpi_register_params\n"); + return ret; + } + /* initialize ompi procs */ if (OMPI_SUCCESS != (ret = ompi_proc_init())) { /* JMS show_help */ @@ -101,36 +108,41 @@ int ompi_mpi_init(int argc, char **argv, int requested, int *provided) return ret; } - /* Open up relevant MCA modules. Do not open io, topo, or one - module types here -- they are loaded upon demand (i.e., upon - relevant constructors). */ + /* Open up relevant MCA modules. */ + if (OMPI_SUCCESS != (ret = mca_allocator_base_open())) { /* JMS show_help */ - printf("show_help: ompi_mpi_init failed in mca_allocator_base_init\n"); + printf("show_help: ompi_mpi_init failed in mca_allocator_base_open\n"); return ret; } if (OMPI_SUCCESS != (ret = mca_mpool_base_open())) { /* JMS show_help */ - printf("show_help: ompi_mpi_init failed in mca_mpool_base_init\n"); + printf("show_help: ompi_mpi_init failed in mca_mpool_base_open\n"); return ret; } if (OMPI_SUCCESS != (ret = mca_pml_base_open())) { /* JMS show_help */ - printf("show_help: ompi_mpi_init failed in mca_pml_base_init\n"); + printf("show_help: ompi_mpi_init failed in mca_pml_base_open\n"); return ret; } if (OMPI_SUCCESS != (ret = mca_ptl_base_open())) { /* JMS show_help */ - printf("show_help: ompi_mpi_init failed in mca_ptl_base_init\n"); + printf("show_help: ompi_mpi_init failed in mca_ptl_base_open\n"); return ret; } if (OMPI_SUCCESS != (ret = mca_coll_base_open())) { /* JMS show_help */ - printf("show_help: ompi_mpi_init failed in mca_coll_base_init\n"); + printf("show_help: ompi_mpi_init failed in mca_coll_base_open\n"); return ret; } if (OMPI_SUCCESS != (ret = mca_topo_base_open())) { /* JMS show_help */ + printf("show_help: ompi_mpi_init failed in mca_topo_base_open\n"); + return ret; + } + if (OMPI_SUCCESS != (ret = mca_io_base_open())) { + /* JMS show_help */ + printf("show_help: ompi_mpi_init failed in mca_io_base_open\n"); return ret; } @@ -216,12 +228,12 @@ int ompi_mpi_init(int argc, char **argv, int requested, int *provided) return ret; } - /* If we have run-time MPI parameter checking possible, register - an MCA paramter to find out if the user wants it on or off by - default */ - param = mca_base_param_register_int("mpi", NULL, "error_check", NULL, 1); - mca_base_param_lookup_int(param, &value); - ompi_mpi_param_check = (bool) value; + /* initialize file handles */ + if (OMPI_SUCCESS != (ret = ompi_file_init())) { + /* JMS show_help */ + printf("show_help: ompi_mpi_init failed in ompi_file_init\n"); + return ret; + } /* do module exchange */ if (OMPI_SUCCESS != (ret = mca_base_modex_exchange())) { diff --git a/src/mpi/runtime/ompi_mpi_params.c b/src/mpi/runtime/ompi_mpi_params.c new file mode 100644 index 0000000000..dc58827b9c --- /dev/null +++ b/src/mpi/runtime/ompi_mpi_params.c @@ -0,0 +1,63 @@ +/* + * $HEADER$ + */ + +#include "ompi_config.h" + +#include "include/constants.h" +#include "mpi/runtime/mpiruntime.h" +#include "mpi/runtime/params.h" +#include "mca/base/mca_base_param.h" + + +/* + * Global variables + * + * As a deviation from the norm, ompi_mpi_param_check is also + * extern'ed in src/mpi/interface/c/bindings.h because it is already + * included in all MPI function imlementation files + * + * The values below are the default values. + */ +bool ompi_mpi_param_check = true; +bool ompi_debug_show_handle_leaks = false; +bool ompi_debug_no_free_handles = false; + + +int ompi_mpi_register_params(void) +{ + int param_check_param; + int show_leaks_param; + int no_free_param; + int value; + + param_check_param = + mca_base_param_register_int("base", "mpi", "param_check", + "mpi_param_check", + (int) ompi_mpi_param_check); + mca_base_param_lookup_int(param_check_param, &value); + ompi_mpi_param_check = (bool) value; + + /* Whether or not to show MPI handle leaks */ + + show_leaks_param = + mca_base_param_register_int("base", "mpi", "show_handle_leaks", + "mpi_show_handle_leaks", + (int) ompi_debug_show_handle_leaks); + mca_base_param_lookup_int(show_leaks_param, &value); + ompi_debug_show_handle_leaks = (bool) value; + + /* Whether or not to free MPI handles */ + + no_free_param = + mca_base_param_register_int("base", "mpi", "no_free_handles", + "mpi_no_free_handles", + (int) ompi_debug_no_free_handles); + mca_base_param_lookup_int(no_free_param, &value); + ompi_debug_no_free_handles = (bool) value; + + /* All done */ + + return OMPI_SUCCESS; +} + diff --git a/src/mpi/runtime/params.h b/src/mpi/runtime/params.h new file mode 100644 index 0000000000..dfef8b7278 --- /dev/null +++ b/src/mpi/runtime/params.h @@ -0,0 +1,68 @@ +/* + * $HEADER$ + */ + +#ifndef OMPI_RUNTIME_PARAMS_H +#define OMPI_RUNTIME_PARAMS_H + +/* + * Global variables + */ + +/** + * Whether or not to check the parameters of top-level MPI API + * functions or not. + * + * This variable should never be checked directly; the macro + * MPI_PARAM_CHECK should be used instead. This allows multiple + * levels of MPI function parameter checking: + * + * #- Disable all parameter checking at configure/compile time + * #- Enable all parameter checking at configure/compile time + * #- Disable all parameter checking at run time + * #- Enable all parameter checking at run time + * + * Hence, the MPI_PARAM_CHECK macro will either be "0", "1", or + * "ompi_mpi_param_check". + */ +extern bool ompi_mpi_param_check; + +/** + * Whether or not to check for MPI handle leaks during MPI_FINALIZE. + * If enabled, each MPI handle type will display a summary of the + * handles that are still allocated during MPI_FINALIZE. + * + * This is good debugging for user applications to find out if they + * are inadvertantly orphaning MPI handles. + */ +extern bool ompi_debug_show_handle_leaks; + +/** + * Whether or not to actually free MPI handles when their + * corresponding destructor is invoked. If enabled, Open MPI will not + * free handles, but will rather simply mark them as "freed". Any + * attempt to use them will result in an MPI exception. + * + * This is good debugging for user applications to find out if they + * are inadvertantly using MPI handles after they have been freed. + */ +extern bool ompi_debug_no_free_handles; + + +#ifdef __cplusplus +extern "C" { +#endif + /** + * Register MCA parameters used by the MPI layer. + * + * @returns OMPI_SUCCESS + * + * Registers several MCA parameters and initializes corresponding + * global variables to the values obtained from the MCA system. + */ + int ompi_mpi_register_params(void); +#ifdef __cplusplus +} +#endif + +#endif /* OMPI_RUNTIME_PARAMS_H */ diff --git a/src/tools/ompi_info/components.cc b/src/tools/ompi_info/components.cc index 8948172e04..42ead4d74a 100644 --- a/src/tools/ompi_info/components.cc +++ b/src/tools/ompi_info/components.cc @@ -10,6 +10,7 @@ #include #include +#include "mpi/runtime/params.h" #include "mca/base/base.h" #include "mca/allocator/allocator.h" #include "mca/allocator/base/base.h" @@ -80,6 +81,10 @@ void ompi_info::open_components() } } + // Register the MPI layer's MCA parameters + + ompi_mpi_register_params(); + // Find / open all components mca_base_open();