1
1
openmpi/ompi/errhandler/errhandler.h
Wesley Bland e1ba09ad51 Add a resilience to ORTE. Allows the runtime to continue after a process (or
ORTED) failure. Note that more work will be necessary to allow the MPI layer to
take advantage of this.

Per RFC:
http://www.open-mpi.org/community/lists/devel/2011/06/9299.php

This commit was SVN r24815.
2011-06-23 20:38:02 +00:00

400 строки
13 KiB
C

/* -*- Mode: C; c-basic-offset:4 ; -*- */
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2011 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2008-2010 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2008-2009 Sun Microsystems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
/** @file **/
#ifndef OMPI_ERRHANDLER_H
#define OMPI_ERRHANDLER_H
#include "ompi_config.h"
#include "mpi.h"
#include "opal/prefetch.h"
#include "opal/class/opal_object.h"
#include "opal/class/opal_pointer_array.h"
#include "ompi/runtime/mpiruntime.h"
#include "ompi/errhandler/errhandler_predefined.h"
#include "ompi/errhandler/errcode-internal.h"
#include "orte/types.h"
BEGIN_C_DECLS
/*
* These must correspond to the fortran handle indices
*/
enum {
OMPI_ERRHANDLER_NULL_FORTRAN = 0,
OMPI_ERRORS_ARE_FATAL_FORTRAN,
OMPI_ERRORS_RETURN_FORTRAN
};
/**
* Typedef for all fortran errhandler functions
*/
typedef void (ompi_errhandler_fortran_handler_fn_t)(MPI_Fint *,
MPI_Fint *, ...);
/**
* Typedef for generic errhandler function
*/
typedef void (ompi_errhandler_generic_handler_fn_t)(void *, int *, ...);
/**
* Enum to denote what language the error handler was created from
*/
enum ompi_errhandler_lang_t {
OMPI_ERRHANDLER_LANG_C,
OMPI_ERRHANDLER_LANG_CXX,
OMPI_ERRHANDLER_LANG_FORTRAN
};
typedef enum ompi_errhandler_lang_t ompi_errhandler_lang_t;
/**
* Enum used to describe what kind MPI object an error handler is used for
*/
enum ompi_errhandler_type_t {
OMPI_ERRHANDLER_TYPE_PREDEFINED,
OMPI_ERRHANDLER_TYPE_COMM,
OMPI_ERRHANDLER_TYPE_WIN,
OMPI_ERRHANDLER_TYPE_FILE
};
typedef enum ompi_errhandler_type_t ompi_errhandler_type_t;
/*
* Need to forward declare this for use in ompi_errhandle_cxx_dispatch_fn_t.
*/
struct ompi_errhandler_t;
/**
* C++ invocation function signature
*/
typedef void (ompi_errhandler_cxx_dispatch_fn_t)(struct ompi_errhandler_t *errhandler,
void *handle, int *err_code,
const char *message);
/**
* Back-end type for MPI_Errorhandler.
*/
struct ompi_errhandler_t {
opal_object_t super;
char eh_name[MPI_MAX_OBJECT_NAME];
/* Type of MPI object that this handler is for */
ompi_errhandler_type_t eh_mpi_object_type;
/* What language was the error handler created in */
ompi_errhandler_lang_t eh_lang;
/* Function pointers. Note that we *have* to have all 4 types
(vs., for example, a union) because the predefined errhandlers
can be invoked on any MPI object type, so we need callbacks for
all of three. */
MPI_Comm_errhandler_function *eh_comm_fn;
ompi_file_errhandler_fn *eh_file_fn;
MPI_Win_errhandler_function *eh_win_fn;
ompi_errhandler_fortran_handler_fn_t *eh_fort_fn;
/* Have separate callback for C++ errhandlers. This pointer is
initialized to NULL and will be set explicitly by the C++
bindings for Create_errhandler. This function is invoked
when eh_lang==OMPI_ERRHANDLER_LANG_CXX so that the user's
callback function can be invoked with the right language
semantics. */
ompi_errhandler_cxx_dispatch_fn_t *eh_cxx_dispatch_fn;
/* index in Fortran <-> C translation array */
int eh_f_to_c_index;
};
typedef struct ompi_errhandler_t ompi_errhandler_t;
/**
* Padded struct to maintain back compatibiltiy.
* See ompi/communicator/communicator.h comments with struct ompi_communicator_t
* for full explanation why we chose the following padding construct for predefines.
*/
#define PREDEFINED_ERRHANDLER_PAD 1024
struct ompi_predefined_errhandler_t {
struct ompi_errhandler_t eh;
char padding[PREDEFINED_ERRHANDLER_PAD - sizeof(ompi_errhandler_t)];
};
typedef struct ompi_predefined_errhandler_t ompi_predefined_errhandler_t;
/**
* Global variable for MPI_ERRHANDLER_NULL
*/
OMPI_DECLSPEC extern ompi_predefined_errhandler_t ompi_mpi_errhandler_null;
/**
* Global variable for MPI_ERRORS_ARE_FATAL
*/
OMPI_DECLSPEC extern ompi_predefined_errhandler_t ompi_mpi_errors_are_fatal;
/**
* Global variable for MPI_ERRORS_RETURN
*/
OMPI_DECLSPEC extern ompi_predefined_errhandler_t ompi_mpi_errors_return;
/**
* Global variable for MPI::ERRORS_THROW_EXCEPTIONS. Will abort if
* MPI_INIT wasn't called as MPI::INIT
*/
OMPI_DECLSPEC extern ompi_predefined_errhandler_t ompi_mpi_errors_throw_exceptions;
/**
* Table for Fortran <-> C errhandler handle conversion
*/
OMPI_DECLSPEC extern opal_pointer_array_t ompi_errhandler_f_to_c_table;
/**
* Forward declaration so that we don't have to include
* request/request.h here.
*/
struct ompi_request_t;
/**
* This is the macro to check the state of MPI and determine whether
* it was properly initialized and not yet finalized.
*
* This macro directly invokes the ompi_mpi_errors_are_fatal_handler()
* when an error occurs because MPI_COMM_WORLD does not exist (because
* we're before MPI_Init() or after MPI_Finalize()).
*/
#define OMPI_ERR_INIT_FINALIZE(name) \
if( OPAL_UNLIKELY(!ompi_mpi_initialized || ompi_mpi_finalized) ) { \
ompi_mpi_errors_are_fatal_comm_handler(NULL, NULL, name); \
}
/**
* This is the macro to invoke to directly invoke an MPI error
* handler.
*
* @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 macro is used when you want to directly invoke the error
* handler. It is exactly equivalent to calling
* ompi_errhandler_invoke() directly, but is provided to have a
* parallel invocation to OMPI_ERRHANDLER_CHECK() and OMPI_ERRHANDLER_RETURN().
*/
#define OMPI_ERRHANDLER_INVOKE(mpi_object, err_code, message) \
ompi_errhandler_invoke((mpi_object)->error_handler, \
(mpi_object), \
(int)(mpi_object)->errhandler_type, \
ompi_errcode_get_mpi_code(err_code), \
(message));
/**
* Conditionally invoke an MPI error handler.
*
* @param rc The return code to check
* @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 macro will invoke the error handler if the return code is not
* OMPI_SUCCESS.
*/
#define OMPI_ERRHANDLER_CHECK(rc, mpi_object, err_code, message) \
if( OPAL_UNLIKELY(rc != OMPI_SUCCESS) ) { \
int __mpi_err_code = ompi_errcode_get_mpi_code(err_code); \
OPAL_CR_EXIT_LIBRARY() \
ompi_errhandler_invoke((mpi_object)->error_handler, \
(mpi_object), \
(int) (mpi_object)->errhandler_type, \
(__mpi_err_code), \
(message)); \
return (__mpi_err_code); \
}
/**
* Conditionally invoke an MPI error handler; if there is no error,
* return MPI_SUCCESS.
*
* @param rc The return code to check
* @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 macro will invoke the error handler if the return code is not
* OMPI_SUCCESS. If the return code is OMPI_SUCCESS, then return
* MPI_SUCCESS.
*/
#define OMPI_ERRHANDLER_RETURN(rc, mpi_object, err_code, message) \
OPAL_CR_EXIT_LIBRARY() \
if ( OPAL_UNLIKELY(OMPI_SUCCESS != rc) ) { \
int __mpi_err_code = ompi_errcode_get_mpi_code(err_code); \
ompi_errhandler_invoke((mpi_object)->error_handler, \
(mpi_object), \
(int)(mpi_object)->errhandler_type, \
(__mpi_err_code), \
(message)); \
return (__mpi_err_code); \
} else { \
return MPI_SUCCESS; \
}
/**
* Initialize the error handler interface.
*
* @returns OMPI_SUCCESS Upon success
* @returns OMPI_ERROR Otherwise
*
* Invoked from ompi_mpi_init(); sets up the error handler interface,
* creates the predefined MPI errorhandlers, and creates the
* corresopnding F2C translation table.
*/
int ompi_errhandler_init(void);
/**
* Finalize the error handler interface.
*
* @returns OMPI_SUCCESS Always
*
* Invokes from ompi_mpi_finalize(); tears down the error handler
* interface, and destroys the F2C translation table.
*/
int ompi_errhandler_finalize(void);
/**
* \internal
*
* This function should not be invoked directly; it should only be
* invoked by OMPI_ERRHANDLER_INVOKE(), OMPI_ERRHANDLER_CHECK(), or
* OMPI_ERRHANDLER_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 type The type of the MPI object. Necessary, since
* you can not assign a single type to the predefined
* error handlers. This information is therefore
* stored on the MPI object itself.
* @param err_code The error code
* @param message Any additional message; typically the name of the
* MPI function that is invoking the error.
*
* @returns err_code The same value as the parameter
*
* 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.
*
* If this function returns, it returns the err_code. Note that it
* may not return (e.g., for MPI_ERRORS_ARE_FATAL).
*/
OMPI_DECLSPEC int ompi_errhandler_invoke(ompi_errhandler_t *errhandler, void *mpi_object,
int type, int err_code, const char *message);
/**
* Invoke an MPI exception on the first request found in the array
* that has a non-MPI_SUCCESS value for MPI_ERROR in its status. It
* is safe to invoke this function if none of the requests have an
* outstanding error; MPI_SUCCESS will be returned.
*/
int ompi_errhandler_request_invoke(int count,
struct ompi_request_t **requests,
const char *message);
/**
* Create a ompi_errhandler_t
*
* @param object_type Enum of the type of MPI object
* @param func Function pointer of the error handler
*
* @returns errhandler Pointer to the ompi_errorhandler_t that will be
* created and returned
*
* This function is called as the back-end of all the
* MPI_*_CREATE_ERRHANDLER functions. It creates a new
* ompi_errhandler_t object, initializes it to the correct object
* type, and sets the callback function on it.
*
* The type of the function pointer is (arbitrarily) the fortran
* function handler type. Since this function has to accept 4
* different function pointer types (lest we have 4 different
* functions to create errhandlers), the fortran one was picked
* arbitrarily. Note that (void*) is not sufficient because at
* least theoretically, a sizeof(void*) may not necessarily be the
* same as sizeof(void(*)).
*/
OMPI_DECLSPEC ompi_errhandler_t *ompi_errhandler_create(ompi_errhandler_type_t object_type,
ompi_errhandler_generic_handler_fn_t *func,
ompi_errhandler_lang_t language);
/**
* Callback function from runtime layer to alert the MPI layer of an error at
* the runtime layer.
*
* @param procs The names of the processes that have failed.
*
* This function is used to alert the MPI layer to a specific fault at the
* runtime layer. Currently, the only faults reported using this method are
* process failures. The MPI layer has the option to perform whatever actions it
* needs to stabalize itself and continue running, abort, etc.
*/
OMPI_DECLSPEC void ompi_errhandler_runtime_callback(opal_pointer_array_t *procs);
/**
* Check to see if an errhandler is intrinsic.
*
* @param errhandler The errhandler to check
*
* @returns true If the errhandler is intrinsic
* @returns false If the errhandler is not intrinsic
*
* Self-explanitory. This is needed in a few top-level MPI functions;
* this function is provided to hide the internal structure field
* names.
*/
static inline bool ompi_errhandler_is_intrinsic(ompi_errhandler_t *errhandler)
{
if ( OMPI_ERRHANDLER_TYPE_PREDEFINED == errhandler->eh_mpi_object_type )
return true;
return false;
}
END_C_DECLS
#endif /* OMPI_ERRHANDLER_H */