void vt_fork(pid_t pid) { vt_libassert(pid != -1); fork_performed = 1; /* child process ... */ if ( pid == 0 ) { vt_my_ptrace = vt_my_trace; vt_my_trace = get_new_trcid(); vt_error_pid(vt_my_trace); /* reset VampirTrace for new child process */ vt_reset(); } /* parent process ... */ else { vt_error_pid(vt_my_trace); /* add new pid to child vector */ childv_add(pid); } }
static void idle_tid_list_push_back(uint32_t ptid, uint32_t tid) { IdleThreadIdListEntryT* idle_tid; vt_libassert(ptid < VTThrdMaxNum); /* create new list entry */ idle_tid = (IdleThreadIdListEntryT*)calloc(1, sizeof(IdleThreadIdListEntryT)); if (idle_tid == NULL) vt_error(); idle_tid->tid = tid; /* append new entry to list */ if (idleThreadIds[ptid].last) { idleThreadIds[ptid].last->next = idle_tid; idleThreadIds[ptid].last = idle_tid; } else { idleThreadIds[ptid].first = idleThreadIds[ptid].last = idle_tid; } /* increment size of list */ idleThreadIds[ptid].size++; }
void vt_mpi_register_remain() { vt_libassert( mpi_fid != (uint32_t)-1 ); /* include generated function registry */ # include "vt_mpireg.gen.c" }
static void maybe_register_new_thread(VTThrd * thrd, uint32_t tid) { struct vt_plugin_cntr_defines * plugin_cntr_defines; vt_libassert(thrd!=NULL); /* "register" a thread */ if (thrd->plugin_cntr_defines == NULL) { thrd->plugin_cntr_defines = calloc(1, sizeof(struct vt_plugin_cntr_defines)); vt_libassert(thrd->plugin_cntr_defines!=NULL); plugin_cntr_defines = (struct vt_plugin_cntr_defines *) thrd->plugin_cntr_defines; plugin_cntr_defines->counters = calloc(VT_PLUGIN_CNTR_SYNCH_TYPE_MAX, sizeof(struct vt_plugin_single_counter *)); /* number of counters of type */ plugin_cntr_defines->size_of_counters = calloc( VT_PLUGIN_CNTR_SYNCH_TYPE_MAX, sizeof(uint32_t)); /* single elements in vectors */ } }
uint32_t vt_plugin_cntr_get_num_synch_metrics(VTThrd * thrd) { uint32_t num = 0; vt_libassert(thrd != NULL); if (thrd->plugin_cntr_defines == NULL) return 0; num = ((struct vt_plugin_cntr_defines *)(thrd->plugin_cntr_defines)) ->size_of_counters[VT_PLUGIN_CNTR_SYNCH]; return num; }
void vt_getcpu_init() { vt_libassert(vt_misc_cgid != 0); /* write counter definition */ vt_getcpu_cid = vt_def_counter(VT_CURRENT_THREAD, "CPU_ID", "#", VT_CNTR_ABS | VT_CNTR_NEXT, vt_misc_cgid, 0); }
void VT_Dyn_start(uint32_t index, const char* name, const char* fname, uint32_t lno, uint32_t loop) { uint64_t time; uint32_t* rid; vt_libassert(index < VT_MAX_DYNINST_REGIONS); /* Ignore events if VT is initializing */ if( !dyn_init && !vt_is_alive ) return; /* If not yet initialized, initialize VampirTrace */ if ( dyn_init ) { VT_MEMHOOKS_OFF(); dyn_init = 0; rtab = (uint32_t*)calloc(VT_MAX_DYNINST_REGIONS, sizeof(uint32_t)); if ( rtab == NULL ) vt_error(); vt_open(); vt_comp_finalize = VT_Dyn_finalize; VT_MEMHOOKS_ON(); } /* If VampirTrace already finalized, return */ if ( !vt_is_alive ) return; VT_MEMHOOKS_OFF(); time = vt_pform_wtime(); /* Get region identifier */ rid = &(rtab[index]); if ( *rid == 0 ) { /* If region entered the first time, register region */ #if (defined(VT_MT) || defined(VT_HYB)) VTTHRD_LOCK_IDS(); if ( *rid == 0 ) *rid = register_region(name, fname, lno, loop); VTTHRD_UNLOCK_IDS(); #else /* VT_MT || VT_HYB */ *rid = register_region(name, fname, lno, loop); #endif /* VT_MT || VT_HYB */ } /* Write enter record */ vt_enter(VT_CURRENT_THREAD, &time, *rid); VT_MEMHOOKS_ON(); }
char* vt_fork_get_trcid_filename() { char* filename; vt_libassert(trcid_filename[0] != '\0'); filename = strdup(trcid_filename); if ( filename == NULL ) vt_error(); return filename; }
void __func_trace_exit(char* name, char* fname, int lno) #endif { HashNode *hn; uint32_t tid; uint64_t time; /* -- if VampirTrace already finalized, return -- */ if ( !vt_is_alive ) return; # if __IBMC__ > 1100 vt_libassert(*ihn != NULL); /* -- ignore IBM OMP runtime functions -- */ if ( *ihn == &ignored_func ) return; hn = *ihn; # else /* __IBMC__ */ /* -- ignore IBM OMP runtime functions -- */ if ( ( strchr(name, '@') != NULL ) || (strchr(name, '$') != NULL) ) return; hn = hash_get((long) name); vt_libassert(hn != NULL); # endif /* __IBMC__ */ /* -- get calling thread id -- */ GET_THREAD_ID(tid); VT_SUSPEND_MALLOC_TRACING(tid); time = vt_pform_wtime(); /* -- write exit record -- */ vt_exit(tid, &time); VT_RESUME_MALLOC_TRACING(tid); }
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; }
static uint32_t idle_tid_list_pop_front(uint32_t ptid) { uint32_t tid; IdleThreadIdListEntryT* tmp; vt_libassert(ptid < VTThrdMaxNum); vt_libassert(idleThreadIds[ptid].size > 0); /* get thread-ID from the first list entry */ tid = idleThreadIds[ptid].first->tid; /* remove first list entry */ tmp = idleThreadIds[ptid].first; if (idleThreadIds[ptid].first == idleThreadIds[ptid].last) idleThreadIds[ptid].first = idleThreadIds[ptid].last = NULL; else idleThreadIds[ptid].first = tmp->next; free(tmp); /* decrement size of list */ idleThreadIds[ptid].size--; return tid; }
uint32_t VTThrd_getThreadId() { uint32_t *tid; /* get thread-ID from thread-specific data */ tid = (uint32_t*)pthread_getspecific(pthreadKey); /* by calling pthread_exit() in main() the thread-specific data for the master thread can already be destroyed at this point; if this happens return zero (thread-ID of the master thread) */ if (tid == NULL && masterThreadTerminated) return 0; else vt_libassert(tid != NULL); return *tid; }
void vt_win_create( MPI_Win win, MPI_Comm comm ) { MPI_Group group; /* check if window already exists */ if (win_search( win ) == (uint32_t)-1) { uint32_t wid; #if (defined(VT_MT) || defined(VT_HYB)) VTTHRD_LOCK_IDS(); #endif /* VT_MT || VT_HYB */ wid = vt_get_curid(); #if (defined(VT_MT) || defined(VT_HYB)) VTTHRD_UNLOCK_IDS(); #endif /* VT_MT || VT_HYB */ /* ask for group of win and register them */ PMPI_Win_get_group(win, &group); vt_libassert(group != MPI_GROUP_NULL); vt_group_create(group); /* enter win in wins[] array */ if( free_win != (uint32_t)-1 ) { wins[free_win].win = win; wins[free_win].comm = comm; wins[free_win].gid = vt_group_id(group); wins[free_win].wid = wid; } else { /* raise maximum number of windows, if necessary */ if (last_win == max_wins) RAISE_MAX(wins, max_wins, struct VTWin); wins[last_win].win = win; wins[last_win].comm = comm; wins[last_win].gid = vt_group_id(group); wins[last_win].wid = wid; last_win++; } } }
void VT_Dyn_end(uint32_t index) { uint64_t time; vt_libassert(index < VT_MAX_DYNINST_REGIONS); /* If VampirTrace already finalized, return */ if ( !vt_is_alive ) return; /* If region id isn't present, return */ if ( rtab[index] == 0 ) return; VT_MEMHOOKS_OFF(); time = vt_pform_wtime(); /* Write exit record */ vt_exit(VT_CURRENT_THREAD, &time); VT_MEMHOOKS_ON(); }
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; }
void VTThrd_unlock(VTThrdMutex** mutex) { vt_libassert(*mutex != NULL); omp_unset_lock(&((*mutex)->m)); }
uint32_t VTThrd_getThreadId() { vt_libassert(threadId != VT_NO_ID); return threadId; }
/* may be called per thread */ void vt_plugin_cntr_write_post_mortem(VTThrd * thrd) { uint32_t counter_index; uint64_t * counter_current_indices; vt_plugin_cntr_timevalue ** time_values_by_counter = NULL; uint32_t number_of_counters; uint64_t * number_of_values_by_counter; uint64_t dummy_time; uint32_t tid; struct vt_plugin_single_counter current_counter; struct vt_plugin_cntr_defines * plugin_cntr_defines = (struct vt_plugin_cntr_defines *) thrd->plugin_cntr_defines; if (plugin_cntr_defines == NULL) return; if (plugin_cntr_defines->size_of_counters[VT_PLUGIN_CNTR_ASYNCH_POST_MORTEM] == 0) return; if (VTTHRD_TRACE_STATUS(thrd) != VT_TRACE_ON) return; for (tid=0;tid<VTThrdn;tid++) if ( VTThrdv[tid] == thrd ) break; if ( tid == VTThrdn ){ vt_warning("Can not determine internal TID when gathering post-mortem counters"); return; } /* for all post_mortem counters */ number_of_counters = plugin_cntr_defines->size_of_counters[VT_PLUGIN_CNTR_ASYNCH_POST_MORTEM]; dummy_time = vt_pform_wtime(); /* set flag for writing post mortem counters; prevents writing of flush * enter/exit event when flushing */ thrd->plugin_cntr_writing_post_mortem = 1; /* we assume that for each counter (not plugin), * the data is monotonically increasing */ /* for all counters of this thread */ time_values_by_counter = calloc(number_of_counters, sizeof(*time_values_by_counter)); vt_libassert(time_values_by_counter); number_of_values_by_counter = calloc(number_of_counters, sizeof(*number_of_values_by_counter)); vt_libassert(number_of_values_by_counter); for (counter_index = 0; counter_index < number_of_counters; counter_index++) { current_counter = plugin_cntr_defines->counters[VT_PLUGIN_CNTR_ASYNCH_POST_MORTEM][counter_index]; /* get data */ number_of_values_by_counter[counter_index] = current_counter.getAllValues( current_counter.from_plugin_id, &(time_values_by_counter[counter_index])); if (time_values_by_counter[counter_index] == NULL) { free(time_values_by_counter); free(number_of_values_by_counter); return; } } /* initialized with 0! */ counter_current_indices = calloc(number_of_counters, sizeof(*counter_current_indices)); vt_libassert(counter_current_indices); while (1) { vt_plugin_cntr_timevalue *min_tvp = NULL; uint32_t min_counter; for (counter_index = 0; counter_index < number_of_counters; counter_index++) { /* * TODO optimize for "nice" plugins by looking if the "next" counter has the * _same_ timestamp (so there cannot be anyone else with a smaller one */ vt_plugin_cntr_timevalue *tvp; if (counter_current_indices[counter_index] >= number_of_values_by_counter[counter_index]) { continue; } tvp = &(time_values_by_counter[counter_index][counter_current_indices[counter_index]]); if (!min_tvp || tvp->timestamp < min_tvp->timestamp) { min_tvp = tvp; min_counter = counter_index; } } if (min_tvp == NULL) { /* we are done */ break; } current_counter = plugin_cntr_defines->counters[VT_PLUGIN_CNTR_ASYNCH_POST_MORTEM][min_counter]; WRITE_ASYNCH_DATA(thrd, tid, current_counter, *min_tvp, &dummy_time); counter_current_indices[min_counter]++; } free(time_values_by_counter); free(counter_current_indices); free(number_of_values_by_counter); /* unset flag for writing post mortem counters */ thrd->plugin_cntr_writing_post_mortem = 0; }
void VTThrd_unlock(VTThrdMutex** mutex) { vt_libassert(*mutex != NULL); pthread_mutex_unlock(&((*mutex)->m)); }
static uint32_t idle_tid_list_size(uint32_t ptid) { vt_libassert(ptid < VTThrdMaxNum); return idleThreadIds[ptid].size; }