/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ /* * (C) 2001 by Argonne National Laboratory. * See COPYRIGHT in top-level directory. */ #include "mpiimpl.h" MPL_SUPPRESS_OSX_HAS_NO_SYMBOLS_WARNING; #ifdef USE_MPIU_INSTR static int MPIU_INSTR_Printf( FILE *fp ); static int MPIU_INSTR_Finalize( void *p ); /* */ /* * Basic but general support for instrumentation hooks in MPICH * * Most actions are handled by MPIU_INSTR_xxx macros (to permit both lowest * overhead and to allow instrumentation to be selected at compile time. */ static struct MPIU_INSTR_Generic_t *instrHead = 0, *instrTail = 0; int MPIU_INSTR_AddHandle( void *handlePtr ) { struct MPIU_INSTR_Generic_t *gPtr = (struct MPIU_INSTR_Generic_t *)handlePtr; /* Note that Addhandle must be within a thread-safe initialization */ if (!instrHead) { /* Make sure that this call back occurs early (before MPID_Finalize) */ MPIR_Add_finalize( MPIU_INSTR_Finalize, stdout, MPIR_FINALIZE_CALLBACK_PRIO + 2 ); } if (instrHead) { instrTail->next = gPtr; } else { instrHead = gPtr; } instrTail = gPtr; return 0; } #define MAX_INSTR_BUF 1024 static int MPIU_INSTR_Printf( FILE *fp ) { struct MPIU_INSTR_Generic_t *gPtr = instrHead; char instrBuf[MAX_INSTR_BUF]; while (gPtr) { /* We only output information on events that occured */ if (gPtr->count) { if (gPtr->toStr) { (*gPtr->toStr)( instrBuf, sizeof(instrBuf), gPtr ); } else { if (gPtr->desc) { MPIU_Strncpy( instrBuf, gPtr->desc, sizeof(instrBuf) ); } else { /* This should not happen */ MPIU_Strncpy( instrBuf, "", sizeof(instrBuf) ); } } fputs( instrBuf, fp ); fputc( '\n', fp ); } gPtr = gPtr->next; } fflush( fp ); return 0; } static int MPIU_INSTR_Finalize( void *p ) { int rc; struct MPIU_INSTR_Generic_t *gPtr = instrHead; /* FIXME: This should at least issue the writes in process order */ /* Allow whether output is generated to be controlled */ if (!MPL_env2bool( "MPICH_INSTR_AT_FINALIZE", &rc )) rc = 0; if (rc) { MPIU_INSTR_Printf( stdout ); } /* Free any memory allocated for the descriptions */ while (gPtr) { if (gPtr->desc) { MPIU_Free( (char *)gPtr->desc ); gPtr->desc = 0; } gPtr = gPtr->next; } return 0; } /* * Standard print routines for the instrumentation objects */ /* * Print a duration, which may have extra integer fields. Those fields * are printed as integers, in order, separate by tabs */ int MPIU_INSTR_ToStr_Duration_Count( char *buf, size_t maxBuf, void *ptr ) { double ttime; struct MPIU_INSTR_Duration_count_t *dPtr = (struct MPIU_INSTR_Duration_count_t *)ptr; MPID_Wtime_todouble( &dPtr->ttime, &ttime ); snprintf( buf, maxBuf, "%-40s:\t%d\t%e", dPtr->desc, dPtr->count, ttime ); if (dPtr->nitems) { char *p; size_t len = strlen(buf); int i; /* Add each integer value, separated by a tab. */ maxBuf -= len; p = buf + len; for (i=0; initems; i++) { snprintf( p, maxBuf, "\t%d", dPtr->data[i] ); len = strlen(p); maxBuf -= len; p += len; } } return 0; } /* Print the max counter value and the total counter value. */ int MPIU_INSTR_ToStr_Counter( char * buf, size_t maxBuf, void *ptr ) { struct MPIU_INSTR_Counter_t *dPtr = (struct MPIU_INSTR_Counter_t *)ptr; snprintf( buf, maxBuf, "%-40s:\t%d\t%d", dPtr->desc, dPtr->maxcount, dPtr->totalcount ); return 0; } #else /* No routines required if instrumentation is not selected */ #endif