1
1

First cut at error handlers. Still have more to go.

This commit was SVN r934.
Этот коммит содержится в:
Jeff Squyres 2004-03-19 06:12:43 +00:00
родитель 5e67eb96c8
Коммит 19629774f0
15 изменённых файлов: 494 добавлений и 52 удалений

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

@ -259,7 +259,7 @@ enum {
#define MPI_DATATYPE_NULL ((MPI_Datatype) 0)
#define MPI_REQUEST_NULL ((MPI_Request) 0)
#define MPI_OP_NULL ((MPI_Op) 0)
#define MPI_ERRHANDLER_NULL ((MPI_Errhandler) 0)
#define MPI_ERRHANDLER_NULL ((MPI_Errhandler) &(lam_mpi_errhandler_null))
#define MPI_INFO_NULL ((MPI_Info) 0)
#define MPI_WIN_NULL ((MPI_Win) 0)
@ -316,8 +316,9 @@ extern struct lam_datatype_t lam_mpi_cxx_cplex, lam_mpi_cxx_dblcplex;
extern struct lam_datatype_t lam_mpi_cxx_ldblcplex;
extern struct lam_datatype_t lam_mpi_cxx_bool;
extern struct lam_errorhandler_t lam_mpi_errors_are_fatal;
extern struct lam_errorhandler_t lam_mpi_errors_return;
extern struct lam_errhandler_t lam_mpi_errors_null;
extern struct lam_errhandler_t lam_mpi_errors_are_fatal;
extern struct lam_errhandler_t lam_mpi_errors_return;
extern MPI_Fint *MPI_F_STATUS_IGNORE;
extern MPI_Fint *MPI_F_STATUSES_IGNORE;

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

@ -45,9 +45,11 @@ struct lam_communicator_t {
int c_f_to_c_index;
/* Error handling */
/* Error handling. This field does not have the "c_" prefix so
that the LAM_ERRHDL_* macros can find it, regardless of whether
it's a comm, window, or file. */
lam_errhandler_t *c_error_handler;
lam_errhandler_t *error_handler;
/* Hooks for PML to hang things */
struct mca_pml_comm_t* c_pml_comm;

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

@ -27,7 +27,7 @@ static void lam_comm_construct(lam_communicator_t* comm)
comm->c_my_rank = 0;
comm->c_local_group = NULL;
comm->c_remote_group = NULL;
comm->c_error_handler = NULL;
comm->error_handler = NULL;
comm->c_pml_comm = NULL;
comm->c_coll_comm = NULL;
}

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

@ -10,11 +10,14 @@ noinst_LTLIBRARIES = liberrhandler.la
# Source code files
headers = \
errhandler.h
errhandler.h \
errhandler_predefined.h
liberrhandler_la_SOURCES = \
$(headers) \
errhandler_invoke.c
errhandler.c \
errhandler_invoke.c \
errhandler_predefined.c
# Conditionally install the header files

184
src/errhandler/errhandler.c Обычный файл
Просмотреть файл

@ -0,0 +1,184 @@
/*
* $HEADER$
*/
#include "lam_config.h"
#include "communicator/communicator.h"
#include "win/win.h"
#include "file/file.h"
#include "errhandler/errhandler.h"
#include "errhandler/errhandler_predefined.h"
/* define class information */
static void lam_errhandler_construct(lam_errhandler_t *eh);
static void lam_errhandler_destruct(lam_errhandler_t *eh);
lam_class_t lam_errhandler_t_class = {
"lam_errhandler_t",
OBJ_CLASS(lam_object_t),
(lam_construct_t) lam_errhandler_construct,
(lam_destruct_t) lam_errhandler_destruct
};
/*
* Table for Fortran <-> C errhandler handle conversion
*/
lam_pointer_array_t *lam_errhandler_f_to_c_table;
/*
* MPI_ERRHANDLER_NULL
*/
lam_errhandler_t lam_mpi_errhandler_null = {
{ NULL, 0 },
"MPI_ERRHANDLER_NULL",
false,
LAM_ERRHANDLER_COMM,
{ NULL }
};
/*
* MPI_ERRORS_ARE_FATAL
*/
lam_errhandler_t lam_mpi_errors_are_fatal = {
{ NULL, 0 },
"MPI_ERRORS_ARE_FATAL",
false,
LAM_ERRHANDLER_COMM,
{ lam_mpi_errors_are_fatal_handler },
-1
};
/*
* MPI_ERRORS_RETURN
*/
lam_errhandler_t lam_mpi_errors_return = {
{ NULL, 0 },
"MPI_ERRORS_ARE_RETURN",
false,
LAM_ERRHANDLER_COMM,
{ lam_mpi_errors_return_handler },
-1
};
/**
* Errhandler constructor
*/
static void lam_errhandler_construct(lam_errhandler_t *new_errhandler)
{
int ret_val;
/* assign entry in fortran <-> c translation array */
ret_val = lam_pointer_array_add(lam_errhandler_f_to_c_table,
new_errhandler);
new_errhandler->eh_f_to_c_index = ret_val;
}
/**
* Errhandler destructor
*/
static void lam_errhandler_destruct(lam_errhandler_t *errhandler)
{
/* reset the lam_errhandler_f_to_c_table entry - make sure that the
entry is in the table */
if (NULL!= lam_pointer_array_get_item(lam_errhandler_f_to_c_table,
errhandler->eh_f_to_c_index)) {
lam_pointer_array_set_item(lam_errhandler_f_to_c_table,
errhandler->eh_f_to_c_index, NULL);
}
}
/*
* Initialize LAM errhandler infrastructure
*/
int lam_errhandler_init(void)
{
int ret_val;
/* initialize lam_errhandler_f_to_c_table */
lam_errhandler_f_to_c_table = OBJ_NEW(lam_pointer_array_t);
if (NULL == lam_errhandler_f_to_c_table){
return LAM_ERROR;
}
/* Add MPI_ERRHANDLER_NULL to table */
ret_val = lam_pointer_array_add(lam_errhandler_f_to_c_table,
&lam_mpi_errhandler_null);
if (-1 == ret_val){
return LAM_ERROR;
}
/* Make sure that MPI_ERRHANDLER_NULL is in location in the table */
if (LAM_ERRHANDLER_NULL_FORTRAN != ret_val) {
return LAM_ERROR;
};
lam_mpi_errhandler_null.eh_f_to_c_index = ret_val;
/* Add MPI_ERRORS_ARE_FATAL to table */
ret_val = lam_pointer_array_add(lam_errhandler_f_to_c_table,
&lam_mpi_errors_are_fatal);
if (-1 == ret_val){
return LAM_ERROR;
}
/* Make sure that MPI_ERRORS_ARE_FATAL is in location in the
table */
if (LAM_ERRORS_ARE_FATAL_FORTRAN != ret_val) {
return LAM_ERROR;
};
lam_mpi_errors_are_fatal.eh_f_to_c_index = ret_val;
/* Add MPI_ERRORS_RETURN to table */
ret_val = lam_pointer_array_add(lam_errhandler_f_to_c_table,
&lam_mpi_errors_return);
if (-1 == ret_val){
return LAM_ERROR;
}
/* Make sure that MPI_ERRORS_RETURN is in location in the table */
if (LAM_ERRORS_RETURN_FORTRAN != ret_val) {
return LAM_ERROR;
};
lam_mpi_errors_return.eh_f_to_c_index = ret_val;
/* All done */
return LAM_SUCCESS;
}
/*
* Clean up the errorhandler resources
*/
int lam_errhandler_finalize(void)
{
/* Remove errhandler F2C table */
OBJ_RELEASE(lam_errhandler_f_to_c_table);
/* All done */
return LAM_SUCCESS;
};

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

@ -10,59 +10,70 @@
#include "mpi.h"
#include "lfc/lam_object.h"
typedef void (fortran_handler_fn_t)(int *, int *, ...);
/* This must correspond to the fortran MPI_ERRHANDLER_NULL index */
#define LAM_ERRHANDLER_NULL_FORTRAN 0
/* This must correspond to the fortran MPI_ERRORS_ARE_FATAL index */
#define LAM_ERRORS_ARE_FATAL_FORTRAN 1
/* This must correspond to the fortran MPI_ERRORS_RETURN index */
#define LAM_ERRORS_RETURN_FORTRAN 2
/**
* Typedef for all fortran errhandler functions
*/
typedef void (lam_errhandler_fortran_handler_fn_t)(int *, int *, ...);
/**
* Enum used to describe what kind MPI object an error handler is used for
*/
enum lam_errhandler_type_t {
LAM_ERRHANDLER_COMM,
LAM_ERRHANDLER_WIN,
LAM_ERRHANDLER_FILE
};
typedef enum lam_errhandler_type_t lam_errhandler_type_t;
/**
* Back-end type for MPI_Errorhandler.
*/
struct lam_errhandler_t {
lam_object_t super;
char eh_name[MPI_MAX_OBJECT_NAME];
/* Type of MPI object that this handler is for */
lam_errhandler_type_t eh_mpi_object_type;
/* Is this a fortran function? */
bool eh_fortran_function;
enum {
LAM_ERRHANDLER_COMM,
LAM_ERRHANDLER_WIN,
LAM_ERRHANDLER_FILE
} eh_mpi_object_type;
/* Function pointers */
union {
MPI_Comm_errhandler_fn *c_comm_fn;
MPI_File_errhandler_fn *c_file_fn;
MPI_Win_errhandler_fn *c_win_fn;
fortran_handler_fn_t *fort_fn;
lam_errhandler_fortran_handler_fn_t *fort_fn;
} eh_func;
/* index in Fortran <-> C translation array */
int eh_f_to_c_index;
};
typedef struct lam_errhandler_t lam_errhandler_t;
/**
* \internal
*
* This function should not be invoked directly; it should only be
* invoked by LAM_ERRHDL_INVOKE(), LAM_ERRHDL_CHECK(), or
* LAM_ERRHDL_RETURN().
*
* @param errhandler The MPI_Errhandler to invoke
* @param mpi_object The MPI object to invoke the errhandler on (a
* comm, win, or win)
* @param err_code The error code
* @param message Any additional message; typically the name of the
* MPI function that is invoking the error.
*
* This function invokes the MPI exception function on the error
* handler. If the errhandler was created from fortran, the error
* handler will be invoked with fortran linkage. Otherwise, it is
* invoked with C linkage.
*/
int lam_errhandler_invoke(lam_errhandler_t *errhandler, void *mpi_object,
int err_code, char *message);
/**
* This is the macro to invoke to directly invoke an MPI error
* handler.
*
* @param errhandler The MPI_Errhandler to invoke
* @param mpi_object The MPI object to invoke the errhandler on (a
* comm, win, or win)
* @param err_code The error code
@ -74,8 +85,9 @@ int lam_errhandler_invoke(lam_errhandler_t *errhandler, void *mpi_object,
* lam_errhandler_invoke() directly, but is provided to have a
* parallel invocation to LAM_ERRHDL_CHECK() and LAM_ERRHDL_RETURN().
*/
#define LAM_ERRHDL_INVOKE(errhandler, mpi_object, err_code, message) \
lam_errhandler_invoke((errhandler), (mpi_object), (err_code), (message);
#define LAM_ERRHDL_INVOKE(mpi_object, err_code, message) \
lam_errhandler_invoke((mpi_object)->error_handler, (mpi_object), \
(err_code), (message));
/**
* Conditionally invoke an MPI error handler.
@ -91,9 +103,10 @@ int lam_errhandler_invoke(lam_errhandler_t *errhandler, void *mpi_object,
* This macro will invoke the error handler if the return code is not
* LAM_SUCCESS.
*/
#define LAM_ERRHDL_CHECK(rc, errhandler, mpi_object, err_code, message) \
#define LAM_ERRHDL_CHECK(rc, mpi_object, err_code, message) \
if (rc != LAM_SUCCESS) { \
lam_errhandler_invoke((errhandler), (mpi_object), (err_code), (message)); \
lam_errhandler_invoke((errhandler), (mpi_object)->error_handler, \
(mpi_object), (err_code), (message)); \
}
/**
@ -112,12 +125,67 @@ int lam_errhandler_invoke(lam_errhandler_t *errhandler, void *mpi_object,
* LAM_SUCCESS. If the return code is LAM_SUCCESS, then return
* MPI_SUCCESS.
*/
#define LAM_ERRHDL_RETURN(rc, errhandler, mpi_object, err_code, message) \
#define LAM_ERRHDL_RETURN(rc, mpi_object, err_code, message) \
if (rc != LAM_SUCCESS) { \
lam_errhandler_invoke((errhandler), (mpi_object), (err_code), (message)); \
lam_errhandler_invoke((errhandler), (mpi_object)->error_handler, \
(mpi_object), (err_code), (message)); \
} else { \
return MPI_SUCCESS; \
}
#if defined(c_plusplus) || defined(__cplusplus)
extern "C" {
#endif
/**
* Initialize the error handler interface.
*
* Invoked from lam_mpi_init(); sets up the error handler interface,
* creates the predefined MPI errorhandlers, and creates the
* corresopnding F2C translation table.
*/
int lam_errhandler_init(void);
/*
* Finalize the error handler interface.
*
* Invokes from lam_mpi_finalize(); tears down the error handler
* interface, and destroys the F2C translation table.
*/
int lam_errhandler_finalize(void);
/**
* \internal
*
* This function should not be invoked directly; it should only be
* invoked by LAM_ERRHDL_INVOKE(), LAM_ERRHDL_CHECK(), or
* LAM_ERRHDL_RETURN().
*
* @param errhandler The MPI_Errhandler to invoke
* @param mpi_object The MPI object to invoke the errhandler on (a
* comm, win, or win)
* @param err_code The error code
* @param message Any additional message; typically the name of the
* MPI function that is invoking the error.
*
* This function invokes the MPI exception function on the error
* handler. If the errhandler was created from fortran, the error
* handler will be invoked with fortran linkage. Otherwise, it is
* invoked with C linkage.
*/
int lam_errhandler_invoke(lam_errhandler_t *errhandler, void *mpi_object,
int err_code, char *message);
/**
*/
int lam_errhandler_create(void *mpi_object,
lam_errhandler_type_t object_type,
lam_errhandler_fortran_handler_fn_t *func,
lam_errhandler_t **errhandler);
#if defined(c_plusplus) || defined(__cplusplus)
}
#endif
#endif /* LAM_ERRHANDLER_H */

59
src/errhandler/errhandler_invoke.c Обычный файл
Просмотреть файл

@ -0,0 +1,59 @@
/*
* $HEADER$
*/
#include "lam_config.h"
#include "communicator/communicator.h"
#include "win/win.h"
#include "file/file.h"
#include "errhandler/errhandler.h"
int lam_errhandler_invoke(lam_errhandler_t *errhandler, void *mpi_object,
int err_code, char *message)
{
int fortran_handle;
lam_communicator_t *comm;
lam_win_t *win;
lam_file_t *file;
/* Figure out what kind of errhandler it is, figure out if it's
fortran or C, and then invoke it */
switch (errhandler->eh_mpi_object_type) {
case LAM_ERRHANDLER_COMM:
comm = (lam_communicator_t *) mpi_object;
if (errhandler->eh_fortran_function) {
fortran_handle = comm->c_f_to_c_index;
errhandler->eh_func.fort_fn(&fortran_handle, &err_code);
} else {
errhandler->eh_func.c_comm_fn(&comm, &err_code, message);
}
break;
case LAM_ERRHANDLER_WIN:
win = (lam_win_t *) mpi_object;
if (errhandler->eh_fortran_function) {
fortran_handle = win->w_f_to_c_index;
errhandler->eh_func.fort_fn(&fortran_handle, &err_code);
} else {
errhandler->eh_func.c_win_fn(&win, &err_code, message);
}
break;
case LAM_ERRHANDLER_FILE:
file = (lam_file_t *) mpi_object;
if (errhandler->eh_fortran_function) {
fortran_handle = file->f_f_to_c_index;
errhandler->eh_func.fort_fn(&fortran_handle, &err_code);
} else {
errhandler->eh_func.c_file_fn(&file, &err_code, message);
}
break;
}
/* All done */
return err_code;
}

43
src/errhandler/errhandler_predefined.c Обычный файл
Просмотреть файл

@ -0,0 +1,43 @@
/*
* $HEADER$
*/
#include <stdlib.h>
#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include "util/output.h"
#include "errhandler/errhandler.h"
#include "errhandler/errhandler_predefined.h"
void lam_mpi_errors_are_fatal_handler(lam_communicator_t **comm,
int *error_code, ...)
{
va_list arglist;
#if __STDC__
va_start(arglist, error_code);
#else
va_start(arglist);
#endif
lam_output(0, "*** An error occurred in %s", va_arg(arglist, char *));
lam_output(0, "*** on communicator %s", (*comm)->c_name);
lam_output(0, "*** error code: %d\n", *error_code);
/* JMS: Should print the error string as well */
lam_output(0, "*** MPI_ERRORS_ARE_FATAL");
va_end(arglist);
/* Should we do something more intelligent here? */
abort();
}
void lam_mpi_errors_return_handler(lam_communicator_t **comm,
int *error_code, ...)
{
/* Don't need anything more -- just need this function to exist */
}

26
src/errhandler/errhandler_predefined.h Обычный файл
Просмотреть файл

@ -0,0 +1,26 @@
/*
* $HEADER$
*/
#ifndef LAM_ERRHANDLER_PREDEFINED_H
#define LAM_ERRHANDLER_PREDEFINED_H
#include "errhandler/errhandler.h"
#include "communicator/communicator.h"
/**
* Handler function for MPI_ERRORS_ARE_FATAL
*/
void lam_mpi_errors_are_fatal_handler(lam_communicator_t **comm,
int *error_code, ...);
/**
* Handler function for MPI_ERRORS_RETURN
*/
void lam_mpi_errors_return_handler(lam_communicator_t **comm,
int *error_code, ...);
#endif /* LAM_ERRHANDLER_PREDEFINED_H */

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

@ -29,9 +29,11 @@ struct lam_file_t {
int f_f_to_c_index;
/* Error handling */
/* Error handling. This field does not have the "f_" prefix so that
the LAM_ERRHDL_* macros can find it, regardless of whether it's a
comm, window, or file. */
lam_errhandler_t *f_errhandler;
lam_errhandler_t *error_handler;
};
typedef struct lam_file_t lam_file_t;

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

@ -6,12 +6,30 @@
#include "mpi.h"
#include "mpi/c/bindings.h"
#include "errhandler/errhandler.h"
#include "communicator/communicator.h"
#if LAM_HAVE_WEAK_SYMBOLS && LAM_PROFILING_DEFINES
#pragma weak MPI_Comm_create_errhandler = PMPI_Comm_create_errhandler
#endif
int MPI_Comm_create_errhandler(MPI_Comm_errhandler_fn *function,
MPI_Errhandler *errhandler) {
return MPI_SUCCESS;
MPI_Errhandler *errhandler)
{
/* Error checking */
if (MPI_PARAM_CHECK) {
if (NULL == function ||
NULL == errhandler) {
return LAM_ERRHDL_INVOKE(MPI_COMM_WORLD, MPI_ERR_ARG,
"MPI_Errhandler_get");
}
}
/* JMS Continue here */
/* All done */
return MPI_SUCCESS;
}

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

@ -6,11 +6,33 @@
#include "mpi.h"
#include "mpi/c/bindings.h"
#include "errhandler/errhandler.h"
#include "communicator/communicator.h"
#if LAM_HAVE_WEAK_SYMBOLS && LAM_PROFILING_DEFINES
#pragma weak MPI_Errhandler_get = PMPI_Errhandler_get
#endif
int MPI_Errhandler_get(MPI_Comm comm, MPI_Errhandler *errhandler) {
return MPI_SUCCESS;
int MPI_Errhandler_get(MPI_Comm comm, MPI_Errhandler *errhandler)
{
/* Error checking */
if (MPI_PARAM_CHECK) {
if (MPI_COMM_NULL == comm) {
return LAM_ERRHDL_INVOKE(MPI_COMM_WORLD, MPI_ERR_ARG,
"MPI_Errhandler_get");
} else if (NULL == errhandler) {
return LAM_ERRHDL_INVOKE(comm, MPI_ERR_ARG, "MPI_Errhandler_get");
}
}
/* This is the backwards compatability function for communicator
errorhandlers */
*errhandler = comm->error_handler;
/* All done */
return MPI_SUCCESS;
}

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

@ -8,6 +8,7 @@
#include "runtime/runtime.h"
#include "mpi.h"
#include "group/group.h"
#include "errhandler/errhandler.h"
#include "runtime/runtime.h"
#include "mca/base/base.h"
#include "mca/ptl/ptl.h"
@ -55,6 +56,11 @@ int lam_mpi_finalize(void)
return ret;
}
/* free errhandler resources */
if (LAM_SUCCESS != (ret = lam_errhandler_finalize())) {
return ret;
}
if (LAM_SUCCESS != (ret = lam_finalize())) {
return ret;
}

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

@ -10,6 +10,7 @@
#include "runtime/runtime.h"
#include "communicator/communicator.h"
#include "group/group.h"
#include "errhandler/errhandler.h"
#include "mca/base/base.h"
#include "mca/base/base.h"
#include "mca/ptl/ptl.h"
@ -96,6 +97,11 @@ int lam_mpi_init(int argc, char **argv, int requested, int *provided)
return ret;
}
/* initialize error handlers */
if (LAM_SUCCESS != (ret = lam_errhandler_init())) {
return ret;
}
/* initialize groups */
if (LAM_SUCCESS != (ret = lam_group_init())) {
return ret;

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

@ -24,9 +24,11 @@ struct lam_win_t {
int w_f_to_c_index;
/* Error handling */
/* Error handling. This field does not have the "w_" prefix so that
the LAM_ERRHDL_* macros can find it, regardless of whether it's a
comm, window, or file. */
lam_errhandler_t *w_errhandler;
lam_errhandler_t *error_handler;
};
typedef struct lam_win_t lam_win_t;