⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 errutil.c

📁 fortran并行计算包
💻 C
📖 第 1 页 / 共 4 页
字号:
/* -*- Mode: C; c-basic-offset:4 ; -*- *//* * *  (C) 2001 by Argonne National Laboratory. *      See COPYRIGHT in top-level directory. *//* style: allow:fprintf:4 sig:0 *//* stdarg is required to handle the variable argument lists for    MPIR_Err_create_code */#include <stdarg.h>/* Define USE_ERR_CODE_VALIST to get the prototype for the valist version   of MPIR_Err_create_code in mpierror.h (without this definition,   the prototype is not included.  The "valist" version of the function   is used in only a few places, here and potentially in ROMIO) */#define USE_ERR_CODE_VALIST#include "mpiimpl.h"/* errcodes.h contains the macros used to access fields within an error   code and a description of the bits in an error code.  A brief   version of that description is included below */#include "errcodes.h"/* defmsg is generated automatically from the source files and contains   all of the error messages, both the generic and specific.  Depending    on the value of MPICH_ERROR_MSG_LEVEL, different amounts of message   information will be included from the file defmsg.h */#include "defmsg.h" /* stdio is needed for vsprintf and vsnprintf */#include <stdio.h>/* TEMP TO KEEP COMPILER HAPPY */void MPIR_Err_print_stack_string_ext(int errcode, char *str, int maxlen, 				     MPIR_Err_get_class_string_func_t fn);/* * Structure of this file * * This file contains several groups of routines user for error handling * and reporting.   * * The first group provides memory for the MPID_Errhandler objects  * and the routines to free and manipulate them * * MPIR_Err_return_xxx - For each of the MPI types on which an  * error handler can be defined, there is an MPIR_Err_return_xxx routine * that determines what error handler function to call and whether to  * abort the program.  The comm and win versions are here; ROMIO * provides its own routines for invoking the error handlers for Files. * * The next group of code handles the error messages.  There are three * options, controlled by the value of MPICH_ERROR_MSG_LEVEL.  * * MPICH_ERROR_MSG_NONE - No text messages at all * MPICH_ERROR_MSG_CLASS - Only messages for the MPI error classes * MPICH_ERROR_MSG_GENERIC - Only predefiend messages for the MPI error codes * MPICH_ERROR_MSG_ALL - Instance specific error messages (and error message *                       stack) * * In only the latter (MPICH_ERROR_MSG_ALL) case are instance-specific * messages maintained (including the error message "stack" that you may * see mentioned in various places.  In the other cases, an error code  * identifies a fixed message string (unless MPICH_ERROR_MSG_NONE, * when there are no strings) from the "generic" strings defined in defmsg.h * * A major subgroup in this section is the code to handle the instance-specific * messages (MPICH_ERROR_MSG_ALL only).   * * An MPI error code is made up of a number of fields (see errcodes.h) * These ar  *   is-dynamic? specific-msg-sequence# specific-msg-index  *                                            generic-code is-fatal? class * * There are macros (defined in errcodes.h) that define these fields,  * their sizes, and masks and shifts that may be used to extract them. *//* A few prototypes.  These routines are called from the MPIR_Err_return    routines.  checkValidErrcode depends on the MPICH_ERROR_MSG_LEVEL */static int checkValidErrcode( int error_class, const char fcname[], 			      int *errcode );static void handleFatalError( MPID_Comm *comm_ptr, 			      const char fcname[], int errcode );#if MPICH_ERROR_MSG_LEVEL >= MPICH_ERROR_MSG_ALLstatic int ErrGetInstanceString( int errorcode, char *msg, int num_remaining, 				 MPIR_Err_get_class_string_func_t fn );static void MPIR_Err_stack_init( void );static int checkForUserErrcode( int errcode );#else/* We only need special handling for user error codes when we support the   error message stack */#define checkForUserErrcode(_a) _a#endif/* ------------------------------------------------------------------------- *//* Provide the MPID_Errhandler space and the routines to free and set them   from C++  *//* ------------------------------------------------------------------------- *//* * Error handlers.  These are handled just like the other opaque objects * in MPICH */#ifndef MPID_ERRHANDLER_PREALLOC #define MPID_ERRHANDLER_PREALLOC 8#endif/* Preallocated errorhandler objects */MPID_Errhandler MPID_Errhandler_builtin[2] =           { { MPI_ERRORS_ARE_FATAL, 0},	    { MPI_ERRORS_RETURN, 0} }; MPID_Errhandler MPID_Errhandler_direct[MPID_ERRHANDLER_PREALLOC] = { {0} };MPIU_Object_alloc_t MPID_Errhandler_mem = { 0, 0, 0, 0, MPID_ERRHANDLER, 					    sizeof(MPID_Errhandler), 					    MPID_Errhandler_direct,					    MPID_ERRHANDLER_PREALLOC, };void MPID_Errhandler_free(MPID_Errhandler *errhan_ptr){    MPIU_Handle_obj_free(&MPID_Errhandler_mem, errhan_ptr);}#ifdef HAVE_CXX_BINDING/* This routine is used to install a callback used by the C++ binding to invoke the (C++) error handler.  The callback routine is a C routine, defined in the C++ binding. */void MPIR_Errhandler_set_cxx( MPI_Errhandler errhand, void (*errcall)(void) ){    MPID_Errhandler *errhand_ptr;        MPID_Errhandler_get_ptr( errhand, errhand_ptr );    errhand_ptr->language		= MPID_LANG_CXX;    MPIR_Process.cxx_call_errfn	= (void (*)( int, int *, int *, 					    void (*)(void) ))errcall;}#endif/* ------------------------------------------------------------------------- *//*    Nesting level for routines.   Note that since these use per-thread data, no locks or atomic update   routines are required.   In a single-threaded environment, these are replaced with   MPIR_Thread.nest_count ++, --.  These are defined in the mpiimpl.h file. *//* ------------------------------------------------------------------------- *//* These routines export the nest increment and decrement for use in ROMIO */void MPIR_Nest_incr_export( void ){    MPICH_PerThread_t *p;    MPIR_GetPerThread(&p);    p->nest_count++;}void MPIR_Nest_decr_export( void ){    MPICH_PerThread_t *p;    MPIR_GetPerThread(&p);    p->nest_count--;}/* ------------------------------------------------------------------------- *//* These routines are called on error exit from most top-level MPI routines   to invoke the appropriate error handler.  Also included is the routine   to call if MPI has not been initialized (MPIR_Err_preinit) and to    determine if an error code represents a fatal error (MPIR_Err_is_fatal). *//* ------------------------------------------------------------------------- *//* Special error handler to call if we are not yet initialized, or if we   have finalized */void MPIR_Err_preOrPostInit( void ){    if (MPIR_Process.initialized == MPICH_PRE_INIT) {	MPIU_Error_printf("Attempting to use an MPI routine before initializing MPICH\n");    }    else if (MPIR_Process.initialized == MPICH_POST_FINALIZED) {	MPIU_Error_printf("Attempting to use an MPI routine after finalizing MPICH\n");    }    else {	MPIU_Error_printf("Internal Error: Unknown state of MPI (neither initialized nor finalized)\n" );    }    exit(1);}/* Return true if the error code indicates a fatal error */int MPIR_Err_is_fatal(int errcode){    return (errcode & ERROR_FATAL_MASK) ? TRUE : FALSE;}/* * This is the routine that is invoked by most MPI routines to  * report an error  */int MPIR_Err_return_comm( MPID_Comm  *comm_ptr, const char fcname[], 			  int errcode ){    const int error_class = ERROR_GET_CLASS(errcode);    int rc;    MPIU_THREADPRIV_DECL;    MPIU_THREADPRIV_GET;     rc = checkValidErrcode( error_class, fcname, &errcode );        /* First, check the nesting level */    if (MPIR_Nest_value()) return errcode;        if (!comm_ptr || comm_ptr->errhandler == NULL) {	/* Try to replace with the default handler, which is the one on 	   MPI_COMM_WORLD.  This gives us correct behavior for the	   case where the error handler on MPI_COMM_WORLD has been changed. */	if (MPIR_Process.comm_world)	{	    comm_ptr = MPIR_Process.comm_world;	}    }    if (MPIR_Err_is_fatal(errcode) ||	comm_ptr == NULL || comm_ptr->errhandler == NULL || 	comm_ptr->errhandler->handle == MPI_ERRORS_ARE_FATAL) {	/* Calls MPID_Abort */	handleFatalError( comm_ptr, fcname, errcode );    }    /* Check for the special case of a user-provided error code */    errcode = checkForUserErrcode( errcode );        if (comm_ptr->errhandler->handle == MPI_ERRORS_RETURN)    {	return errcode;    }    else    {	/* The user error handler may make calls to MPI routines, so the	 * nesting counter must be incremented before the handler is called */	MPIR_Nest_incr();    	/* We pass a final 0 (for a null pointer) to these routines	   because MPICH-1 expected that */	switch (comm_ptr->errhandler->language)	{	case MPID_LANG_C:	    (*comm_ptr->errhandler->errfn.C_Comm_Handler_function)( 		&comm_ptr->handle, &errcode, 0 );	    break;#ifdef HAVE_CXX_BINDING	case MPID_LANG_CXX:	    (*MPIR_Process.cxx_call_errfn)( 0, &comm_ptr->handle, &errcode, 		    (void (*)(void))*comm_ptr->errhandler->errfn.C_Comm_Handler_function );	    /* The C++ code throws an exception if the error handler 	     returns something other than MPI_SUCCESS. There is no "return"	     of an error code. */	    errcode = MPI_SUCCESS;	    break;#endif#ifdef HAVE_FORTRAN_BINDING	case MPID_LANG_FORTRAN90:	case MPID_LANG_FORTRAN:	    (*comm_ptr->errhandler->errfn.F77_Handler_function)( 		(MPI_Fint *)&comm_ptr->handle, &errcode );	    break;#endif	}	MPIR_Nest_decr();    }    return errcode;}/*  * MPI routines that detect errors on window objects use this to report errors */int MPIR_Err_return_win( MPID_Win  *win_ptr, const char fcname[], int errcode ){    const int error_class = ERROR_GET_CLASS(errcode);    int rc ;    MPIU_THREADPRIV_DECL;    MPIU_THREADPRIV_GET;    if (win_ptr == NULL || win_ptr->errhandler == NULL)	return MPIR_Err_return_comm(NULL, fcname, errcode);    rc = checkValidErrcode( error_class, fcname, &errcode );    /* First, check the nesting level */    if (MPIR_Nest_value()) return errcode;    if (MPIR_Err_is_fatal(errcode) ||	win_ptr == NULL || win_ptr->errhandler == NULL || 	win_ptr->errhandler->handle == MPI_ERRORS_ARE_FATAL) {	/* Calls MPID_Abort */	handleFatalError( NULL, fcname, errcode );    }    /* Check for the special case of a user-provided error code */    errcode = checkForUserErrcode( errcode );        if (win_ptr->errhandler->handle == MPI_ERRORS_RETURN)    {	return errcode;    }    else    {	/* Now, invoke the error handler for the window */	/* The user error handler may make calls to MPI routines, so the	 * nesting counter must be incremented before the handler is called */	MPIR_Nest_incr();    	/* We pass a final 0 (for a null pointer) to these routines	   because MPICH-1 expected that */	switch (win_ptr->errhandler->language)	{	    case MPID_LANG_C:		(*win_ptr->errhandler->errfn.C_Win_Handler_function)( 		    &win_ptr->handle, &errcode, 0 );		break;#ifdef HAVE_CXX_BINDING	    case MPID_LANG_CXX:	    (*MPIR_Process.cxx_call_errfn)( 2, &win_ptr->handle, &errcode, 		    (void (*)(void))*win_ptr->errhandler->errfn.C_Win_Handler_function );	    /* The C++ code throws an exception if the error handler 	     returns something other than MPI_SUCCESS. There is no "return"	     of an error code. */	    errcode = MPI_SUCCESS;	    break;#endif#ifdef HAVE_FORTRAN_BINDING	    case MPID_LANG_FORTRAN90:	    case MPID_LANG_FORTRAN:		(*win_ptr->errhandler->errfn.F77_Handler_function)( 		    (MPI_Fint *)&win_ptr->handle, &errcode );		break;#endif	}	MPIR_Nest_decr();    }    return errcode;}/* ------------------------------------------------------------------------- *//* ------------------------------------------------------------------------- */static int convertErrcodeToIndexes( int errcode, int *ring_idx, int *ring_id,				    int *generic_idx );static int checkErrcodeIsValid( int errcode );static const char *ErrcodeInvalidReasonStr( int reason );static const char *get_class_msg( int error_class );void MPIR_Err_init( void ){#   if MPICH_ERROR_MSG_LEVEL >= MPICH_ERROR_MSG_ALL    MPIR_Err_stack_init();#   endif}/* ------------------------------------------------------------------------- *//* The following block of code manages the instance-specific error messages  *//* ------------------------------------------------------------------------- */ /* Check for a valid error code.  If the code is not valid, attempt to   print out something sensible; reset the error code to have class    ERR_UNKNOWN *//* FIXME: Now that error codes are chained, this does not produce a valid    error code since there is no valid ring index corresponding to this code */static int checkValidErrcode( int error_class, const char fcname[], 			      int *errcode_p ){    int errcode = *errcode_p;    int rc = 0;    if (error_class > MPICH_ERR_LAST_CLASS)    {	if (errcode & ~ERROR_CLASS_MASK)	{	    MPIU_Error_printf("INTERNAL ERROR: Invalid error class (%d) encountered while returning from\n"			      "%s.  Please file a bug report.\n", error_class, fcname);	    /* Note that we don't try to print the error stack; if the 	       error code is invalid, it can't be used to find	       the error stack.  We could consider dumping the 	       contents of the error ring instead (without trying	       to interpret them) */	}	else	{	    MPIU_Error_printf("INTERNAL ERROR: Invalid error class (%d) encountered while returning from\n"			      "%s.  Please file a bug report.  No error stack is available.\n", error_class, fcname);	}	/* FIXME: We probably want to set this to MPI_ERR_UNKNOWN	   and discard the rest of the bits */	errcode = (errcode & ~ERROR_CLASS_MASK) | MPI_ERR_UNKNOWN;	rc = 1;    }    *errcode_p = errcode;    return rc;}/* Check that an encoded error code is valid. Return 0 if valid, positive,    non-zero if invalid.  Value indicates reason; see    ErrcodeInvalidReasonStr() */#if MPICH_ERROR_MSG_LEVEL <= MPICH_ERROR_MSG_GENERIC/* This is the shortened version when there are no error messages */static int checkErrcodeIsValid( int errcode ){    /* MPICH_ERR_LAST_CLASS is the last of the *predefined* error classes. */    /* FIXME: Should this check against dynamically-created error classes? */    if (errcode < 0 || errcode >= MPICH_ERR_LAST_CLASS) {	return 3;    }    return 0;}static const char *ErrcodeInvalidReasonStr( int reason ){    const char *str = 0;    /* FIXME: These strings need to be internationalized */    switch (reason) {    case 3:	str = "Message class is out of range";	break;    default:	str = "Unknown reason for invalid errcode";	break;    }    return str;}#endif/* This routine is called when there is a fatal error */static void handleFatalError( MPID_Comm *comm_ptr, 			      const char fcname[], int errcode ){    /* Define length of the the maximum error message line (or string with        newlines?).  This definition is used only within this routine.  */    /* FIXME: This should really be the same as MPI_MAX_ERROR_STRING, or in the       worst case, defined in terms of that */#define MAX_ERRMSG_STRING 4096    char error_msg[ MAX_ERRMSG_STRING ];    int len;    /* FIXME: Not internationalized */    MPIU_Snprintf(error_msg, MAX_ERRMSG_STRING, "Fatal error in %s: ", fcname);    len = (int)strlen(error_msg);    MPIR_Err_get_string(errcode, &error_msg[len], MAX_ERRMSG_STRING-len, NULL);    /* The third argument is a return code, a value of 1 usually indicates       an error */    MPID_Abort(comm_ptr, MPI_SUCCESS, 1, error_msg);}#if MPICH_ERROR_MSG_LEVEL >= MPICH_ERROR_MSG_GENERIC/*  * Given a message string abbreviation (e.g., one that starts "**"), return  * the corresponding index.  For the generic (non * parameterized messages), use idx = FindGenericMsgIndex( "**msg" ); */static int FindGenericMsgIndex( const char *msg ){    int i, c;    for (i=0; i<generic_msgs_len; i++) {	/* Check the sentinals to insure that the values are ok first */	if (generic_err_msgs[i].sentinal1 != 0xacebad03 ||	    generic_err_msgs[i].sentinal2 != 0xcb0bfa11) {	    /* Something bad has happened! Don't risk trying the	       short_name pointer; it may have been corrupted */	    break;	}	c = strcmp( generic_err_msgs[i].short_name, msg );	if (c == 0) return i;	if (c > 0)	{	    /* don't return here if the string partially matches */	    if (strncmp(generic_err_msgs[i].short_name, msg, strlen(msg)) != 0)		return -1;	}    }    return -1;}/*    Here is an alternate search routine based on bisection.   int i_low, i_mid, i_high, c;   i_low = 0; i_high = generic_msg_len - 1;   while (i_high - i_low >= 0) {       i_mid = (i_high + i_low) / 2;       c = strcmp( generic_err_msgs[i].short_name, msg );       if (c == 0) return i_mid;       if (c < 0) { i_low = i_mid + 1; }       else       { i_high = i_mid - 1; }   }   return -1;*/#endif#if MPICH_ERROR_MSG_LEVEL == MPICH_ERROR_MSG_ALL/*  * Given a message string abbreviation (e.g., one that starts "**"), return  * the corresponding index.  For the specific * (parameterized messages), use idx = FindSpecificMsgIndex( "**msg" ); */static int FindSpecificMsgIndex( const char *msg ){    int i, c;    for (i=0; i<specific_msgs_len; i++) {	/* Check the sentinals to insure that the values are ok first */	if (specific_err_msgs[i].sentinal1 != 0xacebad03 ||

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -