seanhalle@208: /* seanhalle@208: * Copyright 2010 OpenSourceStewardshipFoundation seanhalle@208: * seanhalle@208: * Licensed under BSD seanhalle@208: */ seanhalle@208: seanhalle@208: #include seanhalle@208: #include seanhalle@208: #include seanhalle@208: seanhalle@208: #include "VMS.h" seanhalle@208: seanhalle@208: seanhalle@208: seanhalle@208: //==================== Probes ================= seanhalle@208: #ifdef STATS__USE_TSC_PROBES seanhalle@208: seanhalle@208: int32 seanhalle@208: VMS__create_histogram_probe( int32 numBins, float32 startValue, seanhalle@208: float32 binWidth, char *nameStr ) seanhalle@208: { IntervalProbe *newProbe; seanhalle@208: int32 idx; seanhalle@208: FloatHist *hist; seanhalle@208: seanhalle@208: idx = VMS__create_single_interval_probe( nameStr ); seanhalle@208: newProbe = _VMSMasterEnv->intervalProbes[ idx ]; seanhalle@208: seanhalle@208: hist = makeFloatHistogram( numBins, startValue, binWidth ); seanhalle@208: newProbe->hist = hist; seanhalle@208: return idx; seanhalle@208: } seanhalle@208: seanhalle@208: void seanhalle@208: VMS_impl__record_interval_start_in_probe( int32 probeID ) seanhalle@208: { IntervalProbe *probe; seanhalle@208: seanhalle@208: probe = _VMSMasterEnv->intervalProbes[ probeID ]; seanhalle@208: probe->startStamp = getTSCount(); seanhalle@208: } seanhalle@208: seanhalle@208: void seanhalle@208: VMS_impl__record_interval_end_in_probe( int32 probeID ) seanhalle@208: { IntervalProbe *probe; seanhalle@208: TSCount endStamp; seanhalle@208: seanhalle@208: endStamp = getTSCount(); seanhalle@208: seanhalle@208: probe = _VMSMasterEnv->intervalProbes[ probeID ]; seanhalle@208: probe->endStamp = endStamp; seanhalle@208: seanhalle@208: if( probe->hist != NULL ) seanhalle@208: { TSCount interval = probe->endStamp - probe->startStamp; seanhalle@208: //if the interval is sane, then add to histogram seanhalle@208: if( interval < probe->hist->endOfRange * 10 ) seanhalle@208: addToFloatHist( interval, probe->hist ); seanhalle@208: } seanhalle@208: } seanhalle@208: seanhalle@208: void seanhalle@208: VMS_impl__print_stats_of_probe( int32 probeID ) seanhalle@208: { IntervalProbe *probe; seanhalle@208: seanhalle@208: probe = _VMSMasterEnv->intervalProbes[ probeID ]; seanhalle@208: seanhalle@208: if( probe->hist == NULL ) seanhalle@208: { seanhalle@208: printf("probe: %s, interval: %.6lf\n", probe->nameStr,probe->interval); seanhalle@208: } seanhalle@208: seanhalle@208: else seanhalle@208: { seanhalle@208: printf( "probe: %s\n", probe->nameStr ); seanhalle@208: printFloatHist( probe->hist ); seanhalle@208: } seanhalle@208: } seanhalle@208: #else seanhalle@208: seanhalle@208: /* seanhalle@208: * In practice, probe operations are called from the app, from inside slaves seanhalle@208: * -- so have to be sure each probe is single-VP owned, and be sure that seanhalle@208: * any place common structures are modified it's done inside the master. seanhalle@208: * So -- the only place common structures are modified is during creation. seanhalle@208: * after that, all mods are to individual instances. seanhalle@208: * seanhalle@208: * Thniking perhaps should change the semantics to be that probes are seanhalle@208: * attached to the virtual processor -- and then everything is guaranteed seanhalle@208: * to be isolated -- except then can't take any intervals that span VPs, seanhalle@208: * and would have to transfer the probes to Master env when VP dissipates.. seanhalle@208: * gets messy.. seanhalle@208: * seanhalle@208: * For now, just making so that probe creation causes a suspend, so that seanhalle@208: * the dynamic array in the master env is only modified from the master seanhalle@208: * seanhalle@208: */ seanhalle@208: IntervalProbe * seanhalle@208: create_generic_probe( char *nameStr, SlaveVP *animPr ) seanhalle@208: { seanhalle@208: VMSSemReq reqData; seanhalle@208: seanhalle@208: reqData.reqType = createProbe; seanhalle@208: reqData.nameStr = nameStr; seanhalle@208: seanhalle@208: VMS_WL__send_VMSSem_request( &reqData, animPr ); seanhalle@208: seanhalle@208: return animPr->dataRetFromReq; seanhalle@208: } seanhalle@208: seanhalle@208: /*Use this version from outside VMS -- it uses external malloc, and modifies seanhalle@208: * dynamic array, so can't be animated in a slave VP seanhalle@208: */ seanhalle@208: IntervalProbe * seanhalle@208: ext__create_generic_probe( char *nameStr ) seanhalle@208: { IntervalProbe *newProbe; seanhalle@208: int32 nameLen; seanhalle@208: seanhalle@208: newProbe = malloc( sizeof(IntervalProbe) ); seanhalle@208: nameLen = strlen( nameStr ); seanhalle@208: newProbe->nameStr = malloc( nameLen ); seanhalle@208: memcpy( newProbe->nameStr, nameStr, nameLen ); seanhalle@208: newProbe->hist = NULL; seanhalle@208: newProbe->schedChoiceWasRecorded = FALSE; seanhalle@208: newProbe->probeID = seanhalle@208: addToDynArray( newProbe, _VMSMasterEnv->dynIntervalProbesInfo ); seanhalle@208: seanhalle@208: return newProbe; seanhalle@208: } seanhalle@208: seanhalle@208: seanhalle@208: /*Only call from inside master or main startup/shutdown thread seanhalle@208: */ seanhalle@208: void seanhalle@208: VMS_impl__free_probe( IntervalProbe *probe ) seanhalle@208: { if( probe->hist != NULL ) freeDblHist( probe->hist ); seanhalle@208: if( probe->nameStr != NULL) VMS_int__free( probe->nameStr ); seanhalle@208: VMS_int__free( probe ); seanhalle@208: } seanhalle@208: seanhalle@208: seanhalle@208: int32 seanhalle@208: VMS_impl__record_time_point_into_new_probe( char *nameStr, SlaveVP *animPr) seanhalle@208: { IntervalProbe *newProbe; seanhalle@208: struct timeval *startStamp; seanhalle@208: float64 startSecs; seanhalle@208: seanhalle@208: newProbe = create_generic_probe( nameStr, animPr ); seanhalle@208: newProbe->endSecs = 0; seanhalle@208: seanhalle@208: gettimeofday( &(newProbe->startStamp), NULL); seanhalle@208: seanhalle@208: //turn into a double seanhalle@208: startStamp = &(newProbe->startStamp); seanhalle@208: startSecs = startStamp->tv_sec + ( startStamp->tv_usec / 1000000.0 ); seanhalle@208: newProbe->startSecs = startSecs; seanhalle@208: seanhalle@208: return newProbe->probeID; seanhalle@208: } seanhalle@208: seanhalle@208: int32 seanhalle@208: VMS_ext_impl__record_time_point_into_new_probe( char *nameStr ) seanhalle@208: { IntervalProbe *newProbe; seanhalle@208: struct timeval *startStamp; seanhalle@208: float64 startSecs; seanhalle@208: seanhalle@208: newProbe = ext__create_generic_probe( nameStr ); seanhalle@208: newProbe->endSecs = 0; seanhalle@208: seanhalle@208: gettimeofday( &(newProbe->startStamp), NULL); seanhalle@208: seanhalle@208: //turn into a double seanhalle@208: startStamp = &(newProbe->startStamp); seanhalle@208: startSecs = startStamp->tv_sec + ( startStamp->tv_usec / 1000000.0 ); seanhalle@208: newProbe->startSecs = startSecs; seanhalle@208: seanhalle@208: return newProbe->probeID; seanhalle@208: } seanhalle@208: seanhalle@208: int32 seanhalle@208: VMS_impl__create_single_interval_probe( char *nameStr, SlaveVP *animPr ) seanhalle@208: { IntervalProbe *newProbe; seanhalle@208: seanhalle@208: newProbe = create_generic_probe( nameStr, animPr ); seanhalle@208: seanhalle@208: return newProbe->probeID; seanhalle@208: } seanhalle@208: seanhalle@208: int32 seanhalle@208: VMS_impl__create_histogram_probe( int32 numBins, float64 startValue, seanhalle@208: float64 binWidth, char *nameStr, SlaveVP *animPr ) seanhalle@208: { IntervalProbe *newProbe; seanhalle@208: DblHist *hist; seanhalle@208: seanhalle@208: newProbe = create_generic_probe( nameStr, animPr ); seanhalle@208: seanhalle@208: hist = makeDblHistogram( numBins, startValue, binWidth ); seanhalle@208: newProbe->hist = hist; seanhalle@208: return newProbe->probeID; seanhalle@208: } seanhalle@208: seanhalle@208: void seanhalle@208: VMS_impl__index_probe_by_its_name( int32 probeID, SlaveVP *animPr ) seanhalle@208: { IntervalProbe *probe; seanhalle@208: seanhalle@208: //TODO: fix this To be in Master -- race condition seanhalle@208: probe = _VMSMasterEnv->intervalProbes[ probeID ]; seanhalle@208: seanhalle@208: addValueIntoTable(probe->nameStr, probe, _VMSMasterEnv->probeNameHashTbl); seanhalle@208: } seanhalle@208: seanhalle@208: IntervalProbe * seanhalle@208: VMS_impl__get_probe_by_name( char *probeName, SlaveVP *animPr ) seanhalle@208: { seanhalle@208: //TODO: fix this To be in Master -- race condition seanhalle@208: return getValueFromTable( probeName, _VMSMasterEnv->probeNameHashTbl ); seanhalle@208: } seanhalle@208: seanhalle@208: seanhalle@208: /*Everything is local to the animating procr, so no need for request, do seanhalle@208: * work locally, in the anim Pr seanhalle@208: */ seanhalle@208: void seanhalle@208: VMS_impl__record_sched_choice_into_probe( int32 probeID, SlaveVP *animatingPr ) seanhalle@208: { IntervalProbe *probe; seanhalle@208: seanhalle@208: probe = _VMSMasterEnv->intervalProbes[ probeID ]; seanhalle@208: probe->schedChoiceWasRecorded = TRUE; seanhalle@208: probe->coreNum = animatingPr->coreAnimatedBy; seanhalle@208: probe->procrID = animatingPr->procrID; seanhalle@208: probe->procrCreateSecs = animatingPr->createPtInSecs; seanhalle@208: } seanhalle@208: seanhalle@208: /*Everything is local to the animating procr, so no need for request, do seanhalle@208: * work locally, in the anim Pr seanhalle@208: */ seanhalle@208: void seanhalle@208: VMS_impl__record_interval_start_in_probe( int32 probeID ) seanhalle@208: { IntervalProbe *probe; seanhalle@208: seanhalle@208: DEBUG( dbgProbes, "record start of interval\n" ) seanhalle@208: probe = _VMSMasterEnv->intervalProbes[ probeID ]; seanhalle@208: gettimeofday( &(probe->startStamp), NULL ); seanhalle@208: } seanhalle@208: seanhalle@208: seanhalle@208: /*Everything is local to the animating procr, so no need for request, do seanhalle@208: * work locally, in the anim Pr seanhalle@208: */ seanhalle@208: void seanhalle@208: VMS_impl__record_interval_end_in_probe( int32 probeID ) seanhalle@208: { IntervalProbe *probe; seanhalle@208: struct timeval *endStamp, *startStamp; seanhalle@208: float64 startSecs, endSecs; seanhalle@208: seanhalle@208: DEBUG( dbgProbes, "record end of interval\n" ) seanhalle@208: //possible seg-fault if array resized by diff core right after this seanhalle@208: // one gets probe..? Something like that? Might be safe.. don't care seanhalle@208: probe = _VMSMasterEnv->intervalProbes[ probeID ]; seanhalle@208: gettimeofday( &(probe->endStamp), NULL); seanhalle@208: seanhalle@208: //now turn into an interval held in a double seanhalle@208: startStamp = &(probe->startStamp); seanhalle@208: endStamp = &(probe->endStamp); seanhalle@208: seanhalle@208: startSecs = startStamp->tv_sec + ( startStamp->tv_usec / 1000000.0 ); seanhalle@208: endSecs = endStamp->tv_sec + ( endStamp->tv_usec / 1000000.0 ); seanhalle@208: seanhalle@208: probe->interval = endSecs - startSecs; seanhalle@208: probe->startSecs = startSecs; seanhalle@208: probe->endSecs = endSecs; seanhalle@208: seanhalle@208: if( probe->hist != NULL ) seanhalle@208: { seanhalle@208: //if the interval is sane, then add to histogram seanhalle@208: if( probe->interval < probe->hist->endOfRange * 10 ) seanhalle@208: addToDblHist( probe->interval, probe->hist ); seanhalle@208: } seanhalle@208: } seanhalle@208: seanhalle@208: void seanhalle@208: print_probe_helper( IntervalProbe *probe ) seanhalle@208: { seanhalle@208: printf( "\nprobe: %s, ", probe->nameStr ); seanhalle@208: seanhalle@208: seanhalle@208: if( probe->schedChoiceWasRecorded ) seanhalle@208: { printf( "coreNum: %d, procrID: %d, procrCreated: %0.6f | ", seanhalle@208: probe->coreNum, probe->procrID, probe->procrCreateSecs ); seanhalle@208: } seanhalle@208: seanhalle@208: if( probe->endSecs == 0 ) //just a single point in time seanhalle@208: { seanhalle@208: printf( " time point: %.6f\n", seanhalle@208: probe->startSecs - _VMSMasterEnv->createPtInSecs ); seanhalle@208: } seanhalle@208: else if( probe->hist == NULL ) //just an interval seanhalle@208: { seanhalle@208: printf( " startSecs: %.6f interval: %.6f\n", seanhalle@208: (probe->startSecs - _VMSMasterEnv->createPtInSecs), probe->interval); seanhalle@208: } seanhalle@208: else //a full histogram of intervals seanhalle@208: { seanhalle@208: printDblHist( probe->hist ); seanhalle@208: } seanhalle@208: } seanhalle@208: seanhalle@208: //TODO: change so pass around pointer to probe instead of its array-index.. seanhalle@208: // will eliminate chance for timing of resize to cause problems with the seanhalle@208: // lookup -- even though don't think it actually can cause problems.. seanhalle@208: // there's no need to pass index around -- have hash table for names, and seanhalle@208: // only need it once, then have ptr to probe.. the thing about enum the seanhalle@208: // index and use that as name is clunky in practice -- just hash. seanhalle@208: void seanhalle@208: VMS_impl__print_stats_of_probe( int32 probeID ) seanhalle@208: { IntervalProbe *probe; seanhalle@208: seanhalle@208: probe = _VMSMasterEnv->intervalProbes[ probeID ]; seanhalle@208: seanhalle@208: print_probe_helper( probe ); seanhalle@208: } seanhalle@208: seanhalle@208: seanhalle@208: inline void doNothing(){}; seanhalle@208: seanhalle@208: void seanhalle@208: generic_print_probe( void *_probe ) seanhalle@208: { seanhalle@208: IntervalProbe *probe = (IntervalProbe *)_probe; seanhalle@208: seanhalle@208: //TODO segfault in printf seanhalle@208: //print_probe_helper( probe ); seanhalle@208: } seanhalle@208: seanhalle@208: void seanhalle@208: VMS_impl__print_stats_of_all_probes() seanhalle@208: { seanhalle@208: forAllInDynArrayDo( _VMSMasterEnv->dynIntervalProbesInfo, seanhalle@208: &generic_print_probe ); seanhalle@208: fflush( stdout ); seanhalle@208: } seanhalle@208: #endif