📄 picl.c
字号:
/* Old-style Picl trace file handling routines for Upshot Ed Karrels Argonne National Laboratory*/#define DEBUG 0#include <stdio.h>#include <ctype.h>#ifdef NEEDS_STDLIB_PROTOTYPES#include "protofix.h"#endif/* here's hoping that sys/stat.h is common */#ifdef __FreeBSD__#include <sys/types.h>#endif#include <sys/stat.h>#include "tcl.h"#include "events.h"#include "states.h"#include "msgs.h"#include "procs.h"#include "log.h"#include "picl.h"#define MAX_LINE_LEN 1024#define MAX_WORD_LEN 64 /* If the user defines a whole buch of different tasks, say 0 through 100, we dont want to create a different state for every one, just do a 'mod' down to 5 unique task types. */#define PICL_MAX_TASK_NO 5typedef enum { min_recordType=0, trace_start, /* 1 */ open, /* 2 */ load, /* 3 */ send, /* 4 */ probe, /* 5 */ recv, /* 6 */ recv_blocking, /* 7 */ recv_waking, /* 8 */ message, /* 9 */ sync, /* 10 */ compstats, /* 11 */ commstats, /* 12 */ close, /* 13 */ trace_level, /* 14 */ trace_mark, /* 15 */ trace_message, /* 16 */ trace_stop, /* 17 */ trace_flush, /* 18 */ trace_exit, /* 19 */ block_begin, /* 20 */ block_end, /* 21 */ trace_marks, /* 22 */ max_recordType} recordTypeEnum;typedef enum { min_blockType=-5, global_op, bcast1, bcast0, barrier, max_blockType} blockTypeEnum;static char *recordTypeNames[] = { "trace_start", "open", "load", "send", "probe", /* why left out? */ "recv", "recv_blocking", "recv_waking", "message", "sync", "compstats", "commstats", "close", "trace_level", "trace_mark", "trace_message", "trace_stop", "trace_flush", "trace_exit", "block_begin", "block_end", "trace_marks"};#define N_RECORD_TYPES 22static char *blockTypeNames[] = { "global_op", "bcast0", "bcast1", "barrier"};#define N_BLOCK_TYPES 4#define PICL_TYPE_NAME_LEN 20#define PICL_HOST_NODE -32768 /* for keeping track of what mode each process is in in this silly format */typedef struct procMode_ { recordTypeEnum mode; int active; /* for messages: */ int other_node; int msg_type; int msg_len;} procMode;typedef struct piclData_ { Tcl_Interp *interp; logFile *log; double startTime, endTime; /* earliest and latest events in the file */ int file_size; /* size of the file */ int bytes_read; /* # of bytes read so far */ int line_no; /* current line # */ int isFirstTime; /* is this the first line to be read? */ int hasHostNode; /* does this tracefile have host node info in it? */ int maxProc; /* largest process # */ /* When a time-consuming event occurs, such as a send, two compstats records will be generated; one at the start of the send, and one at the end. So, when one of these time-consuming events occurs, log the beginning of a state, and save what kind it is, so when a compstats event comes in, we know what kind of state to associate it with. When this first compstats comes in, mark this process as 'active'. When the second compstats comes in, log the end of a state, and set the process back to normal. */ procMode *mode; /* Allocate this to have on element for each process. Store the mode each process is in. */ /* to mesh will the rest of Upshot, every action that will take up time must be mapped to a 'state'. A new state definition is created with a call to State_AddDef(). This will return a state definition # that we should hang onto. These arrays will hold state definition #'s or -1 if a state hasn't been created for the event type yet. */ /* state number for each record type */ /* if no state created yet, set to -1 */ int recordType_state_no[N_RECORD_TYPES]; /* state number for each block type */ /* 0 - 3 will refer to the collective ops, */ /* 4+ will be for user-defined states */ int blockType_state_no[N_BLOCK_TYPES + PICL_MAX_TASK_NO]; } piclData;typedef struct piclLineData_ { int line_no; /* line # */ recordTypeEnum type; /* recordtype of event */ double clock; /* time of the event */ int node; /* node on which the event occurred */ int other_node; /* for sends, the receiver; for receives, */ /* the sender */ int msg_type; /* message type */ int msg_len; /* length of message in bytes */ int type_no; /* user-defined event # */ int block_type; /* for block start/end events, the type of */ /* block: barrier, bcast0, user-defined, ... */ } piclLineData; /* Open up a picl instance */static piclData *Create ANSI_ARGS(( logFile *log ));/* go through the tracefile, getting the first&last timestamps, number of processes, and list of all the states that will be used */static int Preprocess ANSI_ARGS(( piclData *picl ));/* load the tracefile into memory */static int Load ANSI_ARGS(( piclData *picl ));/* Close picl-specific tracefile info, but leave the main logfile information */static int Close ANSI_ARGS(( piclData *picl ));/* Get one word from the given stream, returning -1 if EOF reached, 0 if end-of-line, or the length of the word read. If EOL read, increment picl->line_no. */static int GetWord ANSI_ARGS(( piclData *picl, FILE *fp, char *wordbuf, int maxlen ));/* Given a record type and, if it is a block_begin or block_end, a block type, create a string that will define this state. 'description' should point to at least PICL_TYPE_NAME_LEN bytes. *//*static int GetRecordTypeDesc ANSI_ARGS(( piclData *picl, int recordType, int blockType, char *description ));*//* Given a record type description, return the record type number or -1 for an invalid type */static recordTypeEnum GetRecordTypeFromVerbose ANSI_ARGS(( char *str ));/* Get one line from the tracefile, parsing the data into 'line'. Return -1 on EOF, 0 on blank line, and the length of the line on success. */static int GetLine ANSI_ARGS(( piclData *picl, FILE *fp, piclLineData *line ));/* Create a state definition, if one hasn't been created already, for the given record type of block type. */static int AddState ANSI_ARGS(( piclData *picl, int recordType, int blockType ));/* Given a record type and, if needed, a block type, return the state definition number for the state represented.*/static int GetStateNo ANSI_ARGS(( piclData *picl, int recordType, int blockType ));/* Mark the start of a state.*/static int StartState ANSI_ARGS(( piclData *picl, int node, double time, int recordType, int blockType ));/* Mark the end of a state.*/static int EndState ANSI_ARGS(( piclData *picl, int node, double time, int recordType, int blockType ));int Picl_Open( log )logFile *log;{ piclData *picl; picl = Create( log ); if (!picl) { Tcl_SetResult( log->interp, "Out of memory opening picl tracefile", TCL_STATIC ); return TCL_ERROR; } if (Preprocess( picl ) != TCL_OK) goto err; if (Load( picl ) != TCL_OK) goto err; Close( picl ); return TCL_OK; err: Close( picl ); return TCL_ERROR;}static piclData *Create( log )logFile *log;{ piclData *picl; struct stat statBuf; int i; /* get the size of the file, complain if we can't. */ if (stat( log->filename, &statBuf ) == -1) { Tcl_AppendResult( log->interp, "Couldn't get the size of ", log->filename, (char*)0 ); return 0; } picl = (piclData*)malloc( sizeof( piclData ) ); if (!picl) return 0; picl->interp = log->interp; picl->log = log; picl->isFirstTime = 1; /* set only for the first line */ picl->line_no = 1; /* start counting at line 1 */ picl->bytes_read = 0; /* nothing read so far */ picl->file_size = statBuf.st_size; /* save the size of the file */ picl->hasHostNode = 0; /* assume no host node unless -32768 events are found */ /* set all state definition #'s to 0 - nobody has created a state for themselves yet. */ for (i=0; i<N_RECORD_TYPES; i++) { picl->recordType_state_no[i] = -1; } for (i=0; i<N_BLOCK_TYPES + PICL_MAX_TASK_NO; i++) { picl->blockType_state_no[i] = -1; } return picl;}/* Get one word from the input stream, returning 0 if the end of the line was reached and read, -1 if EOF reached, or a the number of characters in the word.*/static int GetWord( picl, fp, wordbuf, maxlen )piclData *picl;FILE *fp;char *wordbuf;int maxlen;{ int len, c; /* set to output word buffer to a zero-length string */ wordbuf[0] = 0; c = getc( fp ); picl->bytes_read++; /* strip out space between words */ while (c != '\n' && isspace( c )) { c = getc( fp ); picl->bytes_read++; } /* if EOL reached, return 0 */ if (c == '\n') { picl->line_no++; return 0; } /* get the word, stopping at newline, space, or EOF */ len = 0; while (c != '\n' && c != EOF && !isspace( c )) { wordbuf[len++] = c; c = getc( fp ); picl->bytes_read++; } /* If we hit the end of the line or file and nothing has been read yet, return 0. If something has been read, return that and push the newline back into the stream */ if (c == '\n' || c == EOF) { if (len) { picl->bytes_read--; ungetc( c, fp ); } else { wordbuf[0] = 0; /* return 0 if newline, -1 if EOF */ if (c == '\n') { picl->line_no++; return 0; } else { return -1; } } } /* terminate the string */ wordbuf[len] = 0; /* return the # of characters in the word */ return len;} /* flush input through the end of the line */static int GetEOL( picl, fp )piclData *picl;FILE *fp;{ while (getc( fp ) != '\n') picl->bytes_read++; picl->line_no++; return TCL_OK;}/* Given a record type (and block type, if applicable), return a string describing that block type. The 'desc' parameter should point to at least PICL_TYPE_NAME_LEN characters of usable memory.*/static int GetRecordTypeDesc( picl, recordType, blockType, description )piclData *picl; /* all logfile info */int recordType; /* record type */int blockType; /* if record type==block_{start,end}, specify the block type, be it a collective operation or a 'task #' */char *description; /* where to store the description */{ if (recordType < block_begin) { /* one of the standard record types, which start number at 1 */ strcpy( description, recordTypeNames[recordType-1] ); } else { /* a block_begin or block_end */ if (blockType < 0) { /* one of the collective operations */ /* these are numbered from -4 to -1. Remap this into 0 - 3 */ strcpy( description, blockTypeNames[blockType+4] ); } else { /* a user-defined task #, from 0 to whatever. Scale it back. */ blockType %= PICL_MAX_TASK_NO; sprintf( description, "state_%d", blockType ); } } return 0;}/* Given a string form of a record type, such as "trace_start", return the recordTypeEnum index to this record type. Return -1 if not recognized.*/static recordTypeEnum GetRecordTypeFromVerbose( str )char *str;{ int i; for (i=0; i<N_RECORD_TYPES; i++) { if (!strcmp( recordTypeNames[i], str )) { return (recordTypeEnum)i; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -