-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpi/init/finalize.c
        -:    0:Graph:finalize.gcno
        -:    0:Data:finalize.gcda
        -:    0:Runs:4382
        -:    0:Programs:1376
        -:    1:/* -*- Mode: C; c-basic-offset:4 ; -*- */
        -:    2:/*
        -:    3: *  (C) 2001 by Argonne National Laboratory.
        -:    4: *      See COPYRIGHT in top-level directory.
        -:    5: */
        -:    6:/* style: allow:fprintf:1 sig:0 */
        -:    7:
        -:    8:#include "mpiimpl.h"
        -:    9:#include "mpi_init.h"
        -:   10:
        -:   11:/* -- Begin Profiling Symbol Block for routine MPI_Finalize */
        -:   12:#if defined(HAVE_PRAGMA_WEAK)
        -:   13:#pragma weak MPI_Finalize = PMPI_Finalize
        -:   14:#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
        -:   15:#pragma _HP_SECONDARY_DEF PMPI_Finalize  MPI_Finalize
        -:   16:#elif defined(HAVE_PRAGMA_CRI_DUP)
        -:   17:#pragma _CRI duplicate MPI_Finalize as PMPI_Finalize
        -:   18:#endif
        -:   19:/* -- End Profiling Symbol Block */
        -:   20:
        -:   21:/* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
        -:   22:   the MPI routines */
        -:   23:#ifndef MPICH_MPI_FROM_PMPI
        -:   24:#undef MPI_Finalize
        -:   25:#define MPI_Finalize PMPI_Finalize
        -:   26:
        -:   27:/* Any internal routines can go here.  Make them static if possible */
        -:   28:
        -:   29:/* The following routines provide a callback facility for modules that need 
        -:   30:   some code called on exit.  This method allows us to avoid forcing 
        -:   31:   MPI_Finalize to know the routine names a priori.  Any module that wants to 
        -:   32:   have a callback calls MPIR_Add_finalize( routine, extra, priority ).
        -:   33:   
        -:   34: */
        -:   35:PMPI_LOCAL void MPIR_Call_finalize_callbacks( int, int );
        -:   36:typedef struct Finalize_func_t {
        -:   37:    int (*f)( void * );      /* The function to call */
        -:   38:    void *extra_data;        /* Data for the function */
        -:   39:    int  priority;           /* priority is used to control the order
        -:   40:				in which the callbacks are invoked */
        -:   41:} Finalize_func_t;
        -:   42:/* When full debugging is enabled, each MPI handle type has a finalize handler
        -:   43:   installed to detect unfreed handles.  */
        -:   44:#define MAX_FINALIZE_FUNC 32
        -:   45:static Finalize_func_t fstack[MAX_FINALIZE_FUNC];
        -:   46:static int fstack_sp = 0;
        -:   47:static int fstack_max_priority = 0;
        -:   48:
        -:   49:void MPIR_Add_finalize( int (*f)( void * ), void *extra_data, int priority )
    20571:   50:{
        -:   51:    /* --BEGIN ERROR HANDLING-- */
    20571:   52:    if (fstack_sp >= MAX_FINALIZE_FUNC) {
        -:   53:	/* This is a little tricky.  We may want to check the state of
        -:   54:	   MPIR_Process.initialized to decide how to signal the error */
    #####:   55:	(void)MPIU_Internal_error_printf( "overflow in finalize stack!\n" );
    #####:   56:	if (MPIR_Process.initialized == MPICH_WITHIN_MPI) {
    #####:   57:	    MPID_Abort( NULL, MPI_SUCCESS, 13, NULL );
        -:   58:	}
        -:   59:	else {
    #####:   60:	    exit(1);
        -:   61:	}
        -:   62:    }
        -:   63:    /* --END ERROR HANDLING-- */
    20571:   64:    fstack[fstack_sp].f            = f;
    20571:   65:    fstack[fstack_sp].priority     = priority;
    20571:   66:    fstack[fstack_sp++].extra_data = extra_data;
        -:   67:
    20571:   68:    if (priority > fstack_max_priority) 
     4572:   69:	fstack_max_priority = priority;
    20571:   70:}
        -:   71:
        -:   72:/* Invoke the registered callbacks */
        -:   73:PMPI_LOCAL void MPIR_Call_finalize_callbacks( int min_prio, int max_prio )
     8748:   74:{
        -:   75:    int i, j;
        -:   76:
     8748:   77:    if (max_prio > fstack_max_priority) max_prio = fstack_max_priority;
    31542:   78:    for (j=max_prio; j>=min_prio; j--) {
   130404:   79:	for (i=fstack_sp-1; i>=0; i--) {
   107610:   80:	    if (fstack[i].f && fstack[i].priority == j) {
    20540:   81:		fstack[i].f( fstack[i].extra_data );
    20540:   82:		fstack[i].f = 0;
        -:   83:	    }
        -:   84:	}
        -:   85:    }
     8748:   86:}
        -:   87:#else
        -:   88:#ifndef USE_WEAK_SYMBOLS
        -:   89:PMPI_LOCAL void MPIR_Call_finalize_callbacks( int, int );
        -:   90:#endif
        -:   91:#endif
        -:   92:
        -:   93:#undef FUNCNAME
        -:   94:#define FUNCNAME MPI_Finalize
        -:   95:
        -:   96:/*@
        -:   97:   MPI_Finalize - Terminates MPI execution environment
        -:   98:
        -:   99:   Notes:
        -:  100:   All processes must call this routine before exiting.  The number of
        -:  101:   processes running `after` this routine is called is undefined; 
        -:  102:   it is best not to perform much more than a 'return rc' after calling
        -:  103:   'MPI_Finalize'.
        -:  104:
        -:  105:Thread and Signal Safety:
        -:  106:The MPI standard requires that 'MPI_Finalize' be called `only` by the same 
        -:  107:thread that initialized MPI with either 'MPI_Init' or 'MPI_Init_thread'.
        -:  108:
        -:  109:.N Fortran
        -:  110:
        -:  111:.N Errors
        -:  112:.N MPI_SUCCESS
        -:  113:@*/
        -:  114:int MPI_Finalize( void )
     4374:  115:{
        -:  116:    static const char FCNAME[] = "MPI_Finalize";
     4374:  117:    int mpi_errno = MPI_SUCCESS;
        -:  118:#if defined(HAVE_USLEEP) && defined(USE_COVERAGE)
     4374:  119:    int rank=0;
        -:  120:#endif
     4374:  121:    MPIU_THREADPRIV_DECL;
        -:  122:    MPID_MPI_FINALIZE_STATE_DECL(MPID_STATE_MPI_FINALIZE);
        -:  123:
     4374:  124:    MPIR_ERRTEST_INITIALIZED_ORDIE();
        -:  125:
        -:  126:    /* Note: Only one thread may ever call MPI_Finalize (MPI_Finalize may
        -:  127:       be called at most once in any program) */
     4374:  128:    MPIU_THREAD_CS_ENTER(ALLFUNC,);
        -:  129:    MPID_MPI_FINALIZE_FUNC_ENTER(MPID_STATE_MPI_FINALIZE);
        -:  130:    
        -:  131:    /* ... body of routine ... */
        -:  132:
        -:  133:    /* If the user requested for asynchronous progress, we need to
        -:  134:     * shutdown the progress thread */
     4374:  135:    if (MPIR_async_thread_initialized) {
    #####:  136:        mpi_errno = MPIR_Finalize_async_thread();
    #####:  137:        if (mpi_errno) goto fn_fail;
        -:  138:    }
        -:  139:    
        -:  140:#if defined(HAVE_USLEEP) && defined(USE_COVERAGE)
        -:  141:    /* We need to get the rank before freeing MPI_COMM_WORLD */
     4374:  142:    rank = MPIR_Process.comm_world->rank;
        -:  143:#endif    
        -:  144:
        -:  145:    /* Remove the attributes, executing the attribute delete routine.
        -:  146:       Do this only if the attribute functions are defined. */ 
        -:  147:    /* The standard (MPI-2, section 4.8) says that the attributes on 
        -:  148:       MPI_COMM_SELF are deleted before almost anything else happens */
        -:  149:    /* Note that the attributes need to be removed from the communicators 
        -:  150:       so that they aren't freed twice. (The communicators are released
        -:  151:       in MPID_Finalize) */
     4374:  152:    if (MPIR_Process.attr_free && MPIR_Process.comm_self->attributes) {
      237:  153:        mpi_errno = MPIR_Process.attr_free( MPI_COMM_SELF,
        -:  154:					    &MPIR_Process.comm_self->attributes);
      237:  155:	MPIR_Process.comm_self->attributes = 0;
        -:  156:    }
     4374:  157:    if (MPIR_Process.attr_free && MPIR_Process.comm_world->attributes) {
      201:  158:        mpi_errno = MPIR_Process.attr_free( MPI_COMM_WORLD, 
        -:  159:                                            &MPIR_Process.comm_world->attributes);
      201:  160:	MPIR_Process.comm_world->attributes = 0;
        -:  161:    }
        -:  162:
        -:  163:    /* 
        -:  164:     * Now that we're finalizing, we need to take control of the error handlers
        -:  165:     * At this point, we will release any user-defined error handlers on 
        -:  166:     * comm self and comm world
        -:  167:     */
     4374:  168:    if (MPIR_Process.comm_world->errhandler && 
        -:  169:	! (HANDLE_GET_KIND(MPIR_Process.comm_world->errhandler->handle) == 
        -:  170:	   HANDLE_KIND_BUILTIN) ) {
        -:  171:	int in_use;
       11:  172:	MPIR_Errhandler_release_ref( MPIR_Process.comm_world->errhandler,
        -:  173:				     &in_use);
       11:  174:	if (!in_use) {
        5:  175:	    MPIU_Handle_obj_free( &MPID_Errhandler_mem, 
        -:  176:				  MPIR_Process.comm_world->errhandler );
        5:  177:            MPIR_Process.comm_world->errhandler = NULL;
        -:  178:	}
        -:  179:    }
     4374:  180:    if (MPIR_Process.comm_self->errhandler && 
        -:  181:	! (HANDLE_GET_KIND(MPIR_Process.comm_self->errhandler->handle) == 
        -:  182:	   HANDLE_KIND_BUILTIN) ) {
        -:  183:	int in_use;
    #####:  184:	MPIR_Errhandler_release_ref( MPIR_Process.comm_self->errhandler,
        -:  185:				     &in_use);
    #####:  186:	if (!in_use) {
    #####:  187:	    MPIU_Handle_obj_free( &MPID_Errhandler_mem, 
        -:  188:				  MPIR_Process.comm_self->errhandler );
    #####:  189:            MPIR_Process.comm_self->errhandler = NULL;
        -:  190:	}
        -:  191:    }
        -:  192:
        -:  193:    /* FIXME: Why is this not one of the finalize callbacks?.  Do we need
        -:  194:       pre and post MPID_Finalize callbacks? */
        -:  195:    MPIU_Timer_finalize();
        -:  196:
        -:  197:    /* Call the high-priority callbacks */
     4374:  198:    MPIR_Call_finalize_callbacks( MPIR_FINALIZE_CALLBACK_PRIO+1, 
        -:  199:				  MPIR_FINALIZE_CALLBACK_MAX_PRIO );
        -:  200:
        -:  201:    /* Signal the debugger that we are about to exit. */
        -:  202:    /* FIXME: Should this also be a finalize callback? */
        -:  203:#ifdef HAVE_DEBUGGER_SUPPORT
        -:  204:    MPIR_DebuggerSetAborting( (char *)0 );
        -:  205:#endif
        -:  206:
     4374:  207:    mpi_errno = MPID_Finalize();
     4374:  208:    if (mpi_errno) {
    #####:  209:	MPIU_ERR_POP(mpi_errno);
        -:  210:    }
        -:  211:    
        -:  212:    /* Call the low-priority (post Finalize) callbacks */
     4374:  213:    MPIR_Call_finalize_callbacks( 0, MPIR_FINALIZE_CALLBACK_PRIO-1 );
        -:  214:
        -:  215:    /* At this point, if there has been a failure, exit before 
        -:  216:       completing the finalize */
     4374:  217:    if (mpi_errno != MPI_SUCCESS) goto fn_fail;
        -:  218:
        -:  219:    /* FIXME: Many of these debugging items could/should be callbacks, 
        -:  220:       added to the finalize callback list */
        -:  221:    /* FIXME: Both the memory tracing and debug nesting code blocks should
        -:  222:       be finalize callbacks */
        -:  223:    /* If memory debugging is enabled, check the memory here, after all
        -:  224:       finalize callbacks */
        -:  225:#ifdef MPICH_DEBUG_NESTING
        -:  226:    {
        -:  227:	int parmFound, parmValue;
        -:  228:
        -:  229:	MPIU_Param_register( "nestcheck", "NESTCHECK", 
        -:  230:	     "List any memory that was allocated by MPICH2 and that remains allocated when MPI_Finalize completes" );
        -:  231:	parmFound = MPIU_GetEnvBool( "MPICH_NESTCHECK", &parmValue );
        -:  232:	if (!parmFound) parmValue = 1;
        -:  233:	if (parmValue) {
        -:  234:	    MPIU_THREADPRIV_GET;
        -:  235:	    /* Check for an error in the nesting level */
        -:  236:	    if (MPIR_Nest_value()) {
        -:  237:		int i,n;
        -:  238:		n = MPIR_Nest_value();
        -:  239:		fprintf( stderr, "Unexpected value for nesting level = %d\n", n );
        -:  240:		fprintf( stderr, "Nest stack is:\n" );
        -:  241:		for (i=n-1; i>=0; i--) {
        -:  242:		    fprintf( stderr, "\t[%d] %s:%d\n", i, 
        -:  243:			     MPIU_THREADPRIV_FIELD(nestinfo[i].file), 
        -:  244:			     MPIU_THREADPRIV_FIELD(nestinfo[i].line) );
        -:  245:		}
        -:  246:	    }
        -:  247:	}
        -:  248:    }
        -:  249:#endif
        -:  250:
     4374:  251:    MPIU_THREAD_CS_EXIT(ALLFUNC,);
     4374:  252:    MPIR_Process.initialized = MPICH_POST_FINALIZED;
        -:  253:
     4374:  254:    MPID_CS_FINALIZE();
        -:  255:
        -:  256:    /* We place the memory tracing at the very end because any of the other
        -:  257:       steps may have allocated memory that they still need to release*/
        -:  258:#ifdef USE_MEMORY_TRACING
        -:  259:    /* FIXME: We'd like to arrange for the mem dump output to
        -:  260:       go to separate files or to be sorted by rank (note that
        -:  261:       the rank is at the head of the line) */
        -:  262:    {
        -:  263:	int parmFound, parmValue;
        -:  264:	/* The Param_register is used to document the parameters.  A 
        -:  265:	   script will extract the information about these parameters,
        -:  266:	   allowing the documentation to stay up-to-date with the use of the
        -:  267:	   parameters (this script is still to be written) */
        -:  268:	MPIU_Param_register( "memdump", "MEMDUMP", 
        -:  269:	     "List any memory that was allocated by MPICH2 and that remains allocated when MPI_Finalize completes" );
        -:  270:	parmFound = MPIU_GetEnvBool( "MPICH_MEMDUMP", &parmValue );
        -:  271:	if (!parmFound) parmValue = 1;
        -:  272:	if (parmValue) {
        -:  273:	    /* The second argument is the min id to print; memory allocated 
        -:  274:	       after MPI_Init is given an id of one.  This allows us to
        -:  275:	       ignore, if desired, memory leaks in the MPID_Init call */
        -:  276:	    MPIU_trdump( (void *)0, -1 );
        -:  277:	}
        -:  278:    }
        -:  279:#endif
        -:  280:
        -:  281:#if defined(HAVE_USLEEP) && defined(USE_COVERAGE)
        -:  282:    /* If performing coverage analysis, make each process sleep for
        -:  283:       rank * 100 ms, to give time for the coverage tool to write out
        -:  284:       any files.  It would be better if the coverage tool and runtime 
        -:  285:       was more careful about file updates, though the lack of OS support
        -:  286:       for atomic file updates makes this harder. */
        -:  287:    /* 
        -:  288:       On some systems, a 0.1 second delay appears to be too short for 
        -:  289:       the file system.  This code allows the use of the environment
        -:  290:       variable MPICH_FINALDELAY, which is the delay in milliseconds.
        -:  291:       It must be an integer value.
        -:  292:     */
        -:  293:    {
     4374:  294:	int microseconds = 100000;
     4374:  295:	char *delayStr = getenv( "MPICH_FINALDELAY" );
     4374:  296:	if (delayStr) {
        -:  297:	    /* Because this is a maintainer item, we won't check for 
        -:  298:	       errors in the delayStr */
    #####:  299:	    microseconds = 1000 * atoi( delayStr );
        -:  300:	}
     4374:  301:	usleep( rank * microseconds );
        -:  302:    }
        -:  303:#endif
        -:  304:
        -:  305:    /* ... end of body of routine ... */
        -:  306:
     4374:  307:  fn_exit:
        -:  308:    MPID_MPI_FINALIZE_FUNC_EXIT(MPID_STATE_MPI_FINALIZE);
     4374:  309:    return mpi_errno;
        -:  310:
    #####:  311:  fn_fail:
        -:  312:    /* --BEGIN ERROR HANDLING-- */
        -:  313:#   ifdef HAVE_ERROR_CHECKING
        -:  314:    {
    #####:  315:	mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, 
        -:  316:			FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_finalize", 0);
        -:  317:    }
        -:  318:#   endif
    #####:  319:    mpi_errno = MPIR_Err_return_comm( 0, FCNAME, mpi_errno );
    #####:  320:    if (MPIR_Process.initialized < MPICH_POST_FINALIZED) {
    #####:  321:        MPIU_THREAD_CS_EXIT(ALLFUNC,);
        -:  322:    }
        -:  323:    goto fn_exit;
        -:  324:    /* --END ERROR HANDLING-- */
        -:  325:}