mirror of
https://github.com/HDFGroup/hdf5.git
synced 2024-11-27 02:10:55 +08:00
830 lines
34 KiB
C
830 lines
34 KiB
C
/*
|
|
* This file is an extension to NCSA HDF to enable the use of the
|
|
* Pablo trace library.
|
|
*
|
|
* Developed by: The TAPESTRY Parallel Computing Laboratory
|
|
* University of Illinois at Urbana-Champaign
|
|
* Department of Computer Science
|
|
* 1304 W. Springfield Avenue
|
|
* Urbana, IL 61801
|
|
*
|
|
* Copyright (c) 1995
|
|
* The University of Illinois Board of Trustees.
|
|
* All Rights Reserved.
|
|
*
|
|
* PABLO is a registered trademark of
|
|
* The Board of Trustees of the University of Illinois
|
|
* registered in the U.S. Patent and Trademark Office.
|
|
*
|
|
* Author: George Xin Zhou (xzhou@cs.uiuc.edu)
|
|
* Contributing Author: Jonathan M. Reid (jreid@cs.uiuc.edu)
|
|
*
|
|
* Project Manager and Principal Investigator:
|
|
* Daniel A. Reed (reed@cs.uiuc.edu)
|
|
*
|
|
* Funded by: National Aeronautics and Space Administration under NASA
|
|
* Contracts NAG-1-613 and USRA 5555-22 and by the Advanced Research
|
|
* Projects Agency under ARPA contracts DAVT63-91-C-0029 and
|
|
* DABT63-93-C-0040.
|
|
*
|
|
*/
|
|
/*======================================================================*
|
|
// File: PabloHDF_SDDF.c *
|
|
// Purpose: support use of Pablo trace library to analyze HDF *
|
|
// performance *
|
|
// Contents: *
|
|
// HDFinitTrace_SDDF: initialize SDDF tracing *
|
|
// HDFendTrace_SDDF: end SDDF tracing *
|
|
// startHDFtraceEvent: record start of HDF procedure *
|
|
// endHDFtraceEvent: record end of HDF proc *
|
|
// preInitHDFProcTrace: called by HDFinitTrace_SDDF to set up SDDF *
|
|
// interface function calls *
|
|
// initHDFProcTrace: called by HDFinitTrace_SDDF to initialize data *
|
|
// structures used in tracing HDF procedures. *
|
|
// writeHDFProcRecordDescriptors: *
|
|
// generates the record descriptors for the HDF *
|
|
// procedure entry/exit event families. *
|
|
// HDFprocEventRecord: generates trace records for events which are *
|
|
// to produce procedure entry or exit event family *
|
|
// trace records. *
|
|
// findHDFProcEvent: retruns procedure entry/exit index *
|
|
// _hdfTraceEntryDescriptor: *
|
|
// Generate a SDDF binary format record descriptor *
|
|
// for HDF procedure entries *
|
|
// _hdfTraceExitDescriptor: *
|
|
// Generate a SDDF binary format record descriptor *
|
|
// for the HDF procedure exits *
|
|
//======================================================================*/
|
|
#include <stdio.h>
|
|
|
|
#ifdef HAVE_PARALLEL
|
|
#include "mpi.h"
|
|
#endif
|
|
|
|
#include "H5config.h"
|
|
#undef HAVE_PABLO
|
|
#include "H5private.h"
|
|
#define HAVE_PABLO
|
|
#include "ProcIDs.h"
|
|
|
|
#include "SystemDepend.h"
|
|
#include "SDDFparam.h"
|
|
#include "TraceParam.h"
|
|
#include "Trace.h"
|
|
#include "HDFTrace.h"
|
|
void HDFendTrace_SDDF(int);
|
|
void startHDFtraceEvent(int eventID);
|
|
void endHDFtraceEvent(int , int , char *, int );
|
|
int preInitHDFProcTrace( void );
|
|
int initHDFProcTrace( int , int * );
|
|
int writeHDFProcRecordDescriptors( void );
|
|
int findHDFProcEvent( int ) ;
|
|
TR_RECORD *HDFprocEventRecord( int, TR_EVENT *, CLOCK, HDFsetInfo *, unsigned );
|
|
TR_RECORD *miscEventRecord( int , TR_EVENT *, CLOCK, void *, unsigned );
|
|
void _hdfMiscDescriptor( void );
|
|
void _hdfProcNameDescriptor( void );
|
|
/*int setEventRecordFunction( int, void *(*)() );*/
|
|
int setEventRecordFunction( int, TR_RECORD *(*)() );
|
|
void HDFtraceIOEvent( int, void *, unsigned );
|
|
void initIOTrace( void );
|
|
void enableIOdetail( void );
|
|
void disableLifetimeSummaries( void );
|
|
void disableTimeWindowSummaries( void );
|
|
void disableFileRegionSummaries( void );
|
|
void _hdfTraceDescriptor( char *, char *, int );
|
|
void createHDFTraceDescriptor( int );
|
|
void HDFfinalTimeStamp( void );
|
|
|
|
void initIOTrace( void );
|
|
void endIOTrace( void );
|
|
#define PABLO 1
|
|
/* on the ipsc/860 we don't include unistd.h */
|
|
#ifndef __NX
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#define returnRecord(x) return x;
|
|
|
|
#ifdef HAVE_MPIOTRACE
|
|
int initMPIOTrace( char *, int );
|
|
void endMPIOTrace( void ) ;
|
|
#else
|
|
void endMPIOTrace( void ) {return;}
|
|
#endif
|
|
extern char *hdfRecordPointer;
|
|
/*======================================================================*
|
|
// Prototypes of functions in this file. *
|
|
//======================================================================*/
|
|
void HDFinitTrace_SDDF( char *, int );
|
|
/*======================================================================*
|
|
// Each procedure being traced has associated with it a distinct pair *
|
|
// of entry and exit event IDs. This code maintains a vector of such *
|
|
// matchings which permits the ready identification of an event ID as *
|
|
// being either an entry event or an exit event and for which procedure.*
|
|
//======================================================================*/
|
|
typedef struct procEventMatch {
|
|
int entryID; /* procedure entry event ID */
|
|
int exitID; /* procedure exit event ID */
|
|
} PROC_EVENTS;
|
|
|
|
static PROC_EVENTS *procEvents = /* array of event ID pairs */
|
|
(PROC_EVENTS *) 0;
|
|
/*======================================================================*
|
|
// For each procedure being traced this code maintains a stack of *
|
|
// procedure entry times. Each procedure entry event causes the *
|
|
// corresponding procedure's stack to be pushed, each procedure exit *
|
|
// event causes the corresponding procedure's stack to be popped, and *
|
|
// from the difference in time between entry and exit the procedure *
|
|
// duration may be calculated in a very straightforward subtraction. *
|
|
// The above procedure entry-exit event ID matching is used to map *
|
|
// events to their corresponding procedures. In addition, the *
|
|
// cumulative total of these procedure durations is maintained for all *
|
|
// traced subprocedures of each traced procedure. That is, when a *
|
|
// traced procedure exits, it increases this duration sum for its most *
|
|
// immediate traced ancestor procedure. By subtracting this *
|
|
// subprocedure duration sum from the traced procedure's inclusive *
|
|
// duration, we arrive at the exclusive duration of the procedure. *
|
|
//======================================================================*/
|
|
typedef struct procEntryTime {
|
|
CLOCK entryTime; /* when proc entered */
|
|
CLOCK subProcTime; /* subproc duration */
|
|
struct procEntryTime *nextTime; /* stack pointer down */
|
|
struct procEntryTime *ancestorProc; /* traced ancestor */
|
|
} PROC_ENTRY;
|
|
|
|
/*
|
|
static PROC_ENTRY **procEntryStack =*/ /* array of pointers to */
|
|
/* (PROC_ENTRY **) 0;*/ /* stack top elements */
|
|
/*======================================================================*
|
|
// Define data structure types for procedure entry and exit trace *
|
|
// records, similarly to record data structures in Trace.h *
|
|
//======================================================================*/
|
|
|
|
/*======================================================================*
|
|
// TraceRecord Data packets: *
|
|
//======================================================================*/
|
|
struct procTraceRecordData {
|
|
int packetLength; /* bytes in packet */
|
|
int packetType; /* == PKT_DATA */
|
|
int packetTag; /* FAMILY_PROCEXIT | RECORD_TRACE */
|
|
int eventID; /* ID of corresponding event */
|
|
double seconds; /* floating-point timestamp */
|
|
long setID; /* index of file | Data Set accessed */
|
|
int nodeNumber; /* occurred on which node */
|
|
int nameLen; /* Length of file or data set name */
|
|
/* name comes next, but no space is allocated */
|
|
};
|
|
#define procTraceRecLen 6*sizeof(int) + sizeof(double) +sizeof(long)
|
|
/*======================================================================*
|
|
// misc Record Data packets: *
|
|
//======================================================================*/
|
|
struct miscTraceRecordData {
|
|
int packetLength; /* bytes in packet */
|
|
int packetType; /* == PKT_DATA */
|
|
int packetTag; /* FAMILY_MISC | RECORD_TRACE */
|
|
int eventID; /* ID of corresponding event */
|
|
double seconds; /* floating-point timestamp */
|
|
double duration; /* floating-point operation duration */
|
|
unsigned long bytes; /* number of bytes requested */
|
|
int nodeNumber; /* occurred on which node */
|
|
};
|
|
#define miscTraceLen 5*sizeof(int) + 2*sizeof(double) +sizeof(long)
|
|
/*======================================================================*
|
|
// The procEntries array specifies the event IDs of procedure entry *
|
|
// events. *
|
|
//======================================================================*/
|
|
int procEntries[] = {
|
|
0, 0, 0, 0, 0,
|
|
#include "HDFidList.h"
|
|
ID_HDF_Last_Entry
|
|
};
|
|
/*======================================================================*
|
|
// The procEntryCalled array indicates whether or not a procedure entry *
|
|
// was called. *
|
|
//======================================================================*/
|
|
int *procEntryCalled;
|
|
/*======================================================================*
|
|
// The HDFProcNames array holds the names of the HDF entries. *
|
|
//======================================================================*/
|
|
static char HDFProcNames[][40] = {
|
|
"noName",
|
|
"noName",
|
|
"noName",
|
|
"noName",
|
|
"noName",
|
|
#include "HDFentryNames.h"
|
|
"HDF_LAST_ENTRY"
|
|
};
|
|
/*=======================================================================
|
|
// NAME *
|
|
// HDFinitTrace_SDDF -- initalize HDF tracing with SDDF records *
|
|
// USAGE *
|
|
// HDFinitTrace_SDDF( traceFileName, procTraceMask ) *
|
|
// PARAMETERS *
|
|
// char *traceFileName -- name of trace file to hold output *
|
|
// uint32 prcoTraceMask -- mask indicating classes of HDF procs to *
|
|
// be traced *
|
|
// RETURNS *
|
|
// None *
|
|
//======================================================================*/
|
|
void HDFinitTrace_SDDF( char *traceFileName, int OUTSW )
|
|
{
|
|
/*===============================================================
|
|
// set traceFileName and set IO tracing switches. If MPIO *
|
|
// tracing is available, MPIO tracing will also be initialized. *
|
|
//==============================================================*/
|
|
#ifdef HAVE_PARALLEL
|
|
/*===============================================================
|
|
// The code is built to handle parallel processing using MPI. *
|
|
// However, the code may or may not be run using MPI and there *
|
|
// may or may not be support for MPIO tracing in the Pablo *
|
|
// Trace libraries. The type of initialization performed *
|
|
// depends on these factors. *
|
|
//==============================================================*/
|
|
int myNode;
|
|
char *buff;
|
|
/*===============================================================
|
|
// Determine if MPI is running the program. *
|
|
//==============================================================*/
|
|
if ( OUTSW == MPI_RUNTIME_TRACE ) {
|
|
/*============================================================
|
|
// in the parallel case, initialize MPI-IO tracing. This *
|
|
// will initialize the traceFileName and set the I/O tracing *
|
|
// switches. *
|
|
//===========================================================*/
|
|
MPI_Comm_rank( MPI_COMM_WORLD, &myNode );
|
|
setTraceProcessorNumber( myNode );
|
|
#ifdef HAVE_MPIOTRACE
|
|
/*============================================================
|
|
// MPIO Tracing is supported in the Pablo Library. Let the *
|
|
// MPIO initialization be performed and handle the naming of *
|
|
// trace files. *
|
|
//===========================================================*/
|
|
initMPIOTrace( traceFileName, RUNTIME_TRACE );
|
|
#else
|
|
/*============================================================
|
|
// MPIO tracing is not supported. *
|
|
// Set up the trace file names depending on the number of *
|
|
// current node. *
|
|
//===========================================================*/
|
|
buff = (char *)malloc( strlen(traceFileName)+12);
|
|
sprintf( buff, "%s.nd%.4d\0",traceFileName,myNode);
|
|
setTraceFileName( buff );
|
|
free( buff );
|
|
#endif
|
|
} else {
|
|
/*============================================================
|
|
// The HDF library was built to run with MPI, but the *
|
|
// application is being run in serial mode. Initialization *
|
|
// is done as in the serial case. *
|
|
//===========================================================*/
|
|
setTraceFileName(traceFileName);
|
|
initIOTrace();
|
|
enableIOdetail();
|
|
disableLifetimeSummaries();
|
|
disableTimeWindowSummaries();
|
|
disableFileRegionSummaries();
|
|
}
|
|
#else
|
|
/*===============================================================
|
|
// in the non-parallel case, set the trace file name and the *
|
|
// I/O tracing switches. *
|
|
//==============================================================*/
|
|
setTraceFileName(traceFileName);
|
|
initIOTrace();
|
|
enableIOdetail();
|
|
disableLifetimeSummaries();
|
|
disableTimeWindowSummaries();
|
|
disableFileRegionSummaries();
|
|
#endif /* HAVE_PARALLEL */
|
|
/*===============================================================
|
|
// complete HDF initiailization. *
|
|
//==============================================================*/
|
|
preInitHDFProcTrace();
|
|
initHDFProcTrace( sizeof(procEntries)/sizeof(int), procEntries );
|
|
}
|
|
/*=======================================================================
|
|
// NAME *
|
|
// HDFendTrace_SDDF -- end HDF tracing *
|
|
// USAGE *
|
|
// HDFendTrace_SDDF() *
|
|
// RETURNS *
|
|
// None. *
|
|
//======================================================================*/
|
|
void HDFendTrace_SDDF(int OUTSW)
|
|
{
|
|
HDFfinalTimeStamp();
|
|
if ( OUTSW == MPI_RUNTIME_TRACE ) {
|
|
/*============================================================
|
|
// termintate MPI-IO tracing in the parallel case. This *
|
|
// will terminate the I/O tracing and close tracing as well. *
|
|
//===========================================================*/
|
|
endMPIOTrace();
|
|
} else {
|
|
/*============================================================
|
|
// terminate tracing *
|
|
//===========================================================*/
|
|
endIOTrace();
|
|
endTracing();
|
|
exit(1);
|
|
}
|
|
}
|
|
/*=======================================================================
|
|
// NAME *
|
|
// initHDFProcTrace: *
|
|
// This function initializes data structures specific to *
|
|
// the procedure entry/exit tracing extensions of the Pablo *
|
|
// instrumentation library. The argument numProcs specifies *
|
|
// how many procedures are to be traced. The argument procEntryID *
|
|
// is a vector specifying the event IDs to be use as entry events *
|
|
// for each of the procedures. The negative value is used for *
|
|
// the exit event ID. *
|
|
// USAGE *
|
|
// result = initHDFProcTrace(numProcs,procEntryID) *
|
|
// PARAMETERS *
|
|
// int numProcs -- number of Procedures to be initialized *
|
|
// int *procEntryID -- array of id entry codes for these procedures *
|
|
// RETURNS *
|
|
// SUCCESS or FAILURE *
|
|
//======================================================================*/
|
|
int initHDFProcTrace( int numProcs, int *procEntryID )
|
|
{
|
|
int procIndex, IX, ID;
|
|
|
|
if (( numProcs <= 0 ) || ( procEntryID == (int *) 0 ) )
|
|
return FAILURE;
|
|
/*===============================================================
|
|
// Allocate space to store a copy of the procedure entry-exit *
|
|
// event ID matchings and also the procedure entry stacks. *
|
|
//==============================================================*/
|
|
procEvents = (PROC_EVENTS *) TRgetBuffer(
|
|
(numProcs+4)*sizeof(PROC_EVENTS) );
|
|
|
|
if ( procEvents == (PROC_EVENTS *) 0 )
|
|
TRfailure( "cannot allocate procedure events matching" );
|
|
|
|
procEntryCalled = ( int *)malloc( numProcs*sizeof(int) );
|
|
if ( procEvents == NULL )
|
|
TRfailure( "cannot allocate procedure Called indicators" );
|
|
/*===============================================================
|
|
// Initialize the procedure events matching from the arguments *
|
|
// passed. Configure the trace record-generating function for *
|
|
// these events. Initialize the flags indicating whether or *
|
|
// not the procedure was called. *
|
|
//==============================================================*/
|
|
for ( procIndex = 0; procIndex < numProcs; procIndex++ ) {
|
|
|
|
IX = procEntryID[ procIndex ];
|
|
ID = HDFIXtoEventID( IX );
|
|
procEvents[ procIndex ].entryID = ID;
|
|
procEvents[ procIndex ].exitID = -ID;
|
|
|
|
setEventRecordFunction( ID, HDFprocEventRecord );
|
|
setEventRecordFunction( -ID, HDFprocEventRecord );
|
|
procEntryCalled[ procIndex ] = 0;
|
|
|
|
}
|
|
|
|
/*===============================================================
|
|
// Initialize the procedure events for malloc. *
|
|
// Configure the trace record-generating function for this *
|
|
// event. *
|
|
//==============================================================*/
|
|
procEvents[ numProcs ].entryID = ID_malloc;
|
|
procEvents[ numProcs ].exitID = -ID_malloc;
|
|
setEventRecordFunction( ID_malloc, miscEventRecord );
|
|
setEventRecordFunction( -ID_malloc, miscEventRecord );
|
|
procEvents[ numProcs+1 ].entryID = ID_free;
|
|
procEvents[ numProcs+1 ].exitID = -ID_free;
|
|
setEventRecordFunction( ID_free, miscEventRecord );
|
|
setEventRecordFunction( -ID_free, miscEventRecord );
|
|
|
|
return SUCCESS;
|
|
}
|
|
/*=======================================================================
|
|
// NAME *
|
|
// preInitHDFProcTrace: *
|
|
// This function calls the trace library interface function *
|
|
// setRecordDescriptor, which records the address of the *
|
|
// procedure that generates the record descriptors for the *
|
|
// procedure trace event families. It is automatically *
|
|
// invoked by HDFinitTrace_SDDF. *
|
|
// USAGE *
|
|
// result = preInitHDFProcTrace(); *
|
|
// RESULT *
|
|
// SUCCESS or FAILURE *
|
|
/=======================================================================*/
|
|
int preInitHDFProcTrace( void )
|
|
{
|
|
static int preInitDone = FALSE;
|
|
|
|
if ( preInitDone == TRUE )
|
|
return SUCCESS;
|
|
/*===============================================================
|
|
// Give the instrumentation library a pointer to the functions *
|
|
// in which we output the specialized record descriptors for *
|
|
// procedure entry/exit. *
|
|
//==============================================================*/
|
|
setRecordDescriptor( writeHDFProcRecordDescriptors );
|
|
|
|
preInitDone = TRUE;
|
|
return SUCCESS;
|
|
}
|
|
/*=======================================================================
|
|
// NAME *
|
|
// writeHDFProcRecordDescriptors: *
|
|
// This function generates the record descriptors for the HDF *
|
|
// procedure entry/exit event families. It will be invoked *
|
|
// by the instrumentation library initialization routines. *
|
|
// Patterned after instrumentation library internal function *
|
|
// writeRecordDescriptors. *
|
|
// USAGE *
|
|
// result = writeHDFProcRecordDescriptors(); *
|
|
// RESULT *
|
|
// SUCCESS *
|
|
/=======================================================================*/
|
|
int writeHDFProcRecordDescriptors( void )
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf( debugFile, "writeHDFProcRecordDescriptors\n" );
|
|
fflush( debugFile );
|
|
#endif /* DEBUG */
|
|
|
|
_hdfMiscDescriptor();
|
|
|
|
#ifdef DEBUG
|
|
fprintf( debugFile, "writeHDFProcRecordDescriptors done\n" );
|
|
fflush( debugFile );
|
|
#endif /* DEBUG */
|
|
return SUCCESS;
|
|
}
|
|
/*=======================================================================
|
|
// NAME *
|
|
// HDFprocEventRecord: *
|
|
// This function generates trace records for events which are *
|
|
// to produce procedure entry or exit event family trace records. *
|
|
// Patterned after the instrumentation library internal functions *
|
|
// externalEventRecord and sddfRecord. *
|
|
// USAGE *
|
|
// REC = HDFprocEventRecord( recordType, eventPointer, timeStamp, *
|
|
// dataPointer, dataLength) *
|
|
// PARAMETERS *
|
|
// int recordType -- type of event record *
|
|
// TR_EVENT eventPointer -- pointer to event data structure *
|
|
// CLOCK timeStamp -- time event is recorded *
|
|
// HDFsetInfo dataPointer -- information about HDF data set accessed *
|
|
// unsigned dataLength -- dummy for compatability *
|
|
// RETURNS *
|
|
// pointer to trace record for this event *
|
|
//======================================================================*/
|
|
TR_RECORD *
|
|
HDFprocEventRecord( int recordType, TR_EVENT *eventPointer, CLOCK timeStamp,
|
|
HDFsetInfo *dataPointer, unsigned dataLength )
|
|
{
|
|
static TR_RECORD traceRecord;
|
|
static void *recordBuffer = NULL;
|
|
static int bufferLength = 0;
|
|
struct procTraceRecordData *TraceRecordHeader;
|
|
int procIndex;
|
|
int recordFamily;
|
|
char *namePtr;
|
|
|
|
#ifdef DEBUG
|
|
fprintf( debugFile, "HDFprocEventRecord\n" );
|
|
fflush( debugFile );
|
|
#endif /* DEBUG */
|
|
|
|
/*==============================================================*
|
|
// Find the index in the tables for the procedure corresponding *
|
|
// to this eventID. *
|
|
//==============================================================*/
|
|
procIndex = findHDFProcEvent( eventPointer->eventID );
|
|
if ( procIndex < 0 ) {
|
|
return nullRecordFunction( recordType, eventPointer,
|
|
timeStamp, (char *)dataPointer, dataLength );
|
|
}
|
|
/*==============================================================*
|
|
// Produce a packet for the name of the procedure if one has *
|
|
// not already been produced. *
|
|
//==============================================================*/
|
|
if ( procEntryCalled[procIndex] == 0 ) {
|
|
createHDFTraceDescriptor( procIndex );
|
|
procEntryCalled[procIndex] = 1;
|
|
}
|
|
/*==============================================================*
|
|
// Determine whether this is a procedure entry or a procedure *
|
|
// exit family event by lookup in the procedure event ID *
|
|
// matching. *
|
|
//==============================================================*/
|
|
recordFamily = HDF_FAMILY + ( procIndex + 1)*8;
|
|
/*==============================================================*
|
|
// The time stamp stored in the event descriptor will be used *
|
|
// unless one is specified in the timeStamp parameter. *
|
|
//==============================================================*/
|
|
if ( clockCompare( timeStamp, noSuchClock ) == 0 ) {
|
|
timeStamp = eventPointer->eventLast;
|
|
}
|
|
/*==============================================================*
|
|
// Determine how many bytes of storage will be needed for the *
|
|
// contents of the trace record. *
|
|
//==============================================================*/
|
|
traceRecord.recordLength = sizeof *TraceRecordHeader;
|
|
if ( dataPointer != NULL && dataPointer->setName != NULL ) {
|
|
traceRecord.recordLength += strlen( dataPointer->setName );
|
|
}
|
|
/*==============================================================*
|
|
// If there is a previously-allocated buffer and its size will *
|
|
// hold this record, re-use the buffer. Otherwise, deallocate *
|
|
// the buffer (if allocated) and allocate a bigger one. *
|
|
//==============================================================*/
|
|
if ( bufferLength < traceRecord.recordLength ) {
|
|
|
|
if ( recordBuffer != NULL ) {
|
|
TRfreeBuffer( recordBuffer );
|
|
}
|
|
|
|
recordBuffer = (char *)TRgetBuffer( traceRecord.recordLength );
|
|
|
|
if ( recordBuffer == NULL ) {
|
|
TRfailure( "cannot allocate storage for trace record" );
|
|
}
|
|
bufferLength = traceRecord.recordLength;
|
|
}
|
|
|
|
traceRecord.recordContents = recordBuffer;
|
|
/*==============================================================*
|
|
// Load the trace record fields into the allocated buffer *
|
|
//==============================================================*/
|
|
TraceRecordHeader = (struct procTraceRecordData *)recordBuffer;
|
|
TraceRecordHeader->packetLength = traceRecord.recordLength;
|
|
TraceRecordHeader->packetType = PKT_DATA;
|
|
TraceRecordHeader->packetTag = recordFamily | recordType;
|
|
TraceRecordHeader->seconds = clockToSeconds( timeStamp );
|
|
TraceRecordHeader->eventID = eventPointer->eventID;
|
|
TraceRecordHeader->nodeNumber = TRgetNode();
|
|
|
|
if ( dataPointer != 0 ) {
|
|
TraceRecordHeader->setID = dataPointer->setID;
|
|
if (dataPointer->setName != NULL ) {
|
|
TraceRecordHeader->nameLen = (int)strlen( dataPointer->setName );
|
|
/*================================================*
|
|
// copy name directly into the end of the buffer. *
|
|
//================================================*/
|
|
namePtr = (char *)TraceRecordHeader + procTraceRecLen;
|
|
memcpy(namePtr, dataPointer->setName, TraceRecordHeader->nameLen);
|
|
} else {
|
|
TraceRecordHeader->nameLen = 0;
|
|
}
|
|
} else {
|
|
TraceRecordHeader->setID = 0;
|
|
TraceRecordHeader->nameLen = 0;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
fprintf( debugFile, "HDFprocEventRecord done\n" );
|
|
fflush( debugFile );
|
|
#endif /* DEBUG */
|
|
returnRecord(&traceRecord);
|
|
}
|
|
/*======================================================================*
|
|
// Internal Routine: miscEventRecord *
|
|
// Called for misc start and end events. *
|
|
//======================================================================*/
|
|
TR_RECORD *miscEventRecord( int recordType,
|
|
TR_EVENT *eventPointer,
|
|
CLOCK timeStamp,
|
|
void *dataPointer,
|
|
unsigned dataLength )
|
|
{
|
|
static TR_RECORD traceRecord;
|
|
static struct miscTraceRecordData miscRecord;
|
|
static int initialized = FALSE;
|
|
int eventID;
|
|
|
|
if ( clockCompare( timeStamp, noSuchClock ) == 0 ) {
|
|
timeStamp = eventPointer->eventLast;
|
|
}
|
|
|
|
eventID = eventPointer->eventID;
|
|
if ( ! initialized ) {
|
|
miscRecord.packetLength = sizeof( miscRecord );
|
|
miscRecord.packetType = PKT_DATA;
|
|
miscRecord.packetTag = FAMILY_MISC | RECORD_TRACE;
|
|
miscRecord.nodeNumber = traceProcessorNumber;
|
|
|
|
traceRecord.recordLength = miscRecord.packetLength;
|
|
traceRecord.recordContents = (char *) &miscRecord;
|
|
initialized = TRUE;
|
|
}
|
|
|
|
switch ( eventID ) {
|
|
case ID_malloc:
|
|
case ID_free:
|
|
miscRecord.seconds = clockToSeconds( timeStamp ) ;
|
|
miscRecord.eventID = eventID ;
|
|
break;
|
|
case -ID_malloc:
|
|
case -ID_free:
|
|
miscRecord.bytes = *(int *)dataPointer;
|
|
miscRecord.duration = clockToSeconds( timeStamp)
|
|
- miscRecord.seconds;
|
|
return &traceRecord; /* generate trace record */
|
|
default:
|
|
fprintf( stderr, "miscEventRecord: unknown eventID %d\n", eventID );
|
|
break;
|
|
}
|
|
/*==================================================================*
|
|
// If we get here then no trace record generated. Normally we *
|
|
// should get here if this is an entry call. *
|
|
//==================================================================*/
|
|
return( nullRecordFunction( recordType, eventPointer, timeStamp,
|
|
dataPointer, dataLength ) );
|
|
}
|
|
/*======================================================================*
|
|
// NAME *
|
|
// findHDFProcEvent: *
|
|
// Search the procedure entry/exit event ID matching data *
|
|
// structure for an event ID (either entry or exit) which is *
|
|
// the same as the argument eventID. If found, return the *
|
|
// index from that table, which will be between 0 and *
|
|
// numberProcedures - 1, inclusive. If not found, return -1; *
|
|
// USAGE *
|
|
// index = findHDFProcEvent *
|
|
// RETURNS *
|
|
// index of the procedure corresponding to this ID *
|
|
//======================================================================*/
|
|
int findHDFProcEvent( int eventID )
|
|
{
|
|
int procIndex;
|
|
|
|
#ifdef DEBUG
|
|
fprintf( debugFile, "findHDFProcEvent\n" );
|
|
fflush( debugFile );
|
|
#endif /* DEBUG */
|
|
if ( isBeginHDFEvent(eventID) ) {
|
|
procIndex = eventID - BEGIN_HDF;
|
|
} else if ( isEndHDFEvent( eventID ) ) {
|
|
procIndex = -eventID - BEGIN_HDF;
|
|
} else {
|
|
procIndex = -1 ;
|
|
}
|
|
return procIndex;
|
|
}
|
|
void createHDFTraceDescriptor( int Inx )
|
|
{
|
|
char BUF1[256], BUF2[256] ;
|
|
int FAMILY;
|
|
strcpy( BUF2, "HDF ");
|
|
strcat( BUF2, HDFProcNames[Inx] );
|
|
strcat( BUF2, " Procedure");
|
|
strcpy( BUF1, BUF2 );
|
|
strcat( BUF1, " Trace");
|
|
|
|
FAMILY = HDF_FAMILY + (Inx + 1)*8;
|
|
_hdfTraceDescriptor( BUF1, BUF2, FAMILY );
|
|
}
|
|
/*======================================================================*
|
|
// NAME *
|
|
// _hdfTraceDescriptor *
|
|
// Generate a SDDF binary format record descriptor for the *
|
|
// full trace class of events in the HDF procedure entry *
|
|
// USAGE *
|
|
// _hdfTraceDescriptro( recordName, recordDescription, recordFamily ) *
|
|
// RETURNS *
|
|
// void *
|
|
//======================================================================*/
|
|
void _hdfTraceDescriptor( char *recordName,
|
|
char *recordDescription,
|
|
int recordFamily )
|
|
{
|
|
static char recordBuffer[ 4096 ];
|
|
int recordLength;
|
|
|
|
hdfRecordPointer = recordBuffer;
|
|
/*===================================================================
|
|
// Allow space at the beginning of the record for the packet *
|
|
//length which will be computed after the packet is complete. *
|
|
//==================================================================*/
|
|
sddfWriteInteger( &hdfRecordPointer, 0 );
|
|
/*===================================================================
|
|
// The record type, tag, and name *
|
|
//==================================================================*/
|
|
sddfWriteInteger( &hdfRecordPointer, PKT_DESCRIPTOR );
|
|
sddfWriteInteger( &hdfRecordPointer, ( recordFamily | RECORD_TRACE ) );
|
|
sddfWriteString( &hdfRecordPointer, recordName );
|
|
/*===================================================================
|
|
// The record attribute count and string pair *
|
|
//==================================================================*/
|
|
sddfWriteInteger( &hdfRecordPointer, 1 );
|
|
sddfWriteString( &hdfRecordPointer, "description" );
|
|
sddfWriteString( &hdfRecordPointer, recordDescription );
|
|
/*==================================================================*
|
|
// The record field count *
|
|
//==================================================================*/
|
|
sddfWriteInteger( &hdfRecordPointer, 5);
|
|
/*==================================================================*
|
|
// Create fields *
|
|
//==================================================================*/
|
|
WRITE_HDF_FIELD( "Event Identifier",
|
|
"Event ID",
|
|
"Event Identifier Number",
|
|
INTEGER, 0 );
|
|
WRITE_HDF_FIELD( "Seconds",
|
|
"Seconds",
|
|
"Floating Point Timestamp",
|
|
DOUBLE, 0 );
|
|
WRITE_HDF_FIELD2( "HDF ID",
|
|
"HDF ID", "File, Data Set or Dim Identifier number",
|
|
"0", "No HDF ID specified",
|
|
LONG, 0 );
|
|
WRITE_HDF_FIELD( "Processor Number",
|
|
"Node",
|
|
"Processor number",
|
|
INTEGER, 0 );
|
|
WRITE_HDF_FIELD( "HDF Name",
|
|
"HDF Name", "Name of File, Data Set or Dim",
|
|
CHARACTER, 1 );
|
|
|
|
|
|
recordLength = (int)(hdfRecordPointer - recordBuffer);
|
|
|
|
hdfRecordPointer = recordBuffer;
|
|
sddfWriteInteger( &hdfRecordPointer, recordLength );
|
|
|
|
putBytes( recordBuffer, (unsigned) recordLength );
|
|
}
|
|
/*======================================================================*
|
|
// NAME *
|
|
// _hdfMiscDescriptor *
|
|
// Generate a SDDF binary format record descriptor for the *
|
|
// misc procedure *
|
|
// USAGE *
|
|
// _hdfMiscDescriptor() *
|
|
// RETURNS *
|
|
// void *
|
|
//======================================================================*/
|
|
void _hdfMiscDescriptor( void )
|
|
{
|
|
static char recordBuffer[ 4096 ];
|
|
int recordLength;
|
|
|
|
#ifdef DEBUG
|
|
fprintf( debugFile, "_hdfMiscDescriptor entered\n" );
|
|
fflush( debugFile );
|
|
#endif /* DEBUG */
|
|
hdfRecordPointer = recordBuffer;
|
|
/*==================================================================*
|
|
// Allow space at the beginning of the record for the packet *
|
|
//length which will be computed after the packet is complete. *
|
|
//==================================================================*/
|
|
sddfWriteInteger( &hdfRecordPointer, 0 );
|
|
/*==================================================================*
|
|
// The record type, tag, and name *
|
|
//==================================================================*/
|
|
sddfWriteInteger( &hdfRecordPointer, PKT_DESCRIPTOR );
|
|
sddfWriteInteger( &hdfRecordPointer, ( FAMILY_MISC | RECORD_TRACE ) );
|
|
sddfWriteString( &hdfRecordPointer, "Misc Trace" );
|
|
/*==================================================================*
|
|
// The record attribute count and string pair *
|
|
//==================================================================*/
|
|
sddfWriteInteger( &hdfRecordPointer, 1 );
|
|
sddfWriteString( &hdfRecordPointer, "description" );
|
|
sddfWriteString( &hdfRecordPointer, "Misc Trace Record" );
|
|
/*==================================================================*
|
|
// The record field count *
|
|
//==================================================================*/
|
|
sddfWriteInteger( &hdfRecordPointer, 5);
|
|
/*==================================================================*
|
|
// Create fields *
|
|
//==================================================================*/
|
|
WRITE_HDF_FIELD( "Event Identifier",
|
|
"Event ID",
|
|
"Event Identifier Number",
|
|
INTEGER, 0 );
|
|
WRITE_HDF_FIELD( "Seconds",
|
|
"Seconds",
|
|
"Floating Point Timestamp",
|
|
DOUBLE, 0 );
|
|
WRITE_HDF_FIELD( "Duration",
|
|
"Duration",
|
|
"Operation Duration",
|
|
DOUBLE, 0 );
|
|
WRITE_HDF_FIELD( "Bytes",
|
|
"Bytes",
|
|
"Bytes Requested",
|
|
LONG, 0 );
|
|
WRITE_HDF_FIELD( "Processor Number",
|
|
"Node",
|
|
"Processor number",
|
|
INTEGER, 0 );
|
|
|
|
recordLength = (int)(hdfRecordPointer - recordBuffer);
|
|
|
|
hdfRecordPointer = recordBuffer;
|
|
sddfWriteInteger( &hdfRecordPointer, recordLength );
|
|
|
|
putBytes( recordBuffer, (unsigned) recordLength );
|
|
}
|
|
|
|
/*#endif */ /* HAVE_PABLO */
|