[kaffe] CVS kaffe (robilad): Small cleanup
Kaffe CVS
cvs-commits at kaffe.org
Mon Dec 26 14:14:50 PST 2005
PatchSet 7058
Date: 2005/12/26 20:06:30
Author: robilad
Branch: HEAD
Tag: (none)
Log:
Small cleanup
2005-12-26 Dalibor Topic <robilad at kaffe.org>
* kaffe/kaffe/main.c,
kaffe/kaffevm/classMethod.c,
kaffe/kaffevm/gcFuncs.c,
kaffe/kaffevm/jit3/machine.c,
kaffe/xprof/feedback.c,
kaffe/xprof/xprofiler.c,
libraries/clib/management/JIT.c:
Don't include methodCache.h.
Members:
ChangeLog:1.4576->1.4577
kaffe/kaffe/main.c:1.96->1.97
kaffe/kaffevm/classMethod.c:1.150->1.151
kaffe/kaffevm/gcFuncs.c:1.81->1.82
kaffe/kaffevm/jit3/machine.c:1.79->1.80
kaffe/xprof/feedback.c:INITIAL->1.6
kaffe/xprof/xprofiler.c:INITIAL->1.9
libraries/clib/management/JIT.c:1.9->1.10
Index: kaffe/ChangeLog
diff -u kaffe/ChangeLog:1.4576 kaffe/ChangeLog:1.4577
--- kaffe/ChangeLog:1.4576 Mon Dec 26 18:31:35 2005
+++ kaffe/ChangeLog Mon Dec 26 20:06:30 2005
@@ -1,3 +1,14 @@
+2005-12-26 Dalibor Topic <robilad at kaffe.org>
+
+ * kaffe/kaffe/main.c,
+ kaffe/kaffevm/classMethod.c,
+ kaffe/kaffevm/gcFuncs.c,
+ kaffe/kaffevm/jit3/machine.c,
+ kaffe/xprof/feedback.c,
+ kaffe/xprof/xprofiler.c,
+ libraries/clib/management/JIT.c:
+ Don't include methodCache.h.
+
2005-12-26 Guilhem Lavaux <guilhem at kaffe.org>
* replace/ifaddrs_bsd.c: Initialize ifap in case of error.
Index: kaffe/kaffe/kaffe/main.c
diff -u kaffe/kaffe/kaffe/main.c:1.96 kaffe/kaffe/kaffe/main.c:1.97
--- kaffe/kaffe/kaffe/main.c:1.96 Sun Dec 18 17:35:42 2005
+++ kaffe/kaffe/kaffe/main.c Mon Dec 26 20:06:33 2005
@@ -36,7 +36,6 @@
#if defined(KAFFE_FEEDBACK)
#include "feedback.h"
#endif
-#include "methodCache.h"
#include "external.h"
#include "kaffe_jni.h"
Index: kaffe/kaffe/kaffevm/classMethod.c
diff -u kaffe/kaffe/kaffevm/classMethod.c:1.150 kaffe/kaffe/kaffevm/classMethod.c:1.151
--- kaffe/kaffe/kaffevm/classMethod.c:1.150 Thu Dec 22 17:51:23 2005
+++ kaffe/kaffe/kaffevm/classMethod.c Mon Dec 26 20:06:34 2005
@@ -42,7 +42,6 @@
#include "md.h"
#include "jni.h"
#include "soft.h"
-#include "methodCache.h"
#include "gcj/gcj.h"
#include "xprofiler.h"
#include "debugFile.h"
Index: kaffe/kaffe/kaffevm/gcFuncs.c
diff -u kaffe/kaffe/kaffevm/gcFuncs.c:1.81 kaffe/kaffe/kaffevm/gcFuncs.c:1.82
--- kaffe/kaffe/kaffevm/gcFuncs.c:1.81 Sun Dec 18 17:54:31 2005
+++ kaffe/kaffe/kaffevm/gcFuncs.c Mon Dec 26 20:06:34 2005
@@ -46,7 +46,6 @@
#include "jni.h"
#include "soft.h"
#include "thread.h"
-#include "methodCache.h"
#include "jvmpi_kaffe.h"
#include "methodcalls.h"
Index: kaffe/kaffe/kaffevm/jit3/machine.c
diff -u kaffe/kaffe/kaffevm/jit3/machine.c:1.79 kaffe/kaffe/kaffevm/jit3/machine.c:1.80
--- kaffe/kaffe/kaffevm/jit3/machine.c:1.79 Mon Dec 26 18:01:47 2005
+++ kaffe/kaffe/kaffevm/jit3/machine.c Mon Dec 26 20:06:36 2005
@@ -51,7 +51,6 @@
#include "soft.h"
#include "thread.h"
#include "itypes.h"
-#include "methodCache.h"
#include "support.h"
#include "xprofiler.h"
#if defined(KAFFE_FEEDBACK)
===================================================================
Checking out kaffe/kaffe/xprof/feedback.c
RCS: /home/cvs/kaffe/kaffe/kaffe/xprof/feedback.c,v
VERS: 1.6
***************
--- /dev/null Sun Aug 4 19:57:58 2002
+++ kaffe/kaffe/xprof/feedback.c Mon Dec 26 22:14:49 2005
@@ -0,0 +1,304 @@
+/*
+ * feedback.c
+ * Routines for generating information that can be fed back into kaffe for
+ * future runs.
+ *
+ * Copyright (c) 2000 University of Utah and the Flux Group.
+ * All rights reserved.
+ *
+ * This file is licensed under the terms of the GNU Public License.
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Contributed by the Flux Research Group, Department of Computer Science,
+ * University of Utah, http://www.cs.utah.edu/flux/
+ */
+
+#include "config.h"
+
+#if defined(KAFFE_FEEDBACK)
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "gtypes.h"
+#include "access.h"
+#include "classMethod.h"
+#include "lookup.h"
+#include "support.h"
+#include "debug.h"
+#include "stringSupport.h"
+#include "thread.h"
+#include "external.h"
+
+#include "feedback.h"
+#include "fileSections.h"
+
+/* XXX Temporary for now until we define interface header file that
+ * declares "translate"
+ */
+#if defined(TRANSLATOR)
+#if defined(JIT3)
+#include "jit3/machine.h"
+#else
+#include "jit/machine.h"
+#endif
+#endif
+
+#define FEEDBACKSTACKSIZE 4096
+
+struct section_file *kaffe_feedback_file = 0;
+char *feedback_filename = 0;
+
+int feedbackFile(char *filename)
+{
+ int retval = 0;
+
+ /* Create a section file object to store the feedback information */
+ if( (kaffe_feedback_file = createSectionFile()) )
+ {
+ setSectionFileName(kaffe_feedback_file, filename);
+ /*
+ * Add an atexit call to syncFeedback so we know the
+ * information got out
+ */
+ if( !atexit((void (*)(void))syncFeedback) )
+ retval = 1;
+ else
+ {
+ deleteSectionFile(kaffe_feedback_file);
+ kaffe_feedback_file = 0;
+ }
+ }
+ return( retval );
+}
+
+int syncFeedback(void)
+{
+ int retval = 0;
+
+ if( kaffe_feedback_file && syncSectionFile(kaffe_feedback_file) )
+ {
+ retval = 1;
+ }
+ return( retval );
+}
+
+/*
+ * Function that is called by the sections walker
+ */
+static int feedbackWalker(void *arg,
+ struct section_file *sf,
+ struct section_file_data *sfd)
+{
+ int retval = 1;
+
+ /* Check for library section */
+ if( sfd->sfd_type == &lib_section )
+ {
+ struct lib_section_data *lsd = (struct lib_section_data *)sfd;
+
+ if( lsd->lsd_flags & LSDF_PRELOAD )
+ loadNativeLibrary2(sfd->sfd_name, 0, 0, 0);
+ }
+ /* Check for jit-code section */
+ else if( sfd->sfd_type == &jit_section )
+ {
+#if defined(TRANSLATOR)
+ struct jit_section_data *jsd = (struct jit_section_data *)sfd;
+
+ if( jsd->jsd_flags & JSDF_PRECOMPILE )
+ {
+ int len, lpc, sig_start = -1, meth_start = -1;
+ Utf8Const *u8cname, *u8mname, *u8sig;
+ Hjava_lang_Class *cls;
+ char *full_name;
+
+ /*
+ * Parse the name of the section to get the class,
+ * method, and signature
+ */
+ full_name = sfd->sfd_name;
+ len = strlen(full_name);
+ for( lpc = len - 1;
+ (lpc >= 0) && (meth_start < 0);
+ lpc-- )
+ {
+ switch( full_name[lpc] )
+ {
+ case '(':
+ sig_start = lpc;
+ break;
+ case '/':
+ if( sig_start > 0 )
+ meth_start = lpc + 1;
+ break;
+ }
+ }
+ if( (sig_start > 0) && (meth_start > 0) )
+ {
+ jobject loader = 0;
+ errorInfo info;
+
+ /* Get the right strings and find the class */
+ u8cname = utf8ConstNew(full_name,
+ meth_start - 1);
+ u8mname = utf8ConstNew(&full_name[meth_start],
+ sig_start - meth_start);
+ u8sig = utf8ConstNew(&full_name[sig_start],
+ len - sig_start);
+ if( u8cname && u8mname && u8sig &&
+ (cls = loadClass(u8cname, loader, &info)) )
+ {
+ Method *meth;
+
+ if( (meth = findMethodLocal(cls,
+ u8mname,
+ u8sig)) &&
+ !(meth->accflags & ACC_NATIVE) )
+ {
+ if( translate(meth, &info) )
+ {
+ }
+ else
+ {
+ dprintf(
+ "Feedback: "
+ " Precompile "
+ "failed for "
+ "%s!\n",
+ full_name);
+ }
+ }
+ else if( !meth )
+ {
+ dprintf(
+ "Feedback: Didn't "
+ "find method"
+ " %s\n",
+ full_name);
+ }
+ }
+ else
+ {
+ dprintf(
+ "Feedback: Couldn't load "
+ "class %s\n",
+ u8cname->data);
+ }
+ utf8ConstRelease(u8cname);
+ utf8ConstRelease(u8mname);
+ utf8ConstRelease(u8sig);
+ }
+ else
+ {
+ dprintf(
+ "Feedback: Malformed method `%s'\n",
+ full_name);
+ }
+ }
+#else
+ {
+ static int precompile_msg = 0;
+
+ if( !precompile_msg )
+ {
+ precompile_msg = 1;
+ dprintf(
+ "Feedback: Cannot precompile java for "
+ "the interpreter\n");
+ }
+ }
+#endif
+ }
+ return( retval );
+}
+
+static void feedbackRunnable(void *arg)
+{
+ /* Walk over the sections with our function */
+ walkFileSections(kaffe_feedback_file, feedbackWalker, 0);
+}
+
+int processFeedback(void)
+{
+ int retval = 1;
+
+ if( kaffe_feedback_file )
+ {
+ feedbackRunnable(0);
+ retval = 1;
+ }
+ return( retval );
+}
+
+int feedbackJITMethod(char *method, char *address, int size, int precompile)
+{
+ struct section_file_data *sfd;
+ struct jit_section_data *jsd;
+ int retval = 0;
+
+ if( !kaffe_feedback_file )
+ return( 0 );
+ lockMutex(kaffe_feedback_file);
+ if( !(sfd = findSectionInFile(kaffe_feedback_file,
+ &jit_section, method)) )
+ {
+ /*
+ * If the section doesn't exist we need to create and add it.
+ * We only set precompile here since the user might've changed
+ * the file to specify otherwise.
+ */
+ if( (sfd = createFileSection(jit_section.fs_name, method,
+ "precompile", precompile ?
+ "true" : "false",
+ NULL)) )
+ {
+ addSectionToFile(kaffe_feedback_file, sfd);
+ }
+ }
+ if( sfd )
+ {
+ /* Set whatever attributes are interesting */
+ jsd = (struct jit_section_data *)sfd;
+ jsd->jsd_address = address;
+ jsd->jsd_size = size;
+ retval = 1;
+ }
+ unlockMutex(kaffe_feedback_file);
+ return( retval );
+}
+
+int feedbackLibrary(char *name, int preload)
+{
+ struct section_file_data *sfd;
+ int retval = 0;
+
+ if( !kaffe_feedback_file )
+ return( 0 );
+ lockMutex(kaffe_feedback_file);
+ if( !(sfd = findSectionInFile(kaffe_feedback_file,
+ &lib_section, name)) )
+ {
+ /*
+ * If the section doesn't exist we need to create and add it.
+ * We only set preload here since the user might've changed
+ * the file to specify otherwise.
+ */
+ if( (sfd = createFileSection(lib_section.fs_name, name,
+ "preload", preload ?
+ "true" : "false",
+ NULL)) )
+ {
+ addSectionToFile(kaffe_feedback_file, sfd);
+ retval = 1;
+ }
+ }
+ else
+ retval = 1;
+ unlockMutex(kaffe_feedback_file);
+ return( retval );
+}
+
+#endif /* KAFFE_FEEDBACK */
===================================================================
Checking out kaffe/kaffe/xprof/xprofiler.c
RCS: /home/cvs/kaffe/kaffe/kaffe/xprof/xprofiler.c,v
VERS: 1.9
***************
--- /dev/null Sun Aug 4 19:57:58 2002
+++ kaffe/kaffe/xprof/xprofiler.c Mon Dec 26 22:14:50 2005
@@ -0,0 +1,714 @@
+/*
+ * xprofiler.c
+ * Interface functions to the profiling code
+ *
+ * Copyright (c) 2000, 2001 University of Utah and the Flux Group.
+ * All rights reserved.
+ *
+ * This file is licensed under the terms of the GNU Public License.
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Contributed by the Flux Research Group, Department of Computer Science,
+ * University of Utah, http://www.cs.utah.edu/flux/
+ */
+
+#include "config.h"
+
+#if defined(KAFFE_XPROFILER)
+
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/gmon.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/gmon.h>
+#include <sys/sysctl.h>
+
+#include "gtypes.h"
+#include "md.h"
+#include "xprofile-md.h"
+#include "exception.h"
+#include "kaffe/jmalloc.h"
+
+#include "memorySamples.h"
+#include "feedback.h"
+#include "debugFile.h"
+#include "fileSections.h"
+#include "gmonFile.h"
+#include "callGraph.h"
+#include "xprofiler.h"
+
+/* Variables for figuring out the start and end of the program text */
+extern char _start;
+extern char etext;
+
+int xProfFlag = 0;
+/* Flag used to determine whether or not we should record `hits' */
+static volatile int xProfRecord = 1;
+
+/*
+ * This variable is part of a nasty hack to keep the call graph accounting
+ * code from being credited with time. The accounting function should set
+ * this variable while its working so that if a profiling interrupt happens
+ * while its executing the appropriate function will be credited.
+ */
+static char * volatile profiler_sample_override_pc = NULL;
+volatile int profiler_sample_overrides = 0;
+
+/* Structures used to hold the profiling information */
+struct memory_samples *kaffe_memory_samples = NULL;
+struct call_graph *kaffe_call_graph = NULL;
+
+/* The name of the output files */
+const char *kaffe_gmon_filename = "xgmon.out";
+const char *kaffe_syms_filename = "kaffe-jit-symbols.s";
+
+/* Debugging file for profiler symbols */
+struct debug_file *profiler_debug_file = NULL;
+static int extraProfileCount = 0;
+
+/* Number of call_arc structures to preallocate */
+#define XPROFILE_ARCS (1024 * 64)
+
+/*
+ * The gutter threshold is used to determine if the gap between two chunks of
+ * observed memory is too large to put into the file. Since the resulting gap
+ * would just be a bunch of zeros, we split them into different files.
+ */
+#define SAMPLE_GUTTER_THRESHOLD 1024 * 1024 * 5
+
+/* Structure used to track the current gmon file for our walker */
+struct profiler_gmon_file {
+ char *pgf_stage; /* The name of the current stage */
+ struct gmon_file *pgf_file; /* The active gmon file structure */
+ long pgf_record; /* The index of the hist record */
+};
+
+/*
+ * 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 );
+}
+
+/*
+ * Handles any post processing
+ */
+static void profilerAtExit(void)
+{
+ if( !xProfFlag )
+ return;
+ /* We don't care about profiling anymore */
+ disableProfileTimer();
+ /* This is the final stage, write out any data */
+ xProfileStage(0);
+ /* Release everything else */
+ disableXProfiling();
+}
+
+int enableXCallGraph(void)
+{
+ int retval = false;
+
+ if( (kaffe_call_graph = createCallGraph(XPROFILE_ARCS)) )
+ {
+ retval = true;
+ }
+ return( retval );
+}
+
+#if defined(KAFFE_CPROFILER)
+/*
+ * Return the minimum cycles per second for the machine
+ */
+static int hertz(void)
+{
+ struct itimerval value, ovalue;
+ int retval = 0;
+
+ timerclear(&value.it_interval);
+ timerclear(&value.it_value);
+ timerclear(&ovalue.it_interval);
+ timerclear(&ovalue.it_value);
+ value.it_interval.tv_usec = 1;
+ setitimer(ITIMER_REAL, &value, 0);
+ getitimer(ITIMER_REAL, &ovalue);
+ timerclear(&value.it_interval);
+ timerclear(&value.it_value);
+ setitimer(ITIMER_REAL, &value, 0);
+ if( ovalue.it_interval.tv_usec >= 2 )
+ retval = 1000000 / ovalue.it_interval.tv_usec;
+ return( retval );
+}
+
+#if defined(KAFFE_STD_PROF_RATE)
+KAFFE_STD_PROF_RATE
+#endif
+#endif
+
+int enableXProfiling(void)
+{
+ int retval = false;
+
+ xProfilingOff();
+ /* Start up our profiler and set it to observe the main executable */
+ if( xProfFlag &&
+ enableProfileTimer() &&
+ (kaffe_memory_samples = createMemorySamples()) &&
+ observeMemory(kaffe_memory_samples, &_start, &etext - &_start) &&
+ (profiler_debug_file = createDebugFile(kaffe_syms_filename)) &&
+ !atexit(profilerAtExit) )
+ {
+#if defined(KAFFE_CPROFILER)
+ struct gmonparam *gp = getGmonParam();
+ int prof_rate;
+#endif
+
+#if defined(KAFFE_CPROFILER)
+ /* Turn off any other profiling */
+ profil(0, 0, 0, 0);
+#if defined(KAFFE_STD_PROF_RATE)
+ if( !(prof_rate = kaffeStdProfRate()) )
+#endif
+ prof_rate = hertz(); /* Just guess */
+ if( !prof_rate )
+ prof_rate = 100;
+ /* Copy the hits leading up to now into our own counters */
+ if( gp && gp->kcountsize > 0 )
+ {
+ int lpc, len = gp->kcountsize / sizeof(HISTCOUNTER);
+ HISTCOUNTER *hist = gp->kcount;
+ int scale;
+
+ scale = (gp->highpc - gp->lowpc) / len;
+ for( lpc = 0; lpc < len; lpc++ )
+ {
+ if( hist[lpc] )
+ {
+ char *pc = ((char *)gp->lowpc) +
+ (lpc * scale);
+
+ memoryHitCount(kaffe_memory_samples,
+ pc,
+ (100 * hist[lpc]) /
+ prof_rate);
+ }
+ }
+ }
+#endif
+ retval = true;
+ }
+ else
+ {
+ xProfFlag = 0;
+ disableXProfiling();
+ }
+ xProfilingOn();
+ return( retval );
+}
+
+void disableXProfiling(void)
+{
+ /* Shutoff the timer and delete any structures */
+ disableProfileTimer();
+ xProfilingOff();
+ deleteMemorySamples(kaffe_memory_samples);
+ kaffe_memory_samples = 0;
+ deleteCallGraph(kaffe_call_graph);
+ kaffe_call_graph = 0;
+ deleteDebugFile(profiler_debug_file);
+ profiler_debug_file = 0;
+}
+
+void xProfilingOn(void)
+{
+ xProfRecord++;
+#if defined(KAFFE_CPROFILER)
+ {
+ struct gmonparam *gp = getGmonParam();
+
+ if( xProfRecord && gp )
+ gp->state = GMON_PROF_ON;
+ }
+#endif
+}
+
+void xProfilingOff(void)
+{
+ xProfRecord--;
+#if defined(KAFFE_CPROFILER)
+ {
+ struct gmonparam *gp = getGmonParam();
+
+ if( !xProfRecord && gp )
+ gp->state = GMON_PROF_OFF;
+ }
+#endif
+}
+
+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)();
+}
+
+int profileGmonFile(char *name)
+{
+ /* Just set the file for now, we'll make it at exit */
+ kaffe_gmon_filename = name;
+ return( true );
+}
+
+int profileSymbolFile(char *name)
+{
+ kaffe_syms_filename = name;
+ return( true );
+}
+
+#if defined(KAFFE_XPROFILER)
+
+struct sigaction oldSigAction;
+
+static void profileTimerHandler(SIGNAL_ARGS(sig UNUSED, sc))
+{
+ SIGNAL_CONTEXT_POINTER(scp) = GET_SIGNAL_CONTEXT_POINTER(sc);
+ char *addr = (char *)SIGNAL_PC(scp);
+
+ if( kaffe_memory_samples && xProfRecord )
+ {
+ if( profiler_sample_override_pc )
+ {
+ profiler_sample_overrides++;
+ /* Use the override address */
+ addr = profiler_sample_override_pc;
+ /* Null it out to stop false positives */
+ profiler_sample_override_pc = 0;
+ }
+ memoryHit(kaffe_memory_samples, addr);
+ }
+}
+
+int enableProfileTimer(void)
+{
+ struct sigaction sa;
+ int retval = false;
+
+ /* Setup our signal handler */
+ sa.sa_handler = (SIG_T)profileTimerHandler;
+ sigfillset(&sa.sa_mask);
+ sa.sa_flags = 0;
+#if 0
+ if( sigaction(SIGALRM, &sa, &oldSigAction) >= 0 )
+ {
+ struct itimerval new_value;
+
+ /* Setup a 10ms timer */
+ new_value.it_interval.tv_sec = 0;
+ new_value.it_interval.tv_usec = 10000;
+ new_value.it_value.tv_sec = 0;
+ new_value.it_value.tv_usec = 10000;
+ if( setitimer(ITIMER_REAL, &new_value, 0) >= 0 )
+ {
+ retval = true;
+ }
+ }
+#endif
+ retval = 1;
+ return( retval );
+}
+
+void disableProfileTimer(void)
+{
+ struct itimerval disable_value;
+
+ timerclear(&disable_value.it_interval);
+ timerclear(&disable_value.it_value);
+ setitimer(ITIMER_REAL, &disable_value, 0);
+}
+#else
+int enableProfileTimer(void)
+{
+ return( 1 );
+}
+
+void disableProfileTimer(void)
+{
+}
+#endif
+
+/* The rest of these are just wrappers for other code */
+
+int profileFunction(struct mangled_method *mm, char *code, int codelen)
+{
+ int retval = false;
+
+ if( xProfFlag && kaffe_memory_samples )
+ {
+ /*
+ * Add the function name to the symbol file and observe the
+ * memory
+ */
+ xProfilingOff();
+ if( observeMemory(kaffe_memory_samples, code, codelen) &&
+ addDebugInfo(profiler_debug_file,
+ DIA_FunctionSymbol, mm, code, codelen,
+ DIA_DONE) )
+ {
+ retval = true;
+ }
+ xProfilingOn();
+ }
+ else
+ {
+ retval = true;
+ }
+ return( retval );
+}
+
+int profileMemory(char *code, int codelen)
+{
+ int retval = false;
+
+ if( xProfFlag )
+ {
+ xProfilingOff();
+ if( observeMemory(kaffe_memory_samples, code, codelen) )
+ {
+ retval = true;
+ }
+ xProfilingOn();
+ }
+ else
+ {
+ retval = true;
+ }
+ return( retval );
+}
+
+int profileSymbol(struct mangled_method *mm, char *addr, int size)
+{
+ int retval = false;
+
+ if( xProfFlag )
+ {
+ if( addDebugInfo(profiler_debug_file,
+ DIA_FunctionSymbol, mm, addr, size,
+ DIA_DONE) )
+ {
+ retval = true;
+ }
+ }
+ else
+ {
+ retval = true;
+ }
+ return( retval );
+}
+
+void profileArcHit(char *frompc, char *selfpc)
+{
+ char *old_override = profiler_sample_override_pc;
+
+ /*
+ * profiler_sample_override_pc is a nasty hack to keep the
+ * accounting function from being counted as a hit when it
+ * should really be the caller.
+ */
+ profiler_sample_override_pc = selfpc;
+ if( kaffe_call_graph && xProfRecord )
+ {
+ arcHit(kaffe_call_graph, frompc, selfpc);
+ }
+ profiler_sample_override_pc = old_override;
+}
+
+#if defined(KAFFE_XPROFILER) && defined(KAFFE_CPROFILER) && defined(_KAFFE_OVERRIDE_MCOUNT_DEF)
+_KAFFE_OVERRIDE_MCOUNT_DEF;
+_KAFFE_OVERRIDE_MCOUNT_DEF
+{
+ char *old_override = profiler_sample_override_pc;
+
+ /*
+ * profiler_sample_override_pc is a nasty hack to keep the
+ * accounting function from being counted as a hit when it
+ * should really be the caller.
+ */
+ profiler_sample_override_pc = (char *)selfpc;
+ if( kaffe_call_graph )
+ {
+ register struct gmonparam *gp = getGmonParam();
+
+ if( !xProfRecord || (gp && (gp->state != GMON_PROF_ON)) )
+ goto fini;
*** Patch too long, truncated ***
More information about the kaffe
mailing list