/**************************************************************************** ** TAU Portable Profiling Package ** ** http://www.acl.lanl.gov/tau ** ***************************************************************************** ** Copyright 1999 ** ** Department of Computer and Information Science, University of Oregon ** ** Advanced Computing Laboratory, Los Alamos National Laboratory ** ****************************************************************************/ /*************************************************************************** ** File : TauKtau.cpp ** ** Description : TAU Kernel Profiling ** ** Author : Surave Suthikulpanit ** ** : Aroon Nataraj ** ** Contact : suravee@cs.uoregon.edu ** ** : anataraj@cs.uoregon.edu ** ** Flags : Compile with ** ** -DTAUKTAU -DTAUKTAU_MERGE ** ** Documentation : ** ***************************************************************************/ #include #include #include #include #include #include #include #include #include "Profile/Profiler.h" #include "Profile/TauKtau.h" #include #include "Profile/KtauProfiler.h" using namespace std; #define LINE_SIZE 1024 #define OUTPUT_NAME_SIZE 100 #define DEBUG 0 #define maxof(x,y) ((x>=y)?x:y) /* For sys_gettid syscall */ //_syscall0(pid_t,gettid); #include extern "C" int ktau_diff_profiles(ktau_output* plist1, int size1, ktau_output* plist2, int size2, ktau_output** outlist); /*-------------------------- CON/DESTRUCTOR ---------------------------*/ /* * Function : TauKtau::TauKtau * Description : Constructor */ TauKtau::TauKtau(KtauSymbols& sym):KtauSym(sym) { startBuf = NULL; stopBuf = NULL; diffOutput = NULL; startSize= 0; stopSize = 0; outSize = 0; //ThisKtauOutputInfo.pid = gettid(); ThisKtauOutputInfo.pid = syscall(__NR_gettid); //ThisKtauOutputInfo.pid = getpid(); ThisKtauOutputInfo.templ_fun_counter = 0; ThisKtauOutputInfo.user_ev_counter = 0; startBufTWO = NULL; stopBufTWO = NULL; diffOutputTWO = NULL; startSizeTWO = 0; stopSizeTWO = 0; outSizeTWO = 0; } /* * Function : TauKtau::~TauKtau * Description : Destructor */ TauKtau::~TauKtau() { free(startBuf); free(stopBuf); if(diffOutput) { for(int i=0 ; ient_lst); free(diffOutput); } startSize= 0; stopSize = 0; outSize = 0; startBuf = NULL; stopBuf = NULL; diffOutput = NULL; startSizeTWO = 0; stopSizeTWO = 0; outSizeTWO = 0; startBufTWO = NULL; stopBufTWO = NULL; diffOutputTWO = NULL; } /*----------------------------- PUBLIC --------------------------------*/ int TauKtau::RegisterFork(TauKtau* pKernProf, enum TauFork_t opcode) { int i = 0; if(DEBUG)printf("TauKtau::RegisterFork: Enter\n"); if(DEBUG)printf("TauKtau::RegisterFork: Calling Dest ~TauKtau\n"); //Call the destructor to cleanup pKernProf->~TauKtau(); if(DEBUG)printf("TauKtau::RegisterFork: Redoing Cons Steps TauKtau\n"); //Redo stuff done in the constructor pKernProf->startBuf = NULL; pKernProf->stopBuf = NULL; pKernProf->diffOutput = NULL; pKernProf->startSize= 0; pKernProf->stopSize = 0; pKernProf->outSize = 0; pKernProf->ThisKtauOutputInfo.pid = syscall(__NR_gettid); //pKernProf->ThisKtauOutputInfo.pid = gettid(); //pKernProf->ThisKtauOutputInfo.pid = getpid(); pKernProf->ThisKtauOutputInfo.templ_fun_counter = 0; pKernProf->ThisKtauOutputInfo.user_ev_counter = 0; if(DEBUG)printf("TauKtau::RegisterFork: Calling StartKProfile\n"); //Do a StartKProfile i = pKernProf->StartKProfile(); if(DEBUG)printf("TauKtau::RegisterFork: Exit\n"); return i; } /* * Function : TauKtau::StartKprofile * Description : Read the start profile */ int TauKtau::StartKProfile() { //int selfpid = -1; int selfpid = 0; //ALL //startSize = read_size(KTAU_PROFILE, 1, &selfpid, 1, 0, NULL, -1); //startSize = read_size(KTAU_PROFILE, 1, &selfpid, 1, 0, NULL, 2); startSize = read_size(KTAU_TYPE_PROFILE, 0 /*ALL*/, &selfpid, 0/*ALL*/, 0, NULL, -1); if(startSize <= 0) { return -1; } startBuf = (char*)malloc(startSize*sizeof(ktau_output)); if(!startBuf) { perror("TauKtau::StartKProfile: malloc"); return -1; } startSizeTWO = startSize*sizeof(ktau_output); startBufTWO = (char*) malloc(startSizeTWO); //startSize = read_data(KTAU_PROFILE, 1, &selfpid, 1, startBuf, startSize, 0, NULL); startSize = read_data(KTAU_TYPE_PROFILE, 0 /*ALL*/, &selfpid, 0/*ALL*/, startBuf, startSize, 0, NULL); if(startSize <= 0) { free(startBuf); startBuf = NULL; return -1; } memcpy(startBufTWO, startBuf, startSizeTWO); return startSize; } /* * Function : TauKtau::StartKprofile * Description : Read the stop, diff, and dump profile */ int TauKtau::StopKProfile() { int i=0; int ret = 0; //int selfpid = -1; int selfpid = 0; //ALL //stopSize = read_size(KTAU_PROFILE, 1, &selfpid, 1, 0, NULL, 2); stopSize = read_size(KTAU_TYPE_PROFILE, 0/*ALL*/, &selfpid, 0/*ALL*/, 0, NULL, -1); if(stopSize <= 0) { return -1; } stopBuf = (char*)malloc(stopSize*sizeof(ktau_output)); if(!stopBuf) { perror("TauKtau::StopKProfile: malloc"); return -1; } int stopSizeTWO = stopSize*sizeof(ktau_output); stopBufTWO = (char*) malloc(stopSizeTWO); //stopSize = read_data(KTAU_PROFILE, 1, &selfpid, 1, stopBuf, stopSize, 0, NULL); stopSize = read_data(KTAU_TYPE_PROFILE, 0/*ALL*/, &selfpid, 0/*ALL*/, stopBuf, stopSize, 0, NULL); if(stopSize <= 0) { free(stopBuf); stopBuf = NULL; return -1; } memcpy(stopBufTWO, stopBuf, stopSizeTWO); if((outSize = DiffKProfile()) < 0){ return(-1); } if((outSizeTWO = DiffKProfileTWO(startBufTWO, stopBufTWO, startSizeTWO, stopSizeTWO, &diffOutputTWO)) < 0){ return(-1); } return(ret); } int TauKtau::DumpKProfileOut() { int ret = 0; if((ret = DumpKProfileTWO(outSizeTWO, diffOutputTWO, "perprocess")) < 0){ return(-1); }; /* AN: TODO: Disabling till a leader election method is settled on ktau_output* aggr_profs = NULL; AggrKProfiles(startBufTWO, startSizeTWO, stopBufTWO, stopSizeTWO, &aggr_profs); if(DumpKProfileTWO(1, aggr_profs, "kernelwide") < 0){ return(-1); } */ return 0; } int TauKtau::AggrKProfiles(char* start, int startSz, char* stop, int stopSz, ktau_output** aggrprofs) { int i,j,k,diff_count; ktau_output *startOutput; ktau_output *stopOutput; long startProcNum = 0; long stopProcNum = 0; startProcNum = unpack_bindata(KTAU_TYPE_PROFILE, start, startSz, &startOutput); if(startProcNum < 0) { return -1; } ktau_output* paggr_start_prof = (ktau_output*)calloc(sizeof(ktau_output),1); if(!paggr_start_prof) { printf("calloc ret null.\n"); goto free_out; } paggr_start_prof->ent_lst = (o_ent*)calloc(sizeof(o_ent)*2048,1); if(!paggr_start_prof->ent_lst) { printf("calloc ret null.\n"); free(paggr_start_prof); goto free_out; } aggr_many_profiles(startOutput, startProcNum, 2048, paggr_start_prof); paggr_start_prof->pid = 0; stopProcNum = unpack_bindata(KTAU_TYPE_PROFILE, stop, stopSz, &stopOutput); if(stopProcNum < 0) { return -1; } { //extra brace to make gcc 4.1 happy ktau_output* paggr_prof = (ktau_output*)calloc(sizeof(ktau_output),1); if(!paggr_prof) { printf("calloc ret null.\n"); goto free_out; } paggr_prof->ent_lst = (o_ent*)calloc(sizeof(o_ent)*2048,1); if(!paggr_prof->ent_lst) { printf("calloc ret null.\n"); free(paggr_prof); goto free_out; } aggr_many_profiles(stopOutput, stopProcNum, 2048, paggr_prof); paggr_prof->pid = 0; *aggrprofs = (ktau_output*)calloc(sizeof(ktau_output),1); (*aggrprofs)->ent_lst = (o_ent*)calloc(sizeof(o_ent)*2048,1); return ktau_diff_profiles(paggr_start_prof, 1, paggr_prof, 1, aggrprofs); }//to make gcc 4.1 happy! free_out: return -1; } int TauKtau::DumpKProfileTWO(int outSize, ktau_output* diffOutput, char* tag) { int i=0,j=0; char output_path[OUTPUT_NAME_SIZE]; o_ent *ptr; unsigned int cur_index = 0; unsigned int user_ev_counter = 0; unsigned int templ_fun_counter = 0; if((outSizeTWO <= 0)) { // || (stopSizeTWO <= 0) || (startSizeTWO <= 0)) { return -1; } /* ktau_output* tmp_diffOutput = diffOutput; diffOutput = diffOutputTWO; */ /* int tmp_outSize = outSize; outSize = outSizeTWO; int tmp_startSize = startSize; startSize = startSizeTWO; int tmp_stopSize = stopSize; stopSize = stopSizeTWO; */ /* * Create output directory ./Kprofile */ sprintf(output_path,"./Kprofile.%d.%d.%s", RtsLayer::myNode(), RtsLayer::myThread(), tag); if(mkdir(output_path,777) == -1){ perror("TauKtau::DumpKProfile: mkdir"); if(errno != EEXIST) { //ignore already-exists errors return(-1); } } if(chmod(output_path, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH ) != 0) { perror("TauKtau::DumpKProfile: chmod"); return(-1); } /* * Dumping output to the output file "./Kprofile./profile..0.0" */ // Data format : // %d templated_functions // "%s %s" %ld %G %G // funcname type numcalls Excl Incl // %d aggregates // /* For Each Process */ for(i=0;isize; j++){ ptr = (((diffOutput)+i)->ent_lst)+j; if(ptr->index < 300 || ptr->index > 399){ templ_fun_counter++; }else{ user_ev_counter++; } } int context = 0; if((diffOutput+i)->pid == ThisKtauOutputInfo.pid) { context = 1; } sprintf(output_path,"./Kprofile.%d.%d.%s/profile.%u.0.%d",RtsLayer::myNode(),RtsLayer::myThread(), tag, (diffOutput+i)->pid, context); ofstream fs_output (output_path , ios::out); if(!fs_output.is_open()){ cout << "Error opening file: " << output_path << "\n"; return(-1); } /* OUTPUT: Templated function */ fs_output << templ_fun_counter << " templated_functions" << endl; fs_output << "# Name Calls Subrs Excl Incl ProfileCalls" << endl; for(j=0;j < (diffOutput+i)->size; j++){ ptr = (((diffOutput)+i)->ent_lst)+j; string& func_name = KtauSym.MapSym(ptr->entry.addr); if(ptr->index < 300 || ptr->index > 399){ fs_output << "\"" << func_name << "()\" " //Name << ptr->entry.data.timer.count << " " //Calls << 0 << " " //Subrs << (double)ptr->entry.data.timer.excl/KTauGetMHz() //Excl //<< (double)ptr->entry.data.timer.excl //Excl << " " << (double)ptr->entry.data.timer.incl/KTauGetMHz() //Incl //<< (double)ptr->entry.data.timer.incl //Incl << " " << 0 << " "; //ProfileCalls if(strstr(func_name.c_str(), "schedule")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_SCHEDULE\"" << endl; //}else if(!strcmp("__run_timers",func_name.c_str())){ // fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_RUN_TIMERS\"" << endl; }else if(strstr(func_name.c_str(), "page_fault")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_EXCEPTION\"" << endl; }else if(strstr(func_name.c_str(), "IRQ")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_IRQ\"" << endl; }else if(strstr(func_name.c_str(), "run_timers")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_BH\"" << endl; }else if(strstr(func_name.c_str(), "workqueue")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_BH\"" << endl; }else if(strstr(func_name.c_str(), "tasklet")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_BH\"" << endl; //}else if(!strcmp("__do_softirq",func_name.c_str())){ // fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_DO_SOFTIRQ\"" << endl; }else if(strstr(func_name.c_str(), "softirq")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_BH\"" << endl; }else if(strstr(func_name.c_str(), "sys_")){ if(strstr(func_name.c_str(), "sock")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_SYSCALL | KTAU_SOCK\"" << endl; } else if(strstr(func_name.c_str(), "read")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_SYSCALL | KTAU_IO\"" << endl; } else if(strstr(func_name.c_str(), "write")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_SYSCALL | KTAU_IO\"" << endl; } else if(strstr(func_name.c_str(), "send")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_SYSCALL | KTAU_IO\"" << endl; } else if(strstr(func_name.c_str(), "recv")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_SYSCALL | KTAU_IO\"" << endl; } else { fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_SYSCALL\"" << endl; } }else if(strstr(func_name.c_str(), "tcp")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_TCP\"" << endl; }else if(strstr(func_name.c_str(), "icmp")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_ICMP\"" << endl; }else if(strstr(func_name.c_str(), "sock")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_SOCK\"" << endl; }else{ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_DEFAULT\"" << endl; } } } /* OUTPUT: Aggregates*/ fs_output << 0 << " aggregates" << endl; /* OUTPUT: User-events*/ fs_output << user_ev_counter << " userevents" << endl; fs_output << "# eventname numevents max min mean sumsqr"<< endl; for(j=0;j < (diffOutput+i)->size; j++){ ptr = (((diffOutput)+i)->ent_lst)+j; string& ev_name = KtauSym.MapSym(ptr->entry.addr); if(ptr->index >= 300 && ptr->index <= 399 ){ if(ptr->entry.data.timer.count != 0){ fs_output << "\"Event_" << ev_name << "()\" " //eventname << ptr->entry.data.timer.count << " " //numevents << 1 << " " //max << 1 << " " //min << 1 << " " //mean << 1 << " " //sumsqr << endl; }else{ fs_output << "\"Event_" << ev_name << "()\" " //eventname << ptr->entry.data.timer.count << " " //numevents << 0 << " " //max << 0 << " " //min << 0 << " " //mean << 0 << " " //sumsqr << endl; } } } fs_output.close(); } /* diffOutput = tmp_diffOutput; startSize = tmp_startSize; stopSize = tmp_stopSize; outSize = tmp_outSize; */ return 0; } /*----------------------------- PRIVATE -------------------------------*/ /* * Function : TauKtau::DumpKprofile * Description : Dump the profile to Kprofile./ */ int TauKtau::DumpKProfile(void) { int i=0,j=0; char output_path[OUTPUT_NAME_SIZE]; o_ent *ptr; unsigned int cur_index = 0; unsigned int user_ev_counter = 0; unsigned int templ_fun_counter = 0; if((outSize <= 0) || (stopSize <= 0) || (startSize <= 0)) { return -1; } /* * Create output directory ./Kprofile */ sprintf(output_path,"./Kprofile.%d.%d", RtsLayer::myNode(), RtsLayer::myThread()); if(mkdir(output_path,777) == -1){ perror("TauKtau::DumpKProfile: mkdir"); if(errno != EEXIST) { //ignore already-exists errors return(-1); } } if(chmod(output_path, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH ) != 0) { perror("TauKtau::DumpKProfile: chmod"); return(-1); } /* * Dumping output to the output file "./Kprofile./profile..0.0" */ // Data format : // %d templated_functions // "%s %s" %ld %G %G // funcname type numcalls Excl Incl // %d aggregates // /* For Each Process */ for(i=0;isize; j++){ ptr = (((diffOutput)+i)->ent_lst)+j; if(ptr->index < 300 || ptr->index > 399){ templ_fun_counter++; }else{ user_ev_counter++; } } int context = 0; if((diffOutput+i)->pid == ThisKtauOutputInfo.pid) { context = 1; } sprintf(output_path,"./Kprofile.%d.%d/profile.%u.0.%d",RtsLayer::myNode(),RtsLayer::myThread(),(diffOutput+i)->pid, context); ofstream fs_output (output_path , ios::out); if(!fs_output.is_open()){ cout << "Error opening file: " << output_path << "\n"; return(-1); } /* OUTPUT: Templated function */ fs_output << templ_fun_counter << " templated_functions" << endl; fs_output << "# Name Calls Subrs Excl Incl ProfileCalls" << endl; for(j=0;j < (diffOutput+i)->size; j++){ ptr = (((diffOutput)+i)->ent_lst)+j; string& func_name = KtauSym.MapSym(ptr->entry.addr); if(ptr->index < 300 || ptr->index > 399){ fs_output << "\"" << func_name << "()\" " //Name << ptr->entry.data.timer.count << " " //Calls << 0 << " " //Subrs << (double)ptr->entry.data.timer.excl/KTauGetMHz() //Excl //<< (double)ptr->entry.data.timer.excl //Excl << " " << (double)ptr->entry.data.timer.incl/KTauGetMHz() //Incl //<< (double)ptr->entry.data.timer.incl //Incl << " " << 0 << " "; //ProfileCalls if(strstr(func_name.c_str(), "schedule")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_SCHEDULE\"" << endl; //}else if(!strcmp("__run_timers",func_name.c_str())){ // fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_RUN_TIMERS\"" << endl; }else if(strstr(func_name.c_str(), "page_fault")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_EXCEPTION\"" << endl; }else if(strstr(func_name.c_str(), "IRQ")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_IRQ\"" << endl; }else if(strstr(func_name.c_str(), "run_timers")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_BH\"" << endl; }else if(strstr(func_name.c_str(), "workqueue")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_BH\"" << endl; }else if(strstr(func_name.c_str(), "tasklet")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_BH\"" << endl; //}else if(!strcmp("__do_softirq",func_name.c_str())){ // fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_DO_SOFTIRQ\"" << endl; }else if(strstr(func_name.c_str(), "softirq")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_BH\"" << endl; }else if(strstr(func_name.c_str(), "sys_")){ if(strstr(func_name.c_str(), "sock")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_SYSCALL | KTAU_SOCK\"" << endl; } else if(strstr(func_name.c_str(), "read")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_SYSCALL | KTAU_IO\"" << endl; } else if(strstr(func_name.c_str(), "write")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_SYSCALL | KTAU_IO\"" << endl; } else if(strstr(func_name.c_str(), "send")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_SYSCALL | KTAU_IO\"" << endl; } else if(strstr(func_name.c_str(), "recv")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_SYSCALL | KTAU_IO\"" << endl; } else { fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_SYSCALL\"" << endl; } }else if(strstr(func_name.c_str(), "tcp")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_TCP\"" << endl; }else if(strstr(func_name.c_str(), "icmp")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_ICMP\"" << endl; }else if(strstr(func_name.c_str(), "sock")){ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_SOCK\"" << endl; }else{ fs_output << "GROUP=\"TAU_KERNEL_MERGE | KTAU_DEFAULT\"" << endl; } } } /* OUTPUT: Aggregates*/ fs_output << 0 << " aggregates" << endl; /* OUTPUT: User-events*/ fs_output << user_ev_counter << " userevents" << endl; fs_output << "# eventname numevents max min mean sumsqr"<< endl; for(j=0;j < (diffOutput+i)->size; j++){ ptr = (((diffOutput)+i)->ent_lst)+j; string& ev_name = KtauSym.MapSym(ptr->entry.addr); if(ptr->index >= 300 && ptr->index <= 399 ){ if(ptr->entry.data.timer.count != 0){ fs_output << "\"Event_" << ev_name << "()\" " //eventname << ptr->entry.data.timer.count << " " //numevents << 1 << " " //max << 1 << " " //min << 1 << " " //mean << 1 << " " //sumsqr << endl; }else{ fs_output << "\"Event_" << ev_name << "()\" " //eventname << ptr->entry.data.timer.count << " " //numevents << 0 << " " //max << 0 << " " //min << 0 << " " //mean << 0 << " " //sumsqr << endl; } } } fs_output.close(); } return 0; } /*----------------------------- PRIVATE -------------------------------*/ /* * Function : diff_h_ent * Description : Diffing h_ent for each o_ent */ int diff_h_ent(o_ent *o1, o_ent *o2){ /* * Comparing h_ent of KTAU_TIMER type. */ if(o1->entry.type == o2->entry.type && o1->entry.type == KTAU_TIMER){ if(o1->entry.addr == o2->entry.addr){ o2->entry.data.timer.count -= o1->entry.data.timer.count; o2->entry.data.timer.incl -= o1->entry.data.timer.incl; o2->entry.data.timer.excl -= o1->entry.data.timer.excl; return(0); } } return(-1); } /* * Function : diff_ktau_output * Description : Diffing stop and start of each ktau_output and * store the result in out. */ int diff_ktau_output(ktau_output *start, ktau_output *stop, ktau_output *out){ int i,j,k; o_ent *st; o_ent *sp; out->ent_lst = (o_ent*)malloc(sizeof(o_ent)*stop->size); /* * For each o_ent, we have to check the hash-index. If the index * doesn't exist in out, then just diff with 0. * */ for(i=0,j=0,k=0; isize || jsize;){ st=(start->ent_lst+i); sp=(stop->ent_lst+j); if(st->index == sp->index){ if(diff_h_ent(st,sp)){ return(-1); } memcpy(((out->ent_lst)+k), ((stop->ent_lst)+j), sizeof(o_ent)); i++;j++;k++; }else{ memcpy(((out->ent_lst)+k), ((stop->ent_lst)+j), sizeof(o_ent)); j++;k++; } } return(k); } int TauKtau::DiffKProfileTWO(char* startB, char* stopB, int startSz, int stopSz, ktau_output** pdiffOut) { int i,j,k,diff_count; ktau_output *startOut; ktau_output *stopOut; long startProcNum = 0; long stopProcNum = 0; if((startB==NULL) || (stopB==NULL) || (startSz<=0) || (stopSz<=0)) { return -1; } startProcNum = unpack_bindata(KTAU_TYPE_PROFILE, startB, startSz, &startOut); if(startProcNum < 0) { return -1; } stopProcNum = unpack_bindata(KTAU_TYPE_PROFILE, stopB, stopSz, &stopOut); if(stopProcNum < 0) { return -1; } return ktau_diff_profiles(startOut, startProcNum, stopOut, stopProcNum, pdiffOut); } /* * Function : TauKtau::DiffKProfile * Description : Diffing profile for each matched pid in startOutput and * stopOutput. If no match is found, discard the pid. * Note : Might want a different scheme */ int TauKtau::DiffKProfile(void) { int i,j,k,diff_count; ktau_output *startOutput; ktau_output *stopOutput; long startProcNum = 0; long stopProcNum = 0; if((startBuf==NULL) || (stopBuf==NULL) || (startSize<=0) || (stopSize<=0)) { return -1; } startProcNum = unpack_bindata(KTAU_TYPE_PROFILE, startBuf, startSize, &startOutput); if(startProcNum < 0) { return -1; } stopProcNum = unpack_bindata(KTAU_TYPE_PROFILE, stopBuf, stopSize, &stopOutput); if(stopProcNum < 0) { return -1; } if(DEBUG)printf("DiffKProfile: startProcNum = %u\n",startProcNum); if(DEBUG)printf("DiffKProfile: stopProcNum = %u\n",stopProcNum); diffOutput = (ktau_output*)malloc(sizeof(ktau_output)*maxof(startProcNum,stopProcNum)); /* * For each ktau_output, we have to check pid if it is the same. * Otherwise, we just ignore that one. */ for(i=0,j=0,k=0; ipid == (stopOutput+j)->pid){ if(DEBUG)printf("DiffKProfile: Diffing pid %d\n",(startOutput+i)->pid); if(DEBUG)printf("DiffKProfile: start size = %d\n",(startOutput+i)->size); if(DEBUG)printf("DiffKProfile: stop size = %d\n",(stopOutput+i)->size); diff_count = diff_ktau_output((startOutput+i),(stopOutput+j),((diffOutput)+k)); (diffOutput+k)->size = diff_count; (diffOutput+k)->pid = (startOutput+i)->pid; if((diffOutput+k)->pid == ThisKtauOutputInfo.pid){ /* Keep track of information of ktau_output * for this pid */ for(int x=0;x < (diffOutput+k)->size; x++){ o_ent *ptr = (((diffOutput)+k)->ent_lst)+x; if(ptr->index < 300 || ptr->index > 399){ ThisKtauOutputInfo.templ_fun_counter++; }else{ ThisKtauOutputInfo.user_ev_counter++; } } } i++;j++;k++; }else if((startOutput+i)->pid < (stopOutput+j)->pid){ if(DEBUG)printf("DiffKProfile: pid unmatch. Increment start.\n"); diffOutput[k] = startOutput[i]; i++;k++; }else{ if(DEBUG)printf("DiffKProfile: pid unmatch. Increment stop.\n"); diffOutput[k] = stopOutput[j]; j++;k++; } } return(k); } int TauKtau::GetNumKProfileFunc(){ return ThisKtauOutputInfo.templ_fun_counter; } int TauKtau::GetNumKProfileEvent(){ return ThisKtauOutputInfo.user_ev_counter; } int TauKtau::MergingKProfileFunc(FILE* fp){ int i=0,j=0,k=0; unsigned int cur_index = 0; if(outSize <= 0) { return -1; } for(i=0;ipid){ for(j=0;j < (diffOutput+i)->size; j++){ o_ent* ptr = (((diffOutput)+i)->ent_lst)+j; string& func_name = KtauSym.MapSym(ptr->entry.addr); if(ptr->index < 300 || ptr->index > 399){ fprintf(fp,"\"%s() \" %u %u %g %g %u ", func_name.c_str(), //Name ptr->entry.data.timer.count, //Calls 0, //Subrs (double)(ptr->entry.data.timer.excl)/KTauGetMHz(), //Excl (double)(ptr->entry.data.timer.incl)/KTauGetMHz(), //Incl 0); //ProfileCalls if(strstr(func_name.c_str(),"schedule")){ fprintf(fp, "GROUP=\"TAU_KERNEL_MERGE | KTAU_SCHEDULE\"\n"); //}else if(!strcmp("__run_timers",func_name.c_str())){ // fprintf(fp, "GROUP=\"TAU_KERNEL_MERGE | KTAU_RUN_TIMERS\"\n"); }else if(strstr(func_name.c_str(), "page_fault")){ fprintf(fp, "GROUP=\"TAU_KERNEL_MERGE | KTAU_EXCEPTION\"\n"); }else if(strstr(func_name.c_str(), "IRQ")){ fprintf(fp, "GROUP=\"TAU_KERNEL_MERGE | KTAU_IRQ\"\n"); }else if(strstr(func_name.c_str(), "run_timers")){ fprintf(fp, "GROUP=\"TAU_KERNEL_MERGE | KTAU_BH\"\n"); }else if(strstr(func_name.c_str(), "workqueue")){ fprintf(fp, "GROUP=\"TAU_KERNEL_MERGE | KTAU_BH\"\n"); }else if(strstr(func_name.c_str(), "tasklet")){ fprintf(fp, "GROUP=\"TAU_KERNEL_MERGE | KTAU_BH\"\n"); //}else if(!strcmp("__do_softirq",func_name.c_str())){ // fprintf(fp, "GROUP=\"TAU_KERNEL_MERGE | KTAU_DO_SOFTIRQ\"\n"); }else if(strstr(func_name.c_str(), "softirq")){ fprintf(fp, "GROUP=\"TAU_KERNEL_MERGE | KTAU_BH\"\n"); }else if(strstr(func_name.c_str(), "sys_")){ if(strstr(func_name.c_str(), "sock")){ fprintf(fp, "GROUP=\"TAU_KERNEL_MERGE | KTAU_SYSCALL | KTAU_SOCK\"\n"); } else if(strstr(func_name.c_str(), "read")){ fprintf(fp, "GROUP=\"TAU_KERNEL_MERGE | KTAU_SYSCALL | KTAU_IO\"\n"); } else if(strstr(func_name.c_str(), "write")){ fprintf(fp, "GROUP=\"TAU_KERNEL_MERGE | KTAU_SYSCALL | KTAU_IO\"\n"); } else if(strstr(func_name.c_str(), "send")){ fprintf(fp, "GROUP=\"TAU_KERNEL_MERGE | KTAU_SYSCALL | KTAU_IO\"\n"); } else if(strstr(func_name.c_str(), "recv")){ fprintf(fp, "GROUP=\"TAU_KERNEL_MERGE | KTAU_SYSCALL | KTAU_IO\"\n"); } else { fprintf(fp, "GROUP=\"TAU_KERNEL_MERGE | KTAU_SYSCALL\"\n"); } }else if(strstr(func_name.c_str(), "tcp")){ fprintf(fp, "GROUP=\"TAU_KERNEL_MERGE | KTAU_TCP\"\n"); }else if(strstr(func_name.c_str(), "icmp")){ fprintf(fp, "GROUP=\"TAU_KERNEL_MERGE | KTAU_ICMP\"\n"); }else if(strstr(func_name.c_str(), "sock")){ fprintf(fp, "GROUP=\"TAU_KERNEL_MERGE | KTAU_SOCK\"\n"); }else{ fprintf(fp, "GROUP=\"TAU_KERNEL_MERGE | KTAU_DEFAULT\"\n"); } /*if(!strcmp("schedule",func_name.c_str())){ fprintf(fp,"GROUP=\"KTAU_SCHEDULE\"\n"); }else if(!strcmp("__run_timers",func_name.c_str())){ fprintf(fp,"GROUP=\"KTAU_RUN_TIMERS\"\n"); }else if(!strcmp("__do_softirq",func_name.c_str())){ fprintf(fp,"GROUP=\"KTAU_DO_SOFTIRQ\"\n"); }else{ fprintf(fp,"GROUP=\"KTAU_DEFAULT\"\n"); }*/ } } } } return(0); } int TauKtau::MergingKProfileEvent(FILE* fp){ int i=0,j=0,k=0; unsigned int cur_index = 0; if(outSize <= 0) { return -1; } for(i=0;ipid){ for(j=0;j < (diffOutput+i)->size; j++){ o_ent* ptr = (((diffOutput)+i)->ent_lst)+j; string& ev_name = KtauSym.MapSym(ptr->entry.addr); if(ptr->index >= 300 && ptr->index <= 399) fprintf(fp,"\"Event_%s()\" %u %u %u %u %u\n", ev_name.c_str(), //eventname ptr->entry.data.timer.count, //numevents 1, //max 1, //min 1, //mean 1); //sumsqr } } } return(0); } /*************************************************************************** * $RCSfile: TauKtau.cpp,v $ $Author: anataraj $ * $Revision: 1.6 $ $Date: 2007/04/19 03:21:45 $ ***************************************************************************/