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: /* seanhalle@208: * In practice, probe operations are called from the app, from inside slaves seanhalle@209: * -- so have to be sure each probe is single-Slv 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@209: * to be isolated -- except then can't take any intervals that span Slvs, seanhalle@209: * and would have to transfer the probes to Master env when Slv 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@209: seanhalle@209: //============================ Helpers =========================== seanhalle@209: inline void seanhalle@209: doNothing() seanhalle@209: { seanhalle@209: } seanhalle@209: seanhalle@209: seanhalle@208: IntervalProbe * seanhalle@209: create_generic_probe( char *nameStr, SlaveVP *animSlv ) seanhalle@209: { seanhalle@208: VMSSemReq reqData; seanhalle@208: seanhalle@208: reqData.reqType = createProbe; seanhalle@208: reqData.nameStr = nameStr; seanhalle@208: seanhalle@209: VMS_WL__send_VMSSem_request( &reqData, animSlv ); seanhalle@208: seanhalle@209: return animSlv->dataRetFromReq; seanhalle@208: } seanhalle@208: seanhalle@208: /*Use this version from outside VMS -- it uses external malloc, and modifies seanhalle@209: * dynamic array, so can't be animated in a slave Slv 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@209: //============================ Fns def in header ======================= seanhalle@208: seanhalle@209: int32 seanhalle@209: VMS_impl__create_single_interval_probe( char *nameStr, SlaveVP *animSlv ) seanhalle@209: { IntervalProbe *newProbe; seanhalle@209: seanhalle@209: newProbe = create_generic_probe( nameStr, animSlv ); seanhalle@209: seanhalle@209: return newProbe->probeID; seanhalle@208: } seanhalle@208: seanhalle@209: int32 seanhalle@209: VMS_impl__create_histogram_probe( int32 numBins, float64 startValue, seanhalle@209: float64 binWidth, char *nameStr, SlaveVP *animSlv ) seanhalle@209: { IntervalProbe *newProbe; seanhalle@209: DblHist *hist; seanhalle@209: seanhalle@209: newProbe = create_generic_probe( nameStr, animSlv ); seanhalle@209: seanhalle@209: hist = makeDblHistogram( numBins, startValue, binWidth ); seanhalle@209: newProbe->hist = hist; seanhalle@209: return newProbe->probeID; seanhalle@209: } seanhalle@209: seanhalle@208: seanhalle@208: int32 seanhalle@209: VMS_impl__record_time_point_into_new_probe( char *nameStr, SlaveVP *animSlv) seanhalle@208: { IntervalProbe *newProbe; seanhalle@208: struct timeval *startStamp; seanhalle@208: float64 startSecs; seanhalle@208: seanhalle@209: newProbe = create_generic_probe( nameStr, animSlv ); 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: seanhalle@209: /*Only call from inside master or main startup/shutdown thread seanhalle@209: */ seanhalle@209: void seanhalle@209: VMS_impl__free_probe( IntervalProbe *probe ) seanhalle@209: { if( probe->hist != NULL ) freeDblHist( probe->hist ); seanhalle@209: if( probe->nameStr != NULL) VMS_int__free( probe->nameStr ); seanhalle@209: VMS_int__free( probe ); seanhalle@208: } seanhalle@208: seanhalle@208: seanhalle@208: void seanhalle@209: VMS_impl__index_probe_by_its_name( int32 probeID, SlaveVP *animSlv ) 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@209: seanhalle@208: IntervalProbe * seanhalle@209: VMS_impl__get_probe_by_name( char *probeName, SlaveVP *animSlv ) 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@209: * work locally, in the anim Slv seanhalle@208: */ seanhalle@208: void seanhalle@209: VMS_impl__record_sched_choice_into_probe( int32 probeID, SlaveVP *animatingSlv ) seanhalle@208: { IntervalProbe *probe; seanhalle@208: seanhalle@208: probe = _VMSMasterEnv->intervalProbes[ probeID ]; seanhalle@208: probe->schedChoiceWasRecorded = TRUE; seanhalle@209: probe->coreNum = animatingSlv->coreAnimatedBy; seanhalle@209: probe->slaveID = animatingSlv->procrID; seanhalle@209: probe->slaveCreateSecs = animatingSlv->createPtInSecs; seanhalle@208: } seanhalle@208: seanhalle@208: /*Everything is local to the animating procr, so no need for request, do seanhalle@209: * work locally, in the anim Slv 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@209: probe->startStamp = getTSCount(); seanhalle@208: } seanhalle@208: seanhalle@208: seanhalle@208: /*Everything is local to the animating procr, so no need for request, do seanhalle@209: * work locally, in the anim Slv seanhalle@209: * seanhalle@209: *This should be safe to run inside SlaveVP -- weird behavior will be due seanhalle@209: * to the logical error of having more than one interval open in overlapped. seanhalle@208: */ seanhalle@208: void seanhalle@208: VMS_impl__record_interval_end_in_probe( int32 probeID ) seanhalle@208: { IntervalProbe *probe; seanhalle@209: TSCount endStamp; seanhalle@208: seanhalle@209: endStamp = getTSCount(); seanhalle@209: seanhalle@208: DEBUG( dbgProbes, "record end of interval\n" ) seanhalle@209: seanhalle@208: probe = _VMSMasterEnv->intervalProbes[ probeID ]; seanhalle@209: probe->endStamp = endStamp; seanhalle@208: seanhalle@208: if( probe->hist != NULL ) seanhalle@209: { TSCount interval = probe->endStamp - probe->startStamp; seanhalle@208: //if the interval is sane, then add to histogram seanhalle@209: if( interval < probe->hist->endOfRange * 10 ) seanhalle@209: addToFloatHist( interval, probe->hist ); seanhalle@208: } seanhalle@208: } seanhalle@208: seanhalle@209: 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@209: probe->coreNum, probe->slaveID, probe->slaveCreateSecs ); 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: void seanhalle@208: VMS_impl__print_stats_of_all_probes() seanhalle@208: { seanhalle@208: forAllInDynArrayDo( _VMSMasterEnv->dynIntervalProbesInfo, seanhalle@209: &VMS_impl__print_stats_of_probe ); seanhalle@208: fflush( stdout ); seanhalle@208: }