void vt_metric_free(struct vt_metv* metv, uint32_t tid) { int retval, i; long_long papi_vals[VT_METRIC_MAXNUM]; if ( metv == NULL ) return; /* treat PAPI failures at this point as non-fatal */ VT_SUSPEND_IO_TRACING(tid); /* foreach used eventset */ for (i=0; i < VT_METRIC_MAXNUM && metv->EventSet[i]!=NULL; i++) { retval = PAPI_stop(metv->EventSet[i]->EventId, papi_vals); if ( retval != PAPI_OK ) { metric_warning(retval, "PAPI_stop"); } else { /* cleanup/destroy require successful PAPI_stop */ retval = PAPI_cleanup_eventset(metv->EventSet[i]->EventId); if ( retval != PAPI_OK ) metric_warning(retval, "PAPI_cleanup_eventset"); retval = PAPI_destroy_eventset(&metv->EventSet[i]->EventId); if ( retval != PAPI_OK ) metric_warning(retval, "PAPI_destroy_eventset"); } free(metv->EventSet[i]); } VT_RESUME_IO_TRACING(tid); free(metv); }
void vt_metric_read(struct vt_metv* metv, uint64_t offsets[], uint64_t values[]) { int retval; int i; if ( metv == NULL ) return; VT_SUSPEND_IO_TRACING(VT_CURRENT_THREAD); /* foreach used eventset */ for (i=0; i < VT_METRIC_MAXNUM && metv->EventSet[i]!=NULL; i++) { retval = PAPI_read(metv->EventSet[i]->EventId, metv->EventSet[i]->Values ); if ( retval != PAPI_OK ) metric_error(retval, "PAPI_read"); } if ( offsets != NULL ) for ( i = 0; i < nmetrics; i++ ) values[i] = (uint64_t) *metv->Values[i] + offsets[i]; else for ( i = 0; i < nmetrics; i++ ) values[i] = (uint64_t) *metv->Values[i]; VT_RESUME_IO_TRACING(VT_CURRENT_THREAD); }
uint32_t vt_fork_get_num_childs_tot() { uint32_t nchilds_tot; /* any fork performed? (trace-id file exists?) */ if ( fork_performed ) { int fd; char tmp[16] = ""; vt_libassert(trcid_filename[0] != '\0'); VT_SUSPEND_IO_TRACING(VT_CURRENT_THREAD); /* open temp. id file for reading */ if ( (fd = open(trcid_filename, O_RDONLY)) == -1 ) vt_error_msg("Cannot open file %s: %s", trcid_filename, strerror(errno)); /* read current trace id */ if ( read(fd, tmp, 16) == -1 ) vt_error_msg("Cannot read file %s: %s", trcid_filename, strerror(errno)); vt_libassert(tmp[0] != '\0'); nchilds_tot = atoi(tmp); vt_libassert(nchilds_tot > 0); /* close temp. id file */ close(fd); VT_RESUME_IO_TRACING(VT_CURRENT_THREAD); } else { nchilds_tot = 0; } return nchilds_tot; }
void vt_sync(MPI_Comm comm, uint64_t* ltime, int64_t* offset) { VT_MPI_INT myrank, myrank_host, myrank_sync; VT_MPI_INT numnodes; uint64_t time; MPI_Comm host_comm; MPI_Comm sync_comm; VT_SUSPEND_IO_TRACING(VT_CURRENT_THREAD); /* mark begin of clock synchronization */ time = vt_pform_wtime(); vt_enter(VT_CURRENT_THREAD, &time, vt_trc_regid[VT__TRC_SYNCTIME]); /* barrier at entry */ PMPI_Barrier(comm); *offset = 0; *ltime = vt_pform_wtime(); PMPI_Comm_rank(comm, &myrank); /* create communicator containing all processes on the same node */ PMPI_Comm_split(comm, (vt_pform_node_id() & 0x7FFFFFFF), 0, &host_comm); PMPI_Comm_rank(host_comm, &myrank_host); /* create communicator containing all processes with rank zero in the previously created communicators */ PMPI_Comm_split(comm, myrank_host, 0, &sync_comm); PMPI_Comm_rank(sync_comm, &myrank_sync); PMPI_Comm_size(sync_comm, &numnodes); /* measure offsets between all nodes and the root node (rank 0 in sync_comm) */ if (myrank_host == 0) { VT_MPI_INT i; for (i = 1; i < numnodes; i++) { PMPI_Barrier(sync_comm); if (myrank_sync == i) *offset = sync_slave(ltime, 0, sync_comm); else if (myrank_sync == 0) *offset = sync_master(ltime, i, sync_comm); } } /* distribute offset and ltime across all processes on the same node */ PMPI_Bcast(offset, 1, MPI_LONG_LONG_INT, 0, host_comm); PMPI_Bcast(ltime, 1, MPI_LONG_LONG_INT, 0, host_comm); PMPI_Comm_free(&host_comm); PMPI_Comm_free(&sync_comm); /* barrier at exit */ PMPI_Barrier(comm); /* mark end of clock synchronization */ time = vt_pform_wtime(); vt_exit(VT_CURRENT_THREAD, &time); VT_RESUME_IO_TRACING(VT_CURRENT_THREAD); }
static void get_symtab(void) { char* nm_cmd = NULL; char* nm_filename; FILE* nm_stream; char* line; size_t line_size; uint32_t lineno = 0; uint8_t parse_error = 0; VT_SUSPEND_IO_TRACING(VT_CURRENT_THREAD); /* open nm-file, if given */ nm_filename = vt_env_gnu_nmfile(); if ( nm_filename != NULL && strlen(nm_filename) > 0 ) { vt_cntl_msg(2, "Collecting symbols from file %s", nm_filename); /* open nm-file */ if ( (nm_stream = fopen(nm_filename, "r")) == NULL ) vt_error_msg("Could not open symbol list file %s", nm_filename); } /* otherwise, try to get symbol table automatically */ else { char* apppath; char* nm; size_t nm_cmd_len; vt_cntl_msg(2, "Collecting symbols by 'nm'"); /* get executable path specified by VT_APPPATH */ apppath = vt_env_apppath(); if ( apppath == NULL || strlen(apppath) == 0 ) { vt_error_msg("Could not determine path of executable.\n" "Please set the environment variable VT_APPPATH to the path " "of your executable or set VT_GNU_NMFILE to a symbol list " "file created with 'nm'."); } /* get nm command specified by VT_GNU_NM */ nm = vt_env_gnu_nm(); if ( nm == NULL ) { vt_error_msg("VampirTrace was configured without an 'nm' command.\n" "Please set the environment variable VT_GNU_NM to the 'nm' " "command including command line switches which lists " "symbol/addresses of an object file in BSD-style or set " "VT_GNU_NMFILE to a pre-created symbol list file." ); } /* allocate memory for nm command */ nm_cmd_len = strlen(nm) + 1 + strlen(apppath) + 1; nm_cmd = (char*)malloc(nm_cmd_len * sizeof(char)); if ( nm_cmd == NULL ) vt_error(); /* compose nm command */ snprintf(nm_cmd, nm_cmd_len, "%s %s", nm, apppath); /* execute nm command */ vt_cntl_msg(2, "Executing %s", nm_cmd); nm_stream = popen(nm_cmd, "r"); /* error handling after pclose below */ nm_filename = NULL; } /* allocate memory for lines */ line = (char*)malloc(NM_LINE_BLK_LEN * sizeof(char)); if ( line == NULL ) vt_error(); line_size = NM_LINE_BLK_LEN; /* read lines */ while( nm_stream != NULL && fgets(line, line_size, nm_stream) ) { char* col; char delim[2] = " "; int nc = 1; long addr = -1; char* filename = NULL; char* funcname = NULL; unsigned int lno = VT_NO_LNO; lineno++; /* trigger a parse error, if line is empty */ if ( strlen(line) == 0 ) { parse_error = 1; break; } /* if line seems to be incomplete, enlarge line buffer and read the remaining line */ while( !parse_error && line[strlen(line)-1] != '\n' ) { char tmp[NM_LINE_BLK_LEN]; /* read the remaining line; if it fails (EOF) the line seems to be complete after all */ if ( !fgets(tmp, sizeof(tmp), nm_stream) ) break; /* trigger a parse error, if line is to long (>NM_LINE_MAX_LEN) */ if ( line_size + NM_LINE_BLK_LEN > NM_LINE_MAX_LEN ) { parse_error = 1; break; } /* enlarge line buffer */ line = (char*)realloc(line, (line_size + NM_LINE_BLK_LEN) * sizeof(char)); if ( line == NULL ) vt_error(); line_size += NM_LINE_BLK_LEN; /* complete line */ strcat(line, tmp); } if ( parse_error ) break; /* chop new-line character from line */ if ( line[strlen(line)-1] == '\n' ) line[strlen(line)-1] = '\0'; /* split line to columns */ col = strtok(line, delim); do { if ( nc == 1 ) /* column 1 (address) */ { /* if there is no address in the first column the symbol could be undefined; try get its address later (nc==3) */ if ( strlen(col) == 1 ) { nc++; /* <- will be 3 in the next round */ strcpy(delim, "\t"); } /* otherwise, convert address string */ else { addr = strtol(col, NULL, 16); } } else if ( nc == 2 ) /* column 2 (type) */ { /* type must have a length of 1 */ if ( strlen(col) != 1 ) { parse_error = 1; break; } strcpy(delim, "\t"); } else if ( nc == 3 ) /* column 3 (symbol) */ { funcname = col; strcpy(delim, ":"); /* try to get address of undefined function, if necessary */ if ( addr == -1 ) addr = (long)GET_ADDR_OF_UNDEF_FUNC(funcname); /* ignore function, if its address could not be determined */ if ( addr == 0 ) break; } else if( nc == 4 ) /* column 4 (filename) */ { filename = col; } else /* column 5 (line) */ { lno = atoi(col); if( lno == 0 ) lno = VT_NO_LNO; break; } nc++; col = strtok(0, delim); } while( col ); /* stop reading file, if an parse error occurred */ if ( parse_error ) { break; } /* at least two columns must be read */ else if ( nc < 3 ) { parse_error = 1; break; } /* add symbol to hash table, if we have its address and name */ else if ( addr > 0 && funcname ) { char* n = strdup(funcname); char* p; if ( n == NULL ) vt_error(); /* chop function name at '??', if necessary */ p = strstr(n, "??"); if ( p != NULL && p != n ) *p = '\0'; hash_put(addr, n, filename, lno); } } /* close file/pipe stream */ if ( nm_filename != NULL ) { fclose(nm_stream); if ( parse_error ) { vt_error_msg("%s:%u: could not be parsed.\n" "Please check the content of %s for BSD-style.", nm_filename, lineno, nm_filename); } } else { uint8_t nmcmd_error = (nm_stream == NULL || pclose(nm_stream) != 0); if ( parse_error ) { vt_error_msg("Could not parse 'nm' output created with %s.\n" "Please set the environment variable VT_GNU_NM to the 'nm' " "command including command line switches which lists " "symbol/addresses of an object file in BSD-style or set " "VT_GNU_NMFILE to a pre-created symbol list file.", nm_cmd); } else if ( nmcmd_error ) { vt_error_msg("Failed to execute %s\n" "Please set the environment variable VT_GNU_NM to the 'nm' " "command including command line switches which lists " "symbol/addresses of an object file in BSD-style or set " "VT_GNU_NMFILE to a pre-created symbol list file.", nm_cmd); } free(nm_cmd); } free(line); VT_RESUME_IO_TRACING(VT_CURRENT_THREAD); }
void vt_esync(MPI_Comm comm) { uint64_t time, etime; Sync_TsPerRun* temp_ts; Sync_Map* temp_map; VT_MPI_INT myrank; VT_MPI_INT numnodes; VT_MPI_INT partnerid, numslots; VT_MPI_INT i; VT_SUSPEND_IO_TRACING(); /* mark begin of clock synchronization */ time = vt_pform_wtime(); vt_enter(&time, vt_trc_regid[VT__TRC_SYNCTIME]); /* ... also as comment for vtunify */ vt_comment(&time, "__ETIMESYNC__"); /* barrier at entry */ PMPI_Barrier(comm); temp_ts = (Sync_TsPerRun*) malloc(sizeof(Sync_TsPerRun)); if (temp_ts == NULL) vt_error(); temp_ts->sync_phase = NULL; temp_ts->next = NULL; if (SyncTsPerRunFirst == NULL) { SyncTsPerRunFirst = temp_ts; SyncTsPerRunLast = temp_ts; } else { SyncTsPerRunLast->next = temp_ts; SyncTsPerRunLast = temp_ts; } /* measure time synchronization */ PMPI_Comm_rank(comm, &myrank); PMPI_Comm_size(comm, &numnodes); numslots = (VT_MPI_INT)ceil(log((double)(numnodes)) / log(2.0)); for(i = 0; i < numslots; i++) { partnerid = esync_commpartner(myrank, numnodes, i); if( partnerid < numnodes ) { if( myrank < partnerid ) { esync_master(partnerid, comm, myrank); } else { esync_slave(partnerid, comm); } } } /* add myrank to list of map ids */ temp_map = (Sync_Map*)malloc(sizeof(Sync_Map)); if (temp_map == NULL) vt_error(); temp_map->id = myrank; temp_map->time = time; temp_map->duration = (uint32_t) 0; temp_map->next = NULL; if (SyncMapIdFirst == NULL) { SyncMapIdFirst = temp_map; SyncMapIdLast = temp_map; } else { SyncMapIdLast->next = temp_map; SyncMapIdLast = temp_map; } /* barrier at exit */ PMPI_Barrier(comm); /* mark end of clock synchronization */ etime = vt_pform_wtime(); vt_exit(&etime); /* increment number of sync. phases */ SyncRound++; /* set timestamp of next synchronization if necessary */ if (SyncNext != (uint64_t)-1) SyncNext = etime + SyncIntv; /* calculate sync. duration */ SyncMapIdLast->duration = etime - time; VT_RESUME_IO_TRACING(); }
static int get_new_trcid() { int new_trcid; int fd; int8_t tmp_len; struct flock fl; char tmp[10] = ""; uint8_t do_unlock = 1; vt_libassert(trcid_filename[0] != '\0'); VT_SUSPEND_IO_TRACING(VT_CURRENT_THREAD); /* open/create temp. id file */ if ( (fd = open(trcid_filename, (O_RDWR | O_CREAT), (S_IRUSR | S_IWUSR))) == -1 ) vt_error_msg("Cannot open file %s: %s", trcid_filename, strerror(errno)); /* lock temp. id file */ fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; if (fcntl(fd, F_SETLKW, &fl) == -1) { do_unlock = 0; vt_warning("Cannot lock file %s: %s", trcid_filename, strerror(errno)); } /* read current trace id */ if ( read(fd, tmp, 9) == -1 ) vt_error_msg("Cannot read file %s: %s", trcid_filename, strerror(errno)); tmp[9] = '\0'; if ( tmp[0] == '\0' ) new_trcid = 1; /* set trace id to 1, if file is empty */ else new_trcid = atoi(tmp) + 1; /* increment trace id */ /* write new trace id */ lseek(fd, 0, SEEK_SET); snprintf(tmp, sizeof(tmp)-1, "%i\n", new_trcid); tmp_len = strlen( tmp ); if( tmp_len > write( fd, tmp, tmp_len ) ){ vt_error_msg( "Failed to write to file %s: %s", trcid_filename,strerror(errno) ); } /* unlock temp. id file */ if ( do_unlock ) { fl.l_type = F_UNLCK; if ( fcntl(fd, F_SETLK, &fl) == -1 ) vt_error_msg("Cannot unlock file %s: %s", trcid_filename, strerror(errno)); } /* close temp. id file */ close(fd); vt_cntl_msg(2, "Updated trace-id in %s to %i", trcid_filename, new_trcid); VT_RESUME_IO_TRACING(VT_CURRENT_THREAD); return new_trcid; }