static void pthread_key_destructor(void* data) { uint32_t tid = *((uint32_t*)data); #if defined(VT_METR) if (vt_is_alive && vt_metric_num() > 0 && VTThrdv[tid]->metv) { /* shut down metrics */ vt_metric_free(VTThrdv[tid]->metv, tid); VTThrdv[tid]->metv = NULL; } #endif /* VT_METR */ if (tid == 0) { /* register termination of main() thread (*tid==0) */ masterThreadTerminated = 1; /* TODO: It's unclear whether/where the lists of idle thread-IDs should be freed. Maybe at this point? */ } else if (vt_is_alive && reuseThreadIds) { /* store thread-ID for reuse */ pthread_mutex_lock(&threadReuseMutex); idle_tid_list_push_back(VTThrdv[tid]->parent_tid, tid); pthread_mutex_unlock(&threadReuseMutex); /* store last metric values */ #if defined(VT_METR) if (vt_metric_num() > 0 && VTThrdv[tid]->offv && VTThrdv[tid]->valv) memcpy(VTThrdv[tid]->offv, VTThrdv[tid]->valv, vt_metric_num() * sizeof(uint64_t)); #endif /* VT_METR */ /* only disable plugin counters, so they can be reused */ #if defined(VT_PLUGIN_CNTR) /* if we really use plugins and this thread also uses some */ if (vt_plugin_cntr_used && VTThrdv[tid]->plugin_cntr_defines) vt_plugin_cntr_thread_disable_counters(VTThrdv[tid]); #endif /* VT_PLUGIN_CNTR */ } /* free thread-specific data */ free(data); }
void VTThrd_destroy(VTThrd* thrd, uint32_t tid) { #if !defined(VT_DISABLE_RFG) RFG_Regions_free(thrd->rfg_regions); #endif /* VT_DISABLE_RFG */ VTGen_destroy(thrd->gen); #if defined(VT_RUSAGE) if ( vt_rusage_num() > 0 ) { if ( thrd->ru_obj ) { vt_rusage_free(thrd->ru_obj); thrd->ru_obj = NULL; } if ( thrd->ru_valv ) { free(thrd->ru_valv); thrd->ru_valv = NULL; } } #endif /* VT_RUSAGE */ #if defined(VT_METR) if ( vt_metric_num() > 0 && thrd->is_virtual_thread == 0 ) { if ( thrd->metv ) { vt_metric_free(thrd->metv, tid); thrd->metv = NULL; } if ( thrd->offv ) { free(thrd->offv); thrd->offv = NULL; } if ( thrd->valv ) { free(thrd->valv); thrd->valv = NULL; } } #endif /* VT_METR */ free(thrd); /* decrement the thread object counter */ #if (defined(VT_MT) || defined(VT_HYB) || defined(VT_JAVA)) VTTHRD_LOCK_ENV(); VTThrdn--; vt_cntl_msg(2, "Thread object #%u destroyed, leaving %u", tid, VTThrdn); VTTHRD_UNLOCK_ENV(); #else /* VT_MT || VT_HYB || VT_JAVA */ VTThrdn--; vt_cntl_msg(2, "Thread object #%u destroyed, leaving %u", tid, VTThrdn); #endif /* VT_MT || VT_HYB || VT_JAVA */ }
void VTThrd_registerThread(uint32_t ptid) { uint32_t *tid; uint8_t tid_reuse = 0; if (!vt_is_alive) return; /* check whether an ID is already created for this thread */ tid = (uint32_t*)pthread_getspecific(pthreadKey); if (tid == NULL) { tid = (uint32_t*)malloc(sizeof(uint32_t)); if (tid == NULL) vt_error(); /* try to get idle thread-ID for reuse, if desired */ if (reuseThreadIds) { pthread_mutex_lock(&threadReuseMutex); if (idle_tid_list_size(ptid) > 0) { *tid = idle_tid_list_pop_front(ptid); tid_reuse = 1; } pthread_mutex_unlock(&threadReuseMutex); } /* create new thread-ID, if not reusing */ if (!tid_reuse) *tid = VTThrd_create(NULL, ptid, 0); /* put (new) thread-ID to thread-specific data */ pthread_setspecific(pthreadKey, tid); /* open thread associated trace file, if new thread object was created */ if (!tid_reuse ) { VTThrd_open(*tid); } /* otherwise, re-create metrics for reused thread object */ else { #if defined(VT_METR) if (vt_metric_num() > 0 && !VTThrdv[*tid]->metv) VTThrdv[*tid]->metv = vt_metric_create(); #endif /* VT_METR */ #if defined(VT_PLUGIN_CNTR) /* if we really use plugins and this thread also uses some */ if (vt_plugin_cntr_used && VTThrdv[*tid]->plugin_cntr_defines) vt_plugin_cntr_thread_enable_counters(VTThrdv[*tid]); #endif /* VT_PLUGIN_CNTR */ } } }
void VTThrd_initOmp() { static uint8_t initflag = 1; if (initflag) { initflag = 0; /* set ID for master thread (=0) */ threadId = 0; #if defined(VT_METR) if (vt_metric_num() > 0) vt_metric_thread_init((long (*)(void))(omp_get_thread_num)); #endif /* VT_METR */ } }
void VTThrd_initPthread() { static uint8_t initflag = 1; if (initflag) { uint32_t* master_tid; initflag = 0; /* reuse thread IDs of terminated threads? */ if ((reuseThreadIds = (uint8_t)vt_env_pthread_reuse())) { /* create lists for idle thread-IDs */ idleThreadIds = (IdleThreadIdListT*)calloc(VTThrdMaxNum, sizeof(IdleThreadIdListT)); if (idleThreadIds == NULL) vt_error(); } /* create thread-specific data key for all threads */ if (pthread_key_create(&pthreadKey, pthread_key_destructor) != 0) vt_error(); /* create ID for master thread (=0) */ master_tid = (uint32_t*)calloc(1, sizeof(uint32_t)); if (master_tid == NULL) vt_error(); /* put master thread-ID to thread-specific data */ if (pthread_setspecific(pthreadKey, master_tid) != 0) vt_error(); #if defined(VT_METR) if (vt_metric_num() > 0) vt_metric_thread_init((long (*)(void))(pthread_self)); #endif /* VT_METR */ } }
void VTThrd_delete(VTThrd* thrd, uint32_t tid) { if ( !thrd ) return; #if !defined(VT_DISABLE_RFG) if ( thrd->rfg_regions ) RFG_Regions_free(thrd->rfg_regions); #endif /* VT_DISABLE_RFG */ /* must be called before VTGen_delete */ #if defined(VT_PLUGIN_CNTR) /* if we really use plugins and this thread also uses some */ if ( vt_plugin_cntr_used && thrd->plugin_cntr_defines ){ vt_plugin_cntr_thread_exit(thrd); } #endif /* VT_PLUGIN_CNTR */ if ( thrd->gen ) VTGen_delete(thrd->gen); #if defined(VT_RUSAGE) if ( vt_rusage_num() > 0 ) { if ( thrd->ru_obj ) { vt_rusage_free(thrd->ru_obj); thrd->ru_obj = NULL; } if ( thrd->ru_valv ) { free(thrd->ru_valv); thrd->ru_valv = NULL; } } #endif /* VT_RUSAGE */ #if defined(VT_METR) if ( vt_metric_num() > 0 && thrd->is_virtual_thread == 0 ) { if ( thrd->metv ) { vt_metric_free(thrd->metv, tid); thrd->metv = NULL; } if ( thrd->offv ) { free( thrd->offv ); thrd->offv = NULL; } if ( thrd->valv ) { free(thrd->valv); thrd->valv = NULL; } } #endif /* VT_METR */ free(thrd); /* decrement the thread object counter */ #if (defined(VT_MT) || defined(VT_HYB) || defined(VT_JAVA)) VTTHRD_LOCK_ENV(); VTThrdn--; vt_cntl_msg(2, "Thread object #%u deleted, leaving %u", tid, VTThrdn); VTTHRD_UNLOCK_ENV(); #else /* VT_MT || VT_HYB || VT_JAVA */ VTThrdn--; vt_cntl_msg(2, "Thread object #%u deleted, leaving %u", tid, VTThrdn); #endif /* VT_MT || VT_HYB || VT_JAVA */ }
void VTThrd_create(uint32_t tid, uint32_t ptid, const char* tname, uint8_t is_virtual) { VTThrd *thread; #if defined(VT_METR) uint32_t num_metrics = (uint32_t)vt_metric_num(); #endif /* VT_METR */ #if defined(VT_RUSAGE) uint32_t num_rusage = (uint32_t)vt_rusage_num(); #endif /* VT_RUSAGE */ thread = (VTThrd*)calloc(1, sizeof(VTThrd)); if ( thread == NULL ) vt_error(); /* set thread name, if available */ if ( tname == NULL ) { if ( tid == 0 ) tname = "Process"; else tname = "Thread"; } /* set thread name */ strncpy(thread->name, tname, sizeof(thread->name)); thread->name[sizeof(thread->name)-1] = '\0'; /* set thread name suffix */ if ( tid != 0 ) { #if (defined(VT_MT) || defined(VT_HYB) || defined(VT_JAVA)) VTTHRD_LOCK_ENV(); #endif /* VT_MT || VT_HYB || VT_JAVA */ snprintf(thread->name_suffix, sizeof(thread->name_suffix)-1, "%s:%d", VTThrdv[ptid]->name_suffix, ++(VTThrdv[ptid]->child_num)); #if (defined(VT_MT) || defined(VT_HYB) || defined(VT_JAVA)) VTTHRD_UNLOCK_ENV(); #endif /* VT_MT || VT_HYB || VT_JAVA */ } /* set parent ID of thread */ thread->parent_tid = ptid; /* set the virtual thread flag */ thread->is_virtual_thread = is_virtual; #if defined(VT_GETCPU) thread->cpuid_val = (uint32_t)-1; #endif /* VT_GETCPU */ #if defined(VT_RUSAGE) if ( num_rusage > 0 ) { /* create rusage object */ thread->ru_obj = vt_rusage_create(); /* initialize per-thread arrays for rusage counter values */ thread->ru_valv = (uint64_t*)calloc(num_rusage, sizeof(uint64_t)); if ( thread->ru_valv == NULL ) vt_error(); /* initialize next timestamp for reading rusage counters */ thread->ru_next_read = 0; } #endif /* VT_RUSAGE */ #if defined(VT_METR) if ( num_metrics > 0 && is_virtual == 0) { /* create event set */ thread->metv = vt_metric_create(); # if (defined(VT_MT) || defined(VT_HYB) || defined(VT_JAVA)) /* initialize per-thread arrays for counter offsets */ thread->offv = (uint64_t*)calloc(num_metrics, sizeof(uint64_t)); if ( thread->offv == NULL ) vt_error(); #endif /* VT_MT || VT_HYB || VT_JAVA */ /* initialize per-thread arrays for counter values */ thread->valv = (uint64_t*)calloc(num_metrics, sizeof(uint64_t)); if ( thread->valv == NULL ) vt_error(); } #endif /* VT_METR */ #if !defined(VT_DISABLE_RFG) /* initialize region filter and grouping management */ thread->rfg_regions = RFG_Regions_init(); if( thread->rfg_regions == NULL ) vt_error_msg("Could not initialize region filter and grouping management"); #endif /* VT_DISABLE_RFG */ /* enable tracing */ thread->trace_status = VT_TRACE_ON; VTThrdv[tid] = thread; #if (defined(VT_MT) || defined(VT_HYB) || defined(VT_JAVA)) VTTHRD_LOCK_ENV(); vt_cntl_msg(2, "Thread object #%u created, total number is %u", tid, VTThrdn); VTTHRD_UNLOCK_ENV(); #else /* VT_MT || VT_HYB || VT_JAVA */ vt_cntl_msg(2, "Thread object #%u created, total number is %u", tid, VTThrdn); #endif /* VT_MT || VT_HYB || VT_JAVA */ }