-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpi/errhan/dynerrutil.c
        -:    0:Graph:dynerrutil.gcno
        -:    0:Data:dynerrutil.gcda
        -:    0:Runs:519
        -:    0:Programs:142
        -:    1:/* -*- Mode: C; c-basic-offset:4 ; -*- */
        -:    2:/*
        -:    3: *
        -:    4: *  (C) 2001 by Argonne National Laboratory.
        -:    5: *      See COPYRIGHT in top-level directory.
        -:    6: */
        -:    7:
        -:    8:#include "mpiimpl.h"
        -:    9:#include "errcodes.h"
        -:   10:
        -:   11:#include <string.h>
        -:   12:
        -:   13:/*
        -:   14: * This file contains the routines needed to implement the MPI routines that
        -:   15: * can add error classes and codes during runtime.  This file is organized
        -:   16: * so that applications that do not use the MPI-2 routines to create new
        -:   17: * error codes will not load any of this code.  
        -:   18: * 
        -:   19: * ROMIO has been customized to provide error messages with the same tools
        -:   20: * as the rest of MPICH2 and will not rely on the dynamically assigned
        -:   21: * error classes.  This leaves all of the classes and codes for the user.
        -:   22: *
        -:   23: * Because we have customized ROMIO, we do not need to implement 
        -:   24: * instance-specific messages for the dynamic error codes.  
        -:   25: */
        -:   26:
        -:   27:/* Local data structures.
        -:   28:   A message may be associated with each class and code.
        -:   29:   Since we limit the number of user-defined classes and code (no more
        -:   30:   than 256 of each), we allocate an array of pointers to the messages here.
        -:   31:
        -:   32:   We *could* allow 256 codes with each class.  However, we don't expect 
        -:   33:   any need for this many codes, so we simply allow 256 (actually
        -:   34:   ERROR_MAX_NCODE) codes, and distribute these among the error codes.
        -:   35:
        -:   36:   A user-defined error code has the following format.  The ERROR_xxx
        -:   37:   is the macro that may be used to extract the data (usually a MASK and
        -:   38:   a (right)shift)
        -:   39:
        -:   40:   [0-6] Class (same as predefined error classes);  ERROR_CLASS_MASK
        -:   41:   [7]   Is dynamic; ERROR_DYN_MASK and ERROR_DYN_SHIFT
        -:   42:   [8-18] Code index (for messages); ERROR_GENERIC_MASK and ERROR_GENERIC_SHIFT
        -:   43:   [19-31] Zero (unused but defined as zero)
        -:   44:*/
        -:   45:
        -:   46:static int  not_initialized = 1;  /* This allows us to use atomic decr */
        -:   47:static const char *(user_class_msgs[ERROR_MAX_NCLASS]) = { 0 };
        -:   48:static const char *(user_code_msgs[ERROR_MAX_NCODE]) = { 0 };
        -:   49:static int  first_free_class = 0;
        -:   50:static int  first_free_code  = 1;  /* code 0 is reserved */
        -:   51:
        -:   52:/* Forward reference */
        -:   53:const char *MPIR_Err_get_dynerr_string( int code );
        -:   54:
        -:   55:/* This external allows this package to define the routine that converts
        -:   56:   dynamically assigned codes and classes to their corresponding strings. 
        -:   57:   A cleaner implementation could replace this exposed global with a method
        -:   58:   defined in the error_string.c file that allowed this package to set 
        -:   59:   the routine. */
        -:   60:
        -:   61:static int MPIR_Dynerrcodes_finalize( void * );
        -:   62:
        -:   63:/* Local routine to initialize the data structures for the dynamic
        -:   64:   error classes and codes.
        -:   65:
        -:   66:   MPIR_Init_err_dyncodes is called if not_initialized is true.  
        -:   67:   Because all of the routines in this file are called by the 
        -:   68:   MPI_Add_error_xxx routines, and those routines use the SINGLE_CS
        -:   69:   when the implementation is multithreaded, these routines (until 
        -:   70:   we implement finer-grain thread-synchronization) need not worry about
        -:   71:   multiple threads
        -:   72: */
        -:   73:static void MPIR_Init_err_dyncodes( void )
       12:   74:{
        -:   75:    int i;
        -:   76:
        -:   77:    /* FIXME: Does this need a thread-safe init? */
       12:   78:    not_initialized = 0;
        -:   79:    
     1548:   80:    for (i=0; i<ERROR_MAX_NCLASS; i++) {
     1536:   81:	user_class_msgs[i] = 0;
        -:   82:    }
    98316:   83:    for (i=0; i<ERROR_MAX_NCODE; i++) {
    98304:   84:	user_code_msgs[i] = 0;
        -:   85:    }
        -:   86:    /* Set the routine to provides access to the dynamically created
        -:   87:       error strings */
       12:   88:    MPIR_Process.errcode_to_string = MPIR_Err_get_dynerr_string;
        -:   89:
        -:   90:    /* Add a finalize handler to free any allocated space */
       12:   91:    MPIR_Add_finalize( MPIR_Dynerrcodes_finalize, (void*)0, 9 );
       12:   92:}
        -:   93:
        -:   94:/*
        -:   95:  MPIR_Err_set_msg - Change the message for an error code or class
        -:   96:
        -:   97:  Input Parameter:
        -:   98:+ code - Error code or class
        -:   99:- msg  - New message to use
        -:  100:
        -:  101:  Notes:
        -:  102:  This routine is needed to implement 'MPI_Add_error_string'.
        -:  103:*/
        -:  104:int MPIR_Err_set_msg( int code, const char *msg_string )
      187:  105:{
        -:  106:    int errcode, errclass;
        -:  107:    size_t msg_len;
        -:  108:    char *str;
        -:  109:    static const char FCNAME[] = "MPIR_Err_set_msg";
        -:  110:
        -:  111:    /* --BEGIN ERROR HANDLING-- */
      187:  112:    if (not_initialized) {
        -:  113:	/* Just to keep the rest of the code more robust, we'll 
        -:  114:	   initialize the dynamic error codes *anyway*, but this is 
        -:  115:	   an error (see MPI_Add_error_string in the standard) */
    #####:  116:	MPIR_Init_err_dyncodes();
    #####:  117:	return MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, 
        -:  118:				     "MPIR_Err_set_msg", __LINE__, 
        -:  119:				     MPI_ERR_ARG, "**argerrcode", 
        -:  120:				     "**argerrcode %d", code );
        -:  121:    }
        -:  122:    /* --END ERROR HANDLING-- */
        -:  123:    
        -:  124:    /* Error strings are attached to a particular error code, not class.
        -:  125:       As a special case, if the code is 0, we use the class message */
      187:  126:    errclass = code & ERROR_CLASS_MASK;
      187:  127:    errcode  = (code & ERROR_GENERIC_MASK) >> ERROR_GENERIC_SHIFT;
        -:  128:
        -:  129:    /* --BEGIN ERROR HANDLING-- */
      187:  130:    if (code & ~(ERROR_CLASS_MASK | ERROR_DYN_MASK | ERROR_GENERIC_MASK)) {
        -:  131:	/* Check for invalid error code */
    #####:  132:	return MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, 
        -:  133:				     FCNAME, __LINE__, 
        -:  134:				     MPI_ERR_ARG, "**argerrcode", 
        -:  135:				     "**argerrcode %d", code );
        -:  136:    }
        -:  137:    /* --END ERROR HANDLING-- */
        -:  138:
        -:  139:    /* --------------------------------------------------------------------- */
      187:  140:    msg_len = strlen( msg_string );
      187:  141:    str = (char *)MPIU_Malloc( msg_len + 1 );
        -:  142:    /* --BEGIN ERROR HANDLING-- */
      187:  143:    if (!str) {
    #####:  144:	return MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
        -:  145:				     FCNAME, __LINE__, MPI_ERR_OTHER, 
        -:  146:				     "**nomem", "**nomem %s %d", 
        -:  147:				     "error message string", msg_len );
        -:  148:    }
        -:  149:    /* --END ERROR HANDLING-- */
        -:  150:
        -:  151:    /* --------------------------------------------------------------------- */
      187:  152:    MPIU_Strncpy( str, msg_string, msg_len + 1 );
      187:  153:    if (errcode) {
      178:  154:	if (errcode < first_free_code) {
      178:  155:	    if (user_code_msgs[errcode]) {
    #####:  156:		MPIU_Free( (void*)(user_code_msgs[errcode]) );
        -:  157:	    }
      178:  158:	    user_code_msgs[errcode] = (const char *)str;
        -:  159:	}
        -:  160:	else {
        -:  161:	    /* FIXME : Unallocated error code? */
    #####:  162:	    MPIU_Free( str );
        -:  163:	}
        -:  164:    }
        -:  165:    else {
        9:  166:	if (errclass < first_free_class) {
        9:  167:	    if (user_class_msgs[errclass]) {
    #####:  168:		MPIU_Free( (void*)(user_class_msgs[errclass]) );
        -:  169:	    }
        9:  170:	    user_class_msgs[errclass] = (const char *)str;
        -:  171:	}
        -:  172:	else {
        -:  173:	    /* FIXME : Unallocated error code? */
    #####:  174:	    MPIU_Free( str );
        -:  175:	}
        -:  176:    }
        -:  177:       
      187:  178:    return MPI_SUCCESS;
        -:  179:}
        -:  180:
        -:  181:/*
        -:  182:  MPIR_Err_add_class - Creata a new error class
        -:  183:
        -:  184:  Return value:
        -:  185:  An error class.  Returns -1 if no more classes are available.
        -:  186:
        -:  187:  Notes:
        -:  188:  This is used to implement 'MPI_Add_error_class'; it may also be used by a 
        -:  189:  device to add device-specific error classes.  
        -:  190:
        -:  191:  Predefined classes are handled directly; this routine is not used to 
        -:  192:  initialize the predefined MPI error classes.  This is done to reduce the
        -:  193:  number of steps that must be executed when starting an MPI program.
        -:  194:
        -:  195:  This routine should be run within a SINGLE_CS in the multithreaded case.
        -:  196:*/
        -:  197:int MPIR_Err_add_class(void)
       45:  198:{
        -:  199:    int new_class;
        -:  200:
       45:  201:    if (not_initialized)
       12:  202:	MPIR_Init_err_dyncodes();
        -:  203:	
        -:  204:    /* Get new class */
       45:  205:    MPIR_Fetch_and_increment( &first_free_class, &new_class );
        -:  206:
        -:  207:    /* --BEGIN ERROR HANDLING-- */
       45:  208:    if (new_class >= ERROR_MAX_NCLASS) {
        -:  209:	/* Fail if out of classes */
    #####:  210:	return -1;
        -:  211:    }
        -:  212:    /* --END ERROR HANDLING-- */
        -:  213:
        -:  214:    /* Note that the MPI interface always adds an error class without
        -:  215:       a string.  */
       45:  216:    user_class_msgs[new_class] = 0;
        -:  217:
       45:  218:    return (new_class | ERROR_DYN_MASK);
        -:  219:}
        -:  220:
        -:  221:/*
        -:  222:  MPIR_Err_add_code - Create a new error code that is associated with an 
        -:  223:  existing error class
        -:  224:
        -:  225:  Input Parameters:
        -:  226:. class - Error class to which the code belongs.
        -:  227:
        -:  228:  Return value:
        -:  229:  An error code.
        -:  230:
        -:  231:  Notes:
        -:  232:  This is used to implement 'MPI_Add_error_code'; it may also be used by a 
        -:  233:  device to add device-specific error codes.  
        -:  234:
        -:  235:  */
        -:  236:int MPIR_Err_add_code( int class )
      178:  237:{
        -:  238:    int new_code;
        -:  239:
        -:  240:    /* Note that we can add codes to existing classes, so we may
        -:  241:       need to initialize the dynamic error routines in this function */
      178:  242:    if (not_initialized)
    #####:  243:	MPIR_Init_err_dyncodes();
        -:  244:
        -:  245:    /* Get the new code */
      178:  246:    MPIR_Fetch_and_increment( &first_free_code, &new_code );
        -:  247:    /* --BEGIN ERROR HANDLING-- */
      178:  248:    if (new_code >= ERROR_MAX_NCODE) {
        -:  249:	/* Fail if out of codes */
    #####:  250:	return -1;
        -:  251:    }
        -:  252:    /* --END ERROR HANDLING-- */
        -:  253:
        -:  254:    /* Create the full error code */
      178:  255:    new_code = class | ERROR_DYN_MASK | (new_code << ERROR_GENERIC_SHIFT);
        -:  256:
        -:  257:    /* FIXME: For robustness, we should make sure that the associated string
        -:  258:       is initialized to null */
      178:  259:    return new_code;
        -:  260:}
        -:  261:
        -:  262:/*
        -:  263:  MPIR_Err_get_dynerr_string - Get the message string that corresponds to a
        -:  264:  dynamically created error class or code
        -:  265:
        -:  266:  Input Parameter:
        -:  267:+ code - An error class or code.  If a code, it must have been created by 
        -:  268:  'MPIR_Err_create_code'.
        -:  269:
        -:  270:  Return value:
        -:  271:  A pointer to a null-terminated text string with the corresponding error 
        -:  272:  message.  A null return indicates an error; usually the value of 'code' is 
        -:  273:  neither a valid error class or code.
        -:  274:
        -:  275:  Notes:
        -:  276:  This routine is used to implement 'MPI_ERROR_STRING'.  It is only called
        -:  277:  for dynamic error codes.  
        -:  278:  */
        -:  279:const char *MPIR_Err_get_dynerr_string( int code )
      199:  280:{
        -:  281:    int errcode, errclass;
      199:  282:    const char *errstr = 0;
        -:  283:
        -:  284:    /* Error strings are attached to a particular error code, not class.
        -:  285:       As a special case, if the code is 0, we use the class message */
      199:  286:    errclass = code & ERROR_CLASS_MASK;
      199:  287:    errcode  = (code & ERROR_GENERIC_MASK) >> ERROR_GENERIC_SHIFT;
        -:  288:
      199:  289:    if (code & ~(ERROR_CLASS_MASK | ERROR_DYN_MASK | ERROR_GENERIC_MASK)) {
        -:  290:	/* Check for invalid error code */
    #####:  291:	return 0;
        -:  292:    }
        -:  293:
      199:  294:    if (errcode) {
      185:  295:	if (errcode < first_free_code) {
      185:  296:	    errstr = user_code_msgs[errcode];
        -:  297:	}
        -:  298:    }
        -:  299:    else {
       14:  300:	if (errclass < first_free_class) {
       14:  301:	    errstr = user_class_msgs[errclass];
        -:  302:	}
        -:  303:    }
        -:  304:       
      199:  305:    return errstr;
        -:  306:}
        -:  307:
        -:  308:
        -:  309:static int MPIR_Dynerrcodes_finalize( void *p ATTRIBUTE((unused)) )
       11:  310:{
        -:  311:    int i;
        -:  312:
        -:  313:    MPIU_UNREFERENCED_ARG(p);
        -:  314:
       11:  315:    if (not_initialized == 0) {
        -:  316:
       55:  317:        for (i=0; i<first_free_class; i++) {
       44:  318:            if (user_class_msgs[i])
        9:  319:                MPIU_Free((char *) user_class_msgs[i]);
        -:  320:        }
        -:  321:
      199:  322:        for (i=0; i<first_free_code; i++) {
      188:  323:            if (user_code_msgs[i])
      177:  324:                MPIU_Free((char *) user_code_msgs[i]);
        -:  325:        }
        -:  326:    }
       11:  327:    return 0;
        -:  328:}