-: 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:}
|