void xProfileStage(char *stage_name) { char *low, *high, *filename; struct gmon_file *gf; size_t len; if( !xProfFlag ) return; xProfilingOff(); low = kaffe_memory_samples->ms_low; high = kaffe_memory_samples->ms_high + (extraProfileCount * HISTFRACTION); KTHREAD(suspendall)(); len = strlen(kaffe_gmon_filename) + (stage_name ? strlen(stage_name) + 1 : 0) + 1; if( (filename = (char *)KMALLOC(len)) ) { sprintf(filename, "%s%s%s", kaffe_gmon_filename, stage_name ? "." : "", stage_name ? stage_name : ""); /* Create and write out the gmon file */ if( (gf = createGmonFile(filename)) ) { struct profiler_gmon_file pgf; /* Initialize the profiler_gmon_files state */ pgf.pgf_stage = stage_name; pgf.pgf_file = gf; /* Write out the samples */ pgf.pgf_record = writeGmonRecord(gf, GRA_Type, GMON_TAG_TIME_HIST, GRA_LowPC, low, GRA_HighPC, high, GRA_DONE); /* The low/high might be aligned by writeGmonRecord */ low = gf->gf_low; high = gf->gf_high; walkMemorySamples(kaffe_memory_samples, low, high - (extraProfileCount * HISTFRACTION), &pgf, profilerSampleWalker); if( pgf.pgf_file ) { /* Dump out the call graph data */ writeCallGraph(kaffe_call_graph, pgf.pgf_file); deleteGmonFile(pgf.pgf_file); } else { resetMemorySamples(kaffe_memory_samples); } } else { fprintf(stderr, "XProf Notice: Cannot create gmon file %s\n", filename); KFREE(filename); resetMemorySamples(kaffe_memory_samples); } } else { fprintf(stderr, "XProf Notice: Not enough memory to write " "profiling data\n"); resetMemorySamples(kaffe_memory_samples); } resetCallGraph(kaffe_call_graph); xProfilingOn(); KTHREAD(unsuspendall)(); }
/* * A walker function for walkMemorySamples. This does a little more than * the one provided by the gmon code since it will create a new gmon file * if theres a large gap in observed memory. */ static int profilerSampleWalker(void *handle, char *addr, short *bins, size_t size) { struct profiler_gmon_file *pgf = handle; struct gmon_file *gf = pgf->pgf_file; int retval = 0; /* Check if we need to dump these samples in another file */ if( (addr - gf->gf_addr) > SAMPLE_GUTTER_THRESHOLD ) { char *filename, *old_high; size_t len; old_high = gf->gf_high; /* Rewrite the old record with the new high address */ writeGmonRecord(gf, GRA_Rewrite, pgf->pgf_record, GRA_Type, GMON_TAG_TIME_HIST, GRA_LowPC, gf->gf_low, GRA_HighPC, gf->gf_addr, GRA_DONE); writeCallGraph(kaffe_call_graph, gf); /* Close down the file */ deleteGmonFile(gf); pgf->pgf_file = 0; gf = 0; /* * Make up the filename for the new file, we'll just use the * starting address for this range to make it unique */ len = strlen(kaffe_gmon_filename) + 1 + /* `.' */ 2 + (sizeof(void *) * 2) + /* `0x...' */ (pgf->pgf_stage ? strlen(pgf->pgf_stage) + 1 : 0) + 1; if( (filename = (char *)KMALLOC(len)) ) { /* Construct the new file name */ sprintf(filename, "%s.%p%s%s", kaffe_gmon_filename, addr, pgf->pgf_stage ? "." : "", pgf->pgf_stage ? pgf->pgf_stage : ""); if( (pgf->pgf_file = createGmonFile(filename)) ) { gf = pgf->pgf_file; /* Write out another hist record */ pgf->pgf_record = writeGmonRecord( gf, GRA_Type, GMON_TAG_TIME_HIST, GRA_LowPC, addr, GRA_HighPC, old_high, GRA_DONE); } } } if( gf ) { /* Let the gmon walker do its thing */ retval = gmonSampleWalker(gf, addr, bins, size); } memset(bins, 0, size * sizeof(short)); return( retval ); }
void write_htmlFnctPages::writePage(void) { // most of the informations can be write only if the function has a body ! dataDrawerListIterator p; // browse the list string fnctName; // name of the function // Browse list one function for time p = dataBL->begin(); while (p != dataBL->end()) { dataB = *p; p++; fData = dataB->getFnctData(); cout << "Generating html page for function " << (fnctName = fData->getName()) << "...\n"; htmlpage.open((HTMLfilesRegister::htmlFile(*fData)).c_str()); // begin of the page pageTitle = fnctName ; writeHead(); writeIndex(); htmlpage << "<br><br>\n"; if (fnctName != "") htmlpage << "This is the page of the function " << fnctName << ".<br><br>\n"; htmlpage << *fData << "<br><l><br>\n\n"; if (fData->hasBody()) { writePageIndex(); // write body graph if (!noBodyGraph) { htmlpage << "<A name=\"bodyGraph\">\n"; writeSectionTitle("Graph of the body"); writeBodyGraph(); } // write CFG if (!noCFG) { htmlpage << "<A name=\"CFG\">\n"; writeSectionTitle("Control flow graph"); writeCFG(); } // write stmt stat if (!noStmtStat) { htmlpage << "<A name=\"stmtStatistics\">\n"; writeSectionTitle("Statements statistics"); htmlpage << *(dataB->getStmtNumData()); } // write decl list if ( (!noDeclsList) && (dataB->hasDeclsList()) ) { htmlpage << "<A name=\"declsList\">\n"; writeSectionTitle("Declarations into the function"); htmlpage << *(dataB->getDeclsList()); } // write var used if ( (!noVarUsed) && (dataB->hasVarUsedList()) ) { htmlpage << "<A name=\"varUsedList\">\n"; writeSectionTitle("Variables used by the function"); htmlpage << *(dataB->getVarUsedList()); } // write exprs list if ( (!noExprsList) && (dataB->hasExprsList()) ) { htmlpage << "<A name=\"exprsList\">\n"; writeSectionTitle("List of the expressions"); htmlpage << *(dataB->getExprsList()); } // write expr stat if (!noExprStat) { htmlpage << "<A name=\"exprStatistics\">\n"; writeSectionTitle("Expression statistics"); htmlpage << *(dataB->getExprNumData()); } // write call graph if (!noCallGraph) { htmlpage << "<A name=\"callGraph\">\n"; writeSectionTitle("Call graph"); writeCallGraph(); } } // end of the page writeIndex(); writeFoot(); htmlpage.close(); } return; }