diff --git a/hermit/Makefile b/hermit/Makefile index 363dff434..6299f1a0a 100644 --- a/hermit/Makefile +++ b/hermit/Makefile @@ -41,6 +41,19 @@ ARFLAGS = rsv RM = rm -rf OUTPUT_FORMAT = -O elf64-x86-64-hermit +# Additional flags for profiling using Xray +PROFILING_LDFLAGS = +PROFILING_CFLAGS = + +ifdef PROFILING + PROFILING_LDFLAGS = -lxray + + PROFILING_CFLAGS = -falign-functions=32 -finstrument-functions + PROFILING_CFLAGS += -finstrument-functions-exclude-function-list=_mm_pause,_mm_setcsr,_mm_getcsr # we need this for libiomp to work + PROFILING_CFLAGS += -DXRAY -DXRAY_DISABLE_BROWSER_INTEGRATION -DXRAY_NO_DEMANGLE + PROFILING_CFLAGS += -DXRAY_ANNOTATE +endif + CFLAGS_FOR_NEWLIB = -m64 -mtls-direct-seg-refs -mno-red-zone -O3 -march=native -mtune=native -ftree-vectorize $(STACKPROT) FCFLAGS_FOR_NEWLIB = -m64 -mtls-direct-seg-refs -mno-red-zone -O3 -march=native -mtune=native -ftree-vectorize FFLAGS_FOR_NEWLIB = -m64 -mtls-direct-seg-refs -mno-red-zone -O3 -march=native -mtune=native -ftree-vectorize @@ -84,7 +97,9 @@ toolchain: RANLIB_FOR_TARGET=$(RANLIB_FOR_TARGET) \ STRIP_FOR_TARGET=$(STRIP_FOR_TARGET) \ ELFEDIT_FOR_TARGET=$(ELFEDIT_FOR_TARGET) \ - READELF_FOR_TARGET=$(READELF_FOR_TARGET) -C usr toolchain + READELF_FOR_TARGET=$(READELF_FOR_TARGET) \ + PROFILING_CFLAGS="$(PROFILING_CFLAGS)" \ + PROFILING_LDFLAGS="$(PROFILING_LDFLAGS)" -C usr toolchain bootstrap: $Q$(MAKE) ARCH=$(ARCH) CFLAGS="" LDFLAGS="" -C usr bootstrap diff --git a/hermit/usr/Makefile b/hermit/usr/Makefile index 5b2528c73..9c698b168 100644 --- a/hermit/usr/Makefile +++ b/hermit/usr/Makefile @@ -26,12 +26,12 @@ default: demo: @echo Build demo applications - $Q$(MAKE) ELFEDIT_FOR_TARGET=$(ELFEDIT_FOR_TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) CXX_FOR_TARGET=$(CXX_FOR_TARGET) CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" LDFLAGS_FOR_TARGET="$(LDFLAGS_FOR_TARGET)" OBJCOPY_FOR_TARGET=$(OBJCOPY_FOR_TARGET) -C tests depend - $Q$(MAKE) ELFEDIT_FOR_TARGET=$(ELFEDIT_FOR_TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) CXX_FOR_TARGET=$(CXX_FOR_TARGET) CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" LDFLAGS_FOR_TARGET="$(LDFLAGS_FOR_TARGET)" OBJCOPY_FOR_TARGET=$(OBJCOPY_FOR_TARGET) -C tests - $Q$(MAKE) ELFEDIT_FOR_TARGET=$(ELFEDIT_FOR_TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) CXX_FOR_TARGET=$(CXX_FOR_TARGET) CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" LDFLAGS_FOR_TARGET="$(LDFLAGS_FOR_TARGET)" OBJCOPY_FOR_TARGET=$(OBJCOPY_FOR_TARGET) -C benchmarks depend - $Q$(MAKE) ELFEDIT_FOR_TARGET=$(ELFEDIT_FOR_TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) CXX_FOR_TARGET=$(CXX_FOR_TARGET) CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" LDFLAGS_FOR_TARGET="$(LDFLAGS_FOR_TARGET)" OBJCOPY_FOR_TARGET=$(OBJCOPY_FOR_TARGET) -C benchmarks + $Q$(MAKE) ELFEDIT_FOR_TARGET=$(ELFEDIT_FOR_TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) CXX_FOR_TARGET=$(CXX_FOR_TARGET) CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET) $(PROFILING_CFLAGS)" LDFLAGS_FOR_TARGET="$(LDFLAGS_FOR_TARGET) $(PROFILING_LDFLAGS)" OBJCOPY_FOR_TARGET=$(OBJCOPY_FOR_TARGET) -C tests depend + $Q$(MAKE) ELFEDIT_FOR_TARGET=$(ELFEDIT_FOR_TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) CXX_FOR_TARGET=$(CXX_FOR_TARGET) CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET) $(PROFILING_CFLAGS)" LDFLAGS_FOR_TARGET="$(LDFLAGS_FOR_TARGET) $(PROFILING_LDFLAGS)" OBJCOPY_FOR_TARGET=$(OBJCOPY_FOR_TARGET) -C tests + $Q$(MAKE) ELFEDIT_FOR_TARGET=$(ELFEDIT_FOR_TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) CXX_FOR_TARGET=$(CXX_FOR_TARGET) CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET) $(PROFILING_CFLAGS)" LDFLAGS_FOR_TARGET="$(LDFLAGS_FOR_TARGET) $(PROFILING_LDFLAGS)" OBJCOPY_FOR_TARGET=$(OBJCOPY_FOR_TARGET) -C benchmarks depend + $Q$(MAKE) ELFEDIT_FOR_TARGET=$(ELFEDIT_FOR_TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) CXX_FOR_TARGET=$(CXX_FOR_TARGET) CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET) $(PROFILING_CFLAGS)" LDFLAGS_FOR_TARGET="$(LDFLAGS_FOR_TARGET) $(PROFILING_LDFLAGS)" OBJCOPY_FOR_TARGET=$(OBJCOPY_FOR_TARGET) -C benchmarks #$Q$(MAKE) ELFEDIT_FOR_TARGET=$(ELFEDIT_FOR_TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) CXX_FOR_TARGET=$(CXX_FOR_TARGET) CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" LDFLAGS_FOR_TARGET="$(LDFLAGS_FOR_TARGET)" OBJCOPY_FOR_TARGET=$(OBJCOPY_FOR_TARGET) -C openmpbench depend - $Q$(MAKE) ELFEDIT_FOR_TARGET=$(ELFEDIT_FOR_TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) CXX_FOR_TARGET=$(CXX_FOR_TARGET) CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" LDFLAGS_FOR_TARGET="$(LDFLAGS_FOR_TARGET)" OBJCOPY_FOR_TARGET=$(OBJCOPY_FOR_TARGET) -C openmpbench + $Q$(MAKE) ELFEDIT_FOR_TARGET=$(ELFEDIT_FOR_TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) CXX_FOR_TARGET=$(CXX_FOR_TARGET) CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET) $(PROFILING_CFLAGS)" LDFLAGS_FOR_TARGET="$(LDFLAGS_FOR_TARGET) $(PROFILING_LDFLAGS)" OBJCOPY_FOR_TARGET=$(OBJCOPY_FOR_TARGET) -C openmpbench $(ARCH): $Q$(MKDIR) $(TMP) @@ -58,13 +58,15 @@ $(TMP)/newlib: pte: @echo Build libpthread - $Q$(MAKE) TARGET=$(TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) AR_FOR_TARGET=$(AR_FOR_TARGET) CFLAGS_FOR_TARGET+="-I. -Iplatform/hermit -Iplatform/helper -Wall" -C pte depend - $Q$(MAKE) TARGET=$(TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) AR_FOR_TARGET=$(AR_FOR_TARGET) CFLAGS_FOR_TARGET+="-I. -Iplatform/hermit -Iplatform/helper -Wall" -C pte + $Q$(MAKE) TARGET=$(TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) AR_FOR_TARGET=$(AR_FOR_TARGET) CFLAGS_FOR_TARGET+="-I. -Iplatform/hermit -Iplatform/helper -Wall $(PROFILING_CFLAGS)" -C pte depend + $Q$(MAKE) TARGET=$(TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) AR_FOR_TARGET=$(AR_FOR_TARGET) CFLAGS_FOR_TARGET+="-I. -Iplatform/hermit -Iplatform/helper -Wall $(PROFILING_CFLAGS)" -C pte libs: + @echo Build Xray profiler + $Q$(MAKE) TARGET=$(TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" LDFLAGS_FOR_TARGET="$(LDFLAGS_FOR_TARGET)" -C xray @echo Build OpenMP Runtime and iRCCE - $Q$(MAKE) TARGET=$(TARGET) CXX_FOR_TARGET=$(CXX_FOR_TARGET) CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" CC_FOR_TARGET=$(CC_FOR_TARGET) AR_FOR_TARGET=$(AR_FOR_TARGET) CFLAGS_FOR_TARGET+="-I. -Wall -pthread" -C $(OMPRT) depend - $Q$(MAKE) TARGET=$(TARGET) CXX_FOR_TARGET=$(CXX_FOR_TARGET) CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" CC_FOR_TARGET=$(CC_FOR_TARGET) AR_FOR_TARGET=$(AR_FOR_TARGET) CFLAGS_FOR_TARGET+="-I. -Wall -pthread" -C $(OMPRT) + $Q$(MAKE) TARGET=$(TARGET) CXX_FOR_TARGET=$(CXX_FOR_TARGET) CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" CC_FOR_TARGET=$(CC_FOR_TARGET) AR_FOR_TARGET=$(AR_FOR_TARGET) CFLAGS_FOR_TARGET+="-I. -Wall -pthread $(PROFILING_CFLAGS)" -C $(OMPRT) depend + $Q$(MAKE) TARGET=$(TARGET) CXX_FOR_TARGET=$(CXX_FOR_TARGET) CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" CC_FOR_TARGET=$(CC_FOR_TARGET) AR_FOR_TARGET=$(AR_FOR_TARGET) CFLAGS_FOR_TARGET+="-I. -Wall -pthread $(PROFILING_CFLAGS)" -C $(OMPRT) $Q$(MAKE) TARGET=$(TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) AR_FOR_TARGET=$(AR_FOR_TARGET) CFLAGS_FOR_TARGET+="-I. -Wall" -C ircce depend $Q$(MAKE) TARGET=$(TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) AR_FOR_TARGET=$(AR_FOR_TARGET) CFLAGS_FOR_TARGET+="-I. -Wall" -C ircce @@ -93,6 +95,7 @@ clean: $Q$(MAKE) -C tests clean $Q$(MAKE) -C benchmarks clean $Q$(MAKE) -C openmpbench clean + $Q$(MAKE) -C xray clean veryclean: @echo Propper cleaning of the toolchain diff --git a/hermit/usr/benchmarks/Makefile b/hermit/usr/benchmarks/Makefile index acc0a476b..f50df1c66 100644 --- a/hermit/usr/benchmarks/Makefile +++ b/hermit/usr/benchmarks/Makefile @@ -52,7 +52,7 @@ stream.o: stream.c stream: stream.o @echo [LD] $@ - $Q$(CC_FOR_TARGET) $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -fopenmp -o $@ $< + $Q$(CC_FOR_TARGET) -o $@ $< $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -fopenmp $Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ $Qchmod a-x $@.sym @@ -63,21 +63,21 @@ basic.o: basic.c basic: basic.o @echo [LD] $@ - $Q$(CC_FOR_TARGET) $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -pthread -o $@ $< + $Q$(CC_FOR_TARGET) -o $@ $< $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -pthread $Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ $Qchmod a-x $@.sym RCCE_pingping: RCCE_pingping.o @echo [LD] $@ - $Q$(CC_FOR_TARGET) $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -o $@ $< -lircce + $Q$(CC_FOR_TARGET) -o $@ $< $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -lircce $Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ $Qchmod a-x $@.sym RCCE_pingpong: RCCE_pingpong.o @echo [LD] $@ - $Q$(CC_FOR_TARGET) $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -o $@ $< -lircce + $Q$(CC_FOR_TARGET) -o $@ $< $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -lircce $Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ $Qchmod a-x $@.sym @@ -88,14 +88,14 @@ netio.o: netio.c netio: netio.o @echo [LD] $@ - $Q$(CC_FOR_TARGET) $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -o $@ $< + $Q$(CC_FOR_TARGET) -o $@ $< $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) $Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ $Qchmod a-x $@.sym hg: hg.o hist.o rdtsc.o run.o init.o opt.o report.o setup.o @echo [LD] $@ - $Q$(CC_FOR_TARGET) $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -o $@ $< hist.o rdtsc.o run.o init.o opt.o report.o setup.o + $Q$(CC_FOR_TARGET) -o $@ $< $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) hist.o rdtsc.o run.o init.o opt.o report.o setup.o $Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ $Qchmod a-x $@.sym diff --git a/hermit/usr/openmpbench/.gitignore b/hermit/usr/openmpbench/.gitignore new file mode 100644 index 000000000..403426a4c --- /dev/null +++ b/hermit/usr/openmpbench/.gitignore @@ -0,0 +1,2 @@ +*.map +*.xray diff --git a/hermit/usr/openmpbench/Makefile b/hermit/usr/openmpbench/Makefile index f3c16d8b7..937877e2f 100644 --- a/hermit/usr/openmpbench/Makefile +++ b/hermit/usr/openmpbench/Makefile @@ -6,33 +6,36 @@ CFLAGS_CRAY = ${CFLAGS} endif .c.o: - ${CC} ${CFLAGS} $(OMPFLAG) -c $*.c + ${CC} ${CFLAGS} $(OMPFLAG) -c $*.c -SYNCOBJS = syncbench.o common.o -SCHEDOBJS = schedbench.o common_sched.o -ARRAYOBJS = arraybench_$(IDA).o common.o -TASKOBJS = taskbench.o common.o +SYNCOBJS = syncbench.o common.o +SCHEDOBJS = schedbench.o common_sched.o +ARRAYOBJS = arraybench_$(IDA).o common.o +TASKOBJS = taskbench.o common.o SCHEDFLAGS = -DSCHEDBENCH all: syncbench schedbench taskbench -prog: arraybench_$(IDA) +prog: arraybench_$(IDA) + +# We need to generate a linker map file so that Xray can resolve function names +LDFLAGS += -Wl,-Map=$@.map syncbench: $(SYNCOBJS) - $(CC) -o syncbench $(LDFLAGS) $(SYNCOBJS) $(CLOCKOBJS) $(LIBS) -lm + $(CC) -o syncbench $(SYNCOBJS) $(LDFLAGS) $(CLOCKOBJS) $(LIBS) -lm -# Rule to ensure the lower optimisation level is picked up for common.c +# Rule to ensure the lower optimisation level is picked up for common.c # with the Cray compiler -common.o: - ${CC} ${CFLAGS_CRAY} $(OMPFLAG) -c $*.c +common.o: + ${CC} ${CFLAGS_CRAY} $(OMPFLAG) -c $*.c -# Separate rule to build common_sched.o as we need to ensure the correct -# DEFAULT_DELAY_TIME is used. -common_sched.o: +# Separate rule to build common_sched.o as we need to ensure the correct +# DEFAULT_DELAY_TIME is used. +common_sched.o: ${CC} ${CFLAGS_CRAY} $(SCHEDFLAGS) $(OMPFLAG) -o common_sched.o -c common.c schedbench: $(SCHEDOBJS) - $(CC) -o schedbench $(LDFLAGS) $(SCHEDOBJS) $(CLOCKOBJS) $(LIBS) -lm + $(CC) -o schedbench $(SCHEDOBJS) $(LDFLAGS) $(CLOCKOBJS) $(LIBS) -lm # Multiple header files due to multiple array sizes, makes header file arraybench_*.h arraybench_$(IDA).h: arraybench.h @@ -44,13 +47,13 @@ arraybench_$(IDA).o: arraybench_$(IDA).h arraybench.c # Multiple executables due to multiple array sizes, makes exe file arraybench_* arraybench_$(IDA): $(ARRAYOBJS) $(CLOCKOBJS) arraybench.c - $(CC) $(LDFLAGS) $(ARRAYOBJS) $(CLOCKOBJS) $(LIBS) -lm -o $@ + $(CC) -o $@ $(LDFLAGS) $(ARRAYOBJS) $(CLOCKOBJS) $(LIBS) -lm taskbench: $(TASKOBJS) - $(CC) -o taskbench $(LDFLAGS) $(OMPFLAG) $(TASKOBJS) $(CLOCKOBJS) $(LIBS) -lm + $(CC) -o taskbench $(TASKOBJS) $(LDFLAGS) $(OMPFLAG) $(CLOCKOBJS) $(LIBS) -lm -clean: - -rm -rf *.o syncbench schedbench arraybench_* taskbench +clean: + -rm -rf *.o *.xray *.map syncbench schedbench arraybench_* taskbench veryclean: clean -rm -rf OpenMPBench.* *.all diff --git a/hermit/usr/openmpbench/common.c b/hermit/usr/openmpbench/common.c index 9267729d1..db68de713 100644 --- a/hermit/usr/openmpbench/common.c +++ b/hermit/usr/openmpbench/common.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "common.h" @@ -276,6 +277,8 @@ void reference(char *name, void (*refer)(void)) { int k; double start; + XRayLabelFrame(name); + // Calculate the required number of innerreps innerreps = getinnerreps(refer); @@ -319,6 +322,8 @@ void benchmark(char *name, void (*test)(void)) intitest(name); + XRayLabelFrame(name); + for (k=0; k<=outerreps; k++) { start = getclock(); test(); diff --git a/hermit/usr/openmpbench/syncbench.c b/hermit/usr/openmpbench/syncbench.c index b8f0d9ae6..b3f87e093 100644 --- a/hermit/usr/openmpbench/syncbench.c +++ b/hermit/usr/openmpbench/syncbench.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "common.h" #include "syncbench.h" @@ -42,6 +43,12 @@ omp_lock_t lock; int main(int argc, char **argv) { + struct XRayTraceCapture* trace = XRayInit( + 20, // max. call depth + 32 * 1000 * 1000, // memory for report + 13, // frame count + "/hermit/usr/openmpbench/syncbench.map"); + // Start Paraver tracing #ifdef PARAVERTRACE Extrae_init(); @@ -52,48 +59,80 @@ int main(int argc, char **argv) { omp_init_lock(&lock); /* GENERATE REFERENCE TIME */ - reference("reference time 1", &refer); + XRayStartFrame(trace); + reference("reference time 1", &refer); + XRayEndFrame(trace); /* TEST PARALLEL REGION */ + XRayStartFrame(trace); benchmark("PARALLEL", &testpr); + XRayEndFrame(trace); - /* TEST FOR */ - benchmark("FOR", &testfor); + /* TEST FOR */ + XRayStartFrame(trace); + benchmark("FOR", &testfor); + XRayEndFrame(trace); - /* TEST PARALLEL FOR */ - benchmark("PARALLEL FOR", &testpfor); + /* TEST PARALLEL FOR */ + XRayStartFrame(trace); + benchmark("PARALLEL FOR", &testpfor); + XRayEndFrame(trace); - /* TEST BARRIER */ - benchmark("BARRIER", &testbar); + /* TEST BARRIER */ + XRayStartFrame(trace); + benchmark("BARRIER", &testbar); + XRayEndFrame(trace); - /* TEST SINGLE */ - benchmark("SINGLE", &testsing); + /* TEST SINGLE */ + XRayStartFrame(trace); + benchmark("SINGLE", &testsing); + XRayEndFrame(trace); - /* TEST CRITICAL*/ - benchmark("CRITICAL", &testcrit); + /* TEST CRITICAL*/ + XRayStartFrame(trace); + benchmark("CRITICAL", &testcrit); + XRayEndFrame(trace); - /* TEST LOCK/UNLOCK */ - benchmark("LOCK/UNLOCK", &testlock); + /* TEST LOCK/UNLOCK */ + XRayStartFrame(trace); + benchmark("LOCK/UNLOCK", &testlock); + XRayEndFrame(trace); - /* TEST ORDERED SECTION */ - benchmark("ORDERED", &testorder); + /* TEST ORDERED SECTION */ + XRayStartFrame(trace); + benchmark("ORDERED", &testorder); + XRayEndFrame(trace); - /* GENERATE NEW REFERENCE TIME */ - reference("reference time 2", &referatom); + /* GENERATE NEW REFERENCE TIME */ + XRayStartFrame(trace); + reference("reference time 2", &referatom); + XRayEndFrame(trace); - /* TEST ATOMIC */ - benchmark("ATOMIC", &testatom); + /* TEST ATOMIC */ + XRayStartFrame(trace); + benchmark("ATOMIC", &testatom); + XRayEndFrame(trace); - /* GENERATE NEW REFERENCE TIME */ - reference("reference time 3", &referred); + /* GENERATE NEW REFERENCE TIME */ + XRayStartFrame(trace); + reference("reference time 3", &referred); + XRayEndFrame(trace); - /* TEST REDUCTION (1 var) */ - benchmark("REDUCTION", &testred); + /* TEST REDUCTION (1 var) */ + XRayStartFrame(trace); + benchmark("REDUCTION", &testred); + XRayEndFrame(trace); #ifdef PARAVERTRACE Extrae_fini(); #endif + XRaySaveReport(trace, + "/hermit/usr/openmpbench/syncbench.xray", // report file + 0.05f, // Only output funcs that have higher runtime [%] + 1000); // Only output funcs that have higher runtime [cycles] + XRayShutdown(trace); + finalise(); return EXIT_SUCCESS; @@ -132,6 +171,11 @@ void referred() { void testpr() { int j; +#ifdef XRAY + static int n = 1; + XRayAnnotate("n = %i", n); + n++; +#endif for (j = 0; j < innerreps; j++) { #pragma omp parallel { @@ -155,6 +199,11 @@ void testfor() { void testpfor() { int i, j; +#ifdef XRAY + static int n = 1; + XRayAnnotate("n = %i", n); + n++; +#endif for (j = 0; j < innerreps; j++) { #pragma omp parallel for for (i = 0; i < nthreads; i++) { diff --git a/hermit/usr/tests/Makefile b/hermit/usr/tests/Makefile index 718794a93..376305d07 100644 --- a/hermit/usr/tests/Makefile +++ b/hermit/usr/tests/Makefile @@ -32,7 +32,7 @@ endif # other implicit rules %.o : %.c @echo [CC] $@ - $Q$(CC_FOR_TARGET) -c $(CFLAGS_FOR_TARGET) -o $@ $< + $Q$(CC_FOR_TARGET) -c $(CFLAGS_FOR_TARGET) -o $@ $< %.o: %.cpp @echo [CXX] $@ @@ -48,28 +48,28 @@ all: hello hello++ thr_hello jacobi hellof RCCE_minimum hello++: hello++.o @echo [LD] $@ - $Q$(CXX_FOR_TARGET) $(LDFLAGS_FOR_TARGET) $(CXXFLAGS_FOR_TARGET) -o $@ $< + $Q$(CXX_FOR_TARGET) -o $@ $< $(LDFLAGS_FOR_TARGET) $(CXXFLAGS_FOR_TARGET) $Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ $Qchmod a-x $@.sym hello: hello.o @echo [LD] $@ - $Q$(CC_FOR_TARGET) $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -o $@ $< + $Q$(CC_FOR_TARGET) -o $@ $< $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) $Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ $Qchmod a-x $@.sym hellof: hellof.o @echo [LD] $@ - $Q$(FC_FOR_TARGET) $(LDFLAGS_FOR_TARGET) $(FFLAGS_FOR_TARGET) -o $@ $< + $Q$(FC_FOR_TARGET) -o $@ $< $(LDFLAGS_FOR_TARGET) $(FFLAGS_FOR_TARGET) $Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ $Qchmod a-x $@.sym jacobi: jacobi.o @echo [LD] $@ - $Q$(CC_FOR_TARGET) $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -o $@ $< -lm + $Q$(CC_FOR_TARGET) -o $@ $< $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) $Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ $Qchmod a-x $@.sym @@ -80,14 +80,14 @@ thr_hello.o: thr_hello.c thr_hello: thr_hello.o @echo [LD] $@ - $Q$(CC_FOR_TARGET) $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -o $@ $< -pthread + $Q$(CC_FOR_TARGET) -o $@ $< $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -pthread $Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ $Qchmod a-x $@.sym RCCE_minimum: RCCE_minimum.o @echo [LD] $@ - $Q$(CC_FOR_TARGET) $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -o $@ $< -lircce + $Q$(CC_FOR_TARGET) -o $@ $< $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -lircce $Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ $Qchmod a-x $@.sym diff --git a/hermit/usr/xray/LICENSE b/hermit/usr/xray/LICENSE new file mode 100644 index 000000000..29b40573f --- /dev/null +++ b/hermit/usr/xray/LICENSE @@ -0,0 +1,28 @@ +Copyright 2011, The Chromium Authors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/hermit/usr/xray/Makefile b/hermit/usr/xray/Makefile new file mode 100644 index 000000000..369ead594 --- /dev/null +++ b/hermit/usr/xray/Makefile @@ -0,0 +1,26 @@ +NEWLIB = ../x86/x86_64-hermit +CP = cp +NAME = libxray.a + +CC_FOR_TARGET ?= gcc +AR_FOR_TARGET ?= ar + +CFLAGS = -DXRAY -DXRAY_DISABLE_BROWSER_INTEGRATION -DXRAY_NO_DEMANGLE -DXRAY_ANNOTATE + +CFLAGS += ${CFLAGS_FOR_TARGET} + +OBJS = xray.o stringpool.o hashtable.o symtable.o demangle.o parsesymbols.o report.o + + +$(NAME): $(OBJS) + $(AR_FOR_TARGET) rsv $@ $(OBJS) + $(CP) $@ $(NEWLIB)/lib + $(CP) libxray.spec $(NEWLIB)/lib + $(CP) xray.h $(NEWLIB)/include + +%.o: %.c + @echo [CC] $@ + @$(CC_FOR_TARGET) $(CFLAGS) -c $< -o $@ + +clean: + rm -f *.o $(NAME) diff --git a/hermit/usr/xray/browser.c b/hermit/usr/xray/browser.c new file mode 100644 index 000000000..a150c5a3f --- /dev/null +++ b/hermit/usr/xray/browser.c @@ -0,0 +1,163 @@ +/* Copyright (c) 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +/* XRay -- a simple profiler for Native Client */ + +#ifndef XRAY_DISABLE_BROWSER_INTEGRATION + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ppapi/c/dev/ppb_trace_event_dev.h" +#include "xray/xray_priv.h" + + +#if defined(XRAY) +static PPB_Trace_Event_Dev* ppb_trace_event_interface = NULL; + +static const char* XRayGetName(struct XRaySymbolTable* symbols, + struct XRayTraceBufferEntry* e) { + uint32_t addr = XRAY_EXTRACT_ADDR(e->depth_addr); + struct XRaySymbol* symbol = XRaySymbolTableLookup(symbols, addr); + return XRaySymbolGetName(symbol); +} + +struct XRayTimestampPair XRayGenerateTimestampsNow(void) { + struct XRayTimestampPair pair; + assert(ppb_trace_event_interface); + + XRayGetTSC(&pair.xray); + pair.pepper = ppb_trace_event_interface->Now(); + return pair; +} + +/* see chromium/src/base/trace_event/trace_event.h */ +#define TRACE_VALUE_TYPE_UINT (2) +#define TRACE_VALUE_TYPE_DOUBLE (4) +#define TRACE_VALUE_TYPE_COPY_STRING (7) + +union TraceValue { + bool as_bool; + unsigned long long as_uint; + long long as_int; + double as_double; + const void* as_pointer; + const char* as_string; + }; + +void XRayBrowserTraceReport(struct XRayTraceCapture* capture) { + + const void* cat_enabled = ppb_trace_event_interface->GetCategoryEnabled( + "xray"); + struct XRaySymbolTable* symbols = XRayGetSymbolTable(capture); + + int32_t thread_id = XRayGetSavedThreadID(capture); + + int head = XRayFrameGetHead(capture); + int frame = XRayFrameGetTail(capture); + while(frame != head) { + + struct XRayTimestampPair start_time = XRayFrameGetStartTimestampPair( + capture, frame); + struct XRayTimestampPair end_time = XRayFrameGetEndTimestampPair( + capture, frame); + + double pdiff = (end_time.pepper - start_time.pepper); + double odiff = (end_time.xray - start_time.xray); + double scale_a = pdiff / odiff; + double scale_b = ((double)end_time.pepper) - (scale_a * end_time.xray); + printf("Xray timestamp calibration frame %d: %f %f\n", + frame, scale_a, scale_b); + + int start = XRayFrameGetTraceStartIndex(capture, frame); + int end = XRayFrameGetTraceEndIndex(capture, frame); + + struct XRayTraceBufferEntry** stack_base = XRayMalloc( + sizeof(struct XRayTraceBufferEntry*) * (XRAY_TRACE_STACK_SIZE + 1)); + struct XRayTraceBufferEntry** stack_top = stack_base; + *stack_top = NULL; + + uint32_t num_args = 0; + const char* arg_names[] = {"annotation"}; + uint8_t arg_types[] = {TRACE_VALUE_TYPE_COPY_STRING}; + uint64_t arg_values[] = {0}; + char annotation[XRAY_TRACE_ANNOTATION_LENGTH]; + + int i; + for(i = start; i != end; i = XRayTraceNextEntry(capture, i)) { + if (XRayTraceIsAnnotation(capture, i)) { + continue; + } + + uint32_t depth = XRAY_EXTRACT_DEPTH( + XRayTraceGetEntry(capture, i)->depth_addr); + + while(*stack_top && + XRAY_EXTRACT_DEPTH((*stack_top)->depth_addr) >= depth) { + struct XRayTraceBufferEntry* e = *(stack_top--); + ppb_trace_event_interface->AddTraceEventWithThreadIdAndTimestamp( + 'E', cat_enabled, + XRayGetName(symbols, e), + 0, thread_id, + (scale_a * e->end_tick) + scale_b, + 0, NULL, NULL, NULL, 0 + ); + } + + num_args = 0; + struct XRayTraceBufferEntry* e = XRayTraceGetEntry(capture, i); + uint32_t annotation_index = e->annotation_index; + if (annotation_index) { + XRayTraceCopyToString(capture, annotation_index, annotation); + + union TraceValue val; + val.as_string = (const char*)annotation; + + arg_values[0] = val.as_uint; + num_args = 1; + } + + ppb_trace_event_interface->AddTraceEventWithThreadIdAndTimestamp( + 'B', cat_enabled, + XRayGetName(symbols, e), + 0, thread_id, + (scale_a * e->start_tick) + scale_b, + num_args, arg_names, arg_types, arg_values, 0 + ); + + *(++stack_top) = e; + } + + while(*stack_top) { + struct XRayTraceBufferEntry* e = *(stack_top--); + ppb_trace_event_interface->AddTraceEventWithThreadIdAndTimestamp( + 'E', cat_enabled, + XRayGetName(symbols, e), + 0, thread_id, + (scale_a * e->end_tick) + scale_b, + 0, NULL, NULL, NULL, 0 + ); + } + + frame = XRayFrameGetNext(capture, frame); + XRayFree(stack_base); + } +} + +void XRayRegisterBrowserInterface(PPB_GetInterface interface) { + ppb_trace_event_interface = (PPB_Trace_Event_Dev*)interface( + PPB_TRACE_EVENT_DEV_INTERFACE); + assert(ppb_trace_event_interface); +} + +#endif /* XRAY */ +#endif /* XRAY_DISABLE_BROWSER_INTEGRATION */ \ No newline at end of file diff --git a/hermit/usr/xray/demangle.c b/hermit/usr/xray/demangle.c new file mode 100644 index 000000000..e76dd23b5 --- /dev/null +++ b/hermit/usr/xray/demangle.c @@ -0,0 +1,25 @@ +/* Copyright (c) 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +#include "xray_priv.h" + +/* Note name demangling requires linking against libstdc++ */ +/* If your platform does not support __cxa_demangle, re-compile XRay with: */ +/* -DXRAY_NO_DEMANGLE */ + +#if !defined(XRAY_NO_DEMANGLE) +extern +char* __cxa_demangle(const char* __mangled_name, char* __output_buffer, + size_t* __length, int* __status); +#endif + +const char* XRayDemangle(char* demangle, size_t size, const char* symbol) { +#if !defined(XRAY_NO_DEMANGLE) + int stat; + __cxa_demangle(symbol, demangle, &size, &stat); + if (stat == 0) + return demangle; +#endif + return symbol; +} diff --git a/hermit/usr/xray/hashtable.c b/hermit/usr/xray/hashtable.c new file mode 100644 index 000000000..3fdd2d1c0 --- /dev/null +++ b/hermit/usr/xray/hashtable.c @@ -0,0 +1,205 @@ +/* Copyright (c) 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + + +/* Hashtable for XRay */ + +#include +#include +#include +#include +#include "xray_priv.h" + +#if defined(XRAY) + +struct XRayHashTableEntry { + void* data; + uint32_t key; +}; + + +struct XRayHashTable { + int capacity; + int count; + struct XRayHashTableEntry* array; +}; + + +XRAY_NO_INSTRUMENT void XRayHashTableGrow(struct XRayHashTable* table); +XRAY_NO_INSTRUMENT uint32_t XRayHashTableHashKey(uint32_t key); +XRAY_NO_INSTRUMENT void XRayHashTableInit(struct XRayHashTable* table, + int32_t capacity); + +#define HASH_HISTO 1024 +int g_hash_histo[HASH_HISTO]; + + +/* Hashes a 32bit key into a 32bit value. */ +uint32_t XRayHashTableHashKey(uint32_t x) { + uint32_t y = x * 7919; + uint32_t z; + size_t c; + uint8_t* s = (uint8_t*)&y; + /* based on djb2 hash function */ + uint32_t h = 5381; + for (c = 0; c < sizeof(y); ++c) { + z = s[c]; + h = ((h << 5) + h) + z; + } + return h; +} + + +int XRayHashTableGetCapacity(struct XRayHashTable* table) { + return table->capacity; +} + + +int XRayHashTableGetCount(struct XRayHashTable* table) { + return table->count; +} + + +/* Looks up key in hashtable and returns blind data. */ +void* XRayHashTableLookup(struct XRayHashTable* table, uint32_t key) { + uint32_t h = XRayHashTableHashKey(key); + uint32_t m = table->capacity - 1; + uint32_t j = h & m; + uint32_t i; + int z = 1; + for (i = 0; i < m; ++i) { + /* An empty entry means the {key, data} isn't in the table. */ + if (NULL == table->array[j].data) { + ++g_hash_histo[0]; + return NULL; + } + /* Search for address */ + if (table->array[j].key == key) { + if (z >= HASH_HISTO) + z = HASH_HISTO - 1; + ++g_hash_histo[z]; + return table->array[j].data; + } + j = (j + 1) & m; + ++z; + } + /* Table was full, and there wasn't a match. */ + return NULL; +} + + +/* Inserts key & data into hash table. No duplicates. */ +void* XRayHashTableInsert(struct XRayHashTable* table, + void* data, uint32_t key) { + uint32_t h = XRayHashTableHashKey(key); + uint32_t m = table->capacity - 1; + uint32_t j = h & m; + uint32_t i; + for (i = 0; i < m; ++i) { + /* Take the first empty entry. */ + /* (the key,data isn't already in the table) */ + if (NULL == table->array[j].data) { + void* ret; + float ratio; + table->array[j].data = data; + table->array[j].key = key; + ++table->count; + ret = data; + ratio = (float)table->count / (float)table->capacity; + /* Double the capacity of the symtable if we've hit the ratio. */ + if (ratio > XRAY_SYMBOL_TABLE_MAX_RATIO) + XRayHashTableGrow(table); + return ret; + } + /* If the key is already present, return the data in the table. */ + if (table->array[j].key == key) { + return table->array[j].data; + } + j = (j + 1) & m; + } + /* Table was full */ + return NULL; +} + + +void* XRayHashTableAtIndex(struct XRayHashTable* table, int i) { + if ((i < 0) || (i >= table->capacity)) + return NULL; + return table->array[i].data; +} + + +/* Grows the hash table by doubling its capacity, */ +/* then re-inserts all the elements into the new table. */ +void XRayHashTableGrow(struct XRayHashTable* table) { + struct XRayHashTableEntry* old_array = table->array; + int old_capacity = table->capacity; + int new_capacity = old_capacity * 2; + int i; + printf("XRay: Growing a hash table...\n"); + XRayHashTableInit(table, new_capacity); + for (i = 0; i < old_capacity; ++i) { + void* data = old_array[i].data; + if (NULL != data) { + uint32_t key = old_array[i].key; + XRayHashTableInsert(table, data, key); + } + } + XRayFree(old_array); +} + + +void XRayHashTableInit(struct XRayHashTable* table, int32_t capacity) { + size_t bytes; + if (0 != (capacity & (capacity - 1))) { + printf("Xray: Hash table capacity should be a power of 2!\n"); + /* Round capacity up to next power of 2 */ + /* see http://aggregate.org/MAGIC/ */ + capacity--; + capacity |= capacity >> 1; + capacity |= capacity >> 2; + capacity |= capacity >> 4; + capacity |= capacity >> 8; + capacity |= capacity >> 16; + capacity++; + } + bytes = sizeof(table->array[0]) * capacity; + table->capacity = capacity; + table->count = 0; + table->array = (struct XRayHashTableEntry*)XRayMalloc(bytes); +} + + +/* Creates & inializes hash table. */ +struct XRayHashTable* XRayHashTableCreate(int capacity) { + struct XRayHashTable* table; + table = (struct XRayHashTable*)XRayMalloc(sizeof(*table)); + XRayHashTableInit(table, capacity); + memset(&g_hash_histo[0], 0, sizeof(g_hash_histo[0]) * HASH_HISTO); + return table; +} + + +/* Prints hash table performance to file; for debugging. */ +void XRayHashTableHisto(FILE* f) { + int i; + for (i = 0; i < HASH_HISTO; ++i) { + if (0 != g_hash_histo[i]) + fprintf(f, "hash_iterations[%d] = %d\n", i, g_hash_histo[i]); + } +} + + +/* Frees hash table. */ +/* Note: Does not free what the hash table entries point to. */ +void XRayHashTableFree(struct XRayHashTable* table) { + XRayFree(table->array); + table->capacity = 0; + table->count = 0; + table->array = NULL; + XRayFree(table); +} + +#endif /* XRAY */ + diff --git a/hermit/usr/xray/libxray.spec b/hermit/usr/xray/libxray.spec new file mode 100644 index 000000000..ee2e0d06d --- /dev/null +++ b/hermit/usr/xray/libxray.spec @@ -0,0 +1,3 @@ +# Do we really need this? Does this even what we want? +*link_xray: -lxray + diff --git a/hermit/usr/xray/parsesymbols.c b/hermit/usr/xray/parsesymbols.c new file mode 100644 index 000000000..1320ea59f --- /dev/null +++ b/hermit/usr/xray/parsesymbols.c @@ -0,0 +1,96 @@ +/* Copyright (c) 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + + +/* XRay -- a simple profiler for Native Client */ + +#include +#include +#include +#include +#include +#include "xray_priv.h" + +#if defined(XRAY) + +struct XRaySymbol* XRaySymbolTableCreateEntry(struct XRaySymbolTable* symtab, + char* line) { + uint32_t addr; + unsigned int uiaddr; + char symbol_text[XRAY_LINE_SIZE]; + char* parsed_symbol; + char* newln; + if (2 != sscanf(line, "%x %1023s", &uiaddr, symbol_text)) + return NULL; + if (uiaddr > 0x07FFFFFF) { + fprintf(stderr, "While parsing the mapfile, XRay encountered:\n"); + fprintf(stderr, "%s\n", line); + fprintf(stderr, + "XRay only works with code addresses 0x00000000 - 0x07FFFFFF\n"); + fprintf(stderr, "All functions must reside in this address space.\n"); + exit(-1); + } + addr = (uint32_t)uiaddr; + parsed_symbol = strstr(line, symbol_text); + newln = strstr(parsed_symbol, "\n"); + if (NULL != newln) { + *newln = 0; + } + return XRaySymbolTableAddByName(symtab, parsed_symbol, addr); +} + + +void XRaySymbolTableParseMapfile(struct XRaySymbolTable* symtab, + const char* mapfile) { + FILE* f; + char line[XRAY_LINE_SIZE]; + bool in_text = false; + bool in_link_once = false; + int in_link_once_counter = 0; + int num_symbols = 0; + + printf("XRay: opening mapfile %s\n", mapfile); + f = fopen(mapfile, "rt"); + if (0 == f) { + fprintf(stderr, "XRay: failed to open %s\n", mapfile); + return; + } + printf("XRay: parsing...\n"); + while (NULL != fgets(line, XRAY_LINE_SIZE, f)) { + if (line == strstr(line, " .text ")) { + in_text = true; + continue; + } + if (line == strstr(line, " .gnu.linkonce.t.")) { + in_link_once = true; + in_link_once_counter = 0; + continue; + } + if (line == strstr(line, " .text.")) { + in_link_once = true; + in_link_once_counter = 0; + continue; + } + if (line == strstr(line, " 0x")) { + if (in_text) { + XRaySymbolTableCreateEntry(symtab, line); + ++num_symbols; + } else if (in_link_once) { + if (in_link_once_counter != 0) { + if (NULL != XRaySymbolTableCreateEntry(symtab, line)) + ++num_symbols; + } else { + ++in_link_once_counter; + } + } + } else { + in_text = false; + in_link_once = false; + } + } + fclose(f); + printf("XRay: parsed %d symbols into symbol table\n", num_symbols); +} + +#endif // XRAY diff --git a/hermit/usr/xray/report.c b/hermit/usr/xray/report.c new file mode 100644 index 000000000..a0a8d5475 --- /dev/null +++ b/hermit/usr/xray/report.c @@ -0,0 +1,211 @@ +/* Copyright (c) 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + + +/* XRay -- a simple profiler for Native Client */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "xray_priv.h" + +#if defined(XRAY) + +struct XRayTotal { + int index; + int frame; + uint64_t ticks; +}; + + +/* Dumps the trace report for a given frame. */ +void XRayTraceReport(struct XRayTraceCapture* capture, + FILE* f, + int frame, + char* label, + float percent_cutoff, + int ticks_cutoff) { + int index; + int start; + int end; + float total; + char space[257]; + struct XRaySymbolTable* symbols = XRayGetSymbolTable(capture); + memset(space, ' ', 256); + space[256] = 0; + if (NULL == f) { + f = stdout; + } + fprintf(f, + "====================================================================\n"); + if (NULL != label) + fprintf(f, "label %s\n", label); + fprintf(f, "\n"); + fprintf(f, + " Address Ticks Percent Function [annotation...]\n"); + fprintf(f, + "--------------------------------------------------------------------\n"); + total = XRayFrameGetTotalTicks(capture, frame); + start = XRayFrameGetTraceStartIndex(capture, frame); + end = XRayFrameGetTraceEndIndex(capture, frame); + index = start; + while (index != end) { + if (!XRayTraceIsAnnotation(capture, index)) { + const char* symbol_name; + char annotation[XRAY_TRACE_ANNOTATION_LENGTH]; + struct XRayTraceBufferEntry* e = XRayTraceGetEntry(capture, index); + uint32_t depth = XRAY_EXTRACT_DEPTH(e->depth_addr); + uint32_t addr = XRAY_EXTRACT_ADDR(e->depth_addr); + uint32_t annotation_index = e->annotation_index; + uint64_t ticks = + e->end_tick > e->start_tick ? e->end_tick - e->start_tick : 0; + float percent = 100.0f * (float)ticks / total; + if (percent >= percent_cutoff && ticks >= ticks_cutoff) { + struct XRaySymbol* symbol; + symbol = XRaySymbolTableLookup(symbols, addr); + symbol_name = XRaySymbolGetName(symbol); + if (0 != annotation_index) { + XRayTraceCopyToString(capture, annotation_index, annotation); + } else { + strcpy(annotation, ""); + } + fprintf(f, "0x%08X %12" PRIu64 " %5.1f %s%s %s\n", + (unsigned int)addr, ticks, percent, + &space[256 - depth], symbol_name, annotation); + } + } + index = XRayTraceNextEntry(capture, index); + } + fflush(f); +} + + +int qcompare(const void* a, const void* b) { + struct XRayTotal* ia = (struct XRayTotal*)a; + struct XRayTotal* ib = (struct XRayTotal*)b; + if (ib->ticks > ia->ticks) + return 1; + else if (ib->ticks < ia->ticks) + return -1; + return 0; +} + + +/* Dumps a frame report */ +void XRayFrameReport(struct XRayTraceCapture* capture, FILE* f) { + int i; + int head = XRayFrameGetHead(capture); + int frame = XRayFrameGetTail(capture); + int counter = 0; + int total_capture = 0; + struct XRayTotal* totals; + totals = (struct XRayTotal*) + alloca(XRayFrameGetCount(capture) * sizeof(struct XRayTotal)); + fprintf(f, "\n"); + fprintf(f, + "Frame# Total Ticks Capture size Annotations Label\n"); + fprintf(f, + "--------------------------------------------------------------------\n"); + while (frame != head) { + uint64_t total_ticks = XRayFrameGetTotalTicks(capture, frame); + int capture_size = XRayFrameGetTraceCount(capture, frame); + int annotation_count = XRayFrameGetAnnotationCount(capture, frame); + bool valid = XRayFrameIsValid(capture, frame); + char label[XRAY_MAX_LABEL]; + XRayFrameMakeLabel(capture, counter, label); + fprintf(f, " %3d %s %12" PRIu64 " %10d %10d %s\n", + counter, + valid ? " " : "*", + total_ticks, + capture_size, + annotation_count, + label); + totals[counter].index = counter; + totals[counter].frame = frame; + totals[counter].ticks = total_ticks; + total_capture += capture_size; + ++counter; + frame = XRayFrameGetNext(capture, frame); + } + fprintf(f, + "--------------------------------------------------------------------\n"); + fprintf(f, + "XRay: %d frame(s) %d total capture(s)\n", counter, total_capture); + fprintf(f, "\n"); + /* Sort and take average of the median cut */ + qsort(totals, counter, sizeof(struct XRayTotal), qcompare); + fprintf(f, "\n"); + fprintf(f, "Sorted by total ticks (most expensive first):\n"); + fprintf(f, "\n"); + fprintf(f, + "Frame# Total Ticks Capture size Annotations Label\n"); + fprintf(f, + "--------------------------------------------------------------------\n"); + for (i = 0; i < counter; ++i) { + int index = totals[i].index; + int frame = totals[i].frame; + uint64_t total_ticks = XRayFrameGetTotalTicks(capture, frame); + int capture_size = XRayFrameGetTraceCount(capture, frame); + int annotation_count = XRayFrameGetAnnotationCount(capture, frame); + char label[XRAY_MAX_LABEL]; + XRayFrameMakeLabel(capture, index, label); + fprintf(f, " %3d %12" PRIu64 " %10d %10d %s\n", + index, + total_ticks, + capture_size, + annotation_count, + label); + } + fflush(f); +} + + +/* Dump a frame report followed by trace report(s) for each frame. */ +void XRayReport(struct XRayTraceCapture* capture, + FILE* f, + float percent_cutoff, + int ticks_cutoff) { + int head = XRayFrameGetHead(capture); + int frame = XRayFrameGetTail(capture); + int counter = 0; + XRayFrameReport(capture, f); + fprintf(f, "\n"); + while (frame != head) { + char label[XRAY_MAX_LABEL]; + fprintf(f, "\n"); + XRayFrameMakeLabel(capture, counter, label); + XRayTraceReport(capture, f, frame, label, percent_cutoff, ticks_cutoff); + ++counter; + frame = XRayFrameGetNext(capture, frame); + } + fprintf(f, + "====================================================================\n"); +#if defined(XRAY_OUTPUT_HASH_COLLISIONS) + XRayHashTableHisto(capture, f); +#endif + fflush(f); +} + +/* Write a profile report to text file. */ +void XRaySaveReport(struct XRayTraceCapture* capture, + const char* filename, + float percent_cutoff, + int ticks_cutoff) { + FILE* f; + f = fopen(filename, "w"); + if (NULL != f) { + XRayReport(capture, f, percent_cutoff, ticks_cutoff); + fclose(f); + } else { + printf("Cannot open file '%s'\n", filename); + } +} + +#endif /* XRAY */ diff --git a/hermit/usr/xray/stringpool.c b/hermit/usr/xray/stringpool.c new file mode 100644 index 000000000..25ac38f02 --- /dev/null +++ b/hermit/usr/xray/stringpool.c @@ -0,0 +1,94 @@ +/* Copyright (c) 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + + +/* XRay string pool */ + +/* String pool holds a large pile of strings. */ +/* It is up to higher level data structures to avoid duplicates. */ +/* It is up to higher level data structures to provide fast lookups. */ + +/* _GNU_SOURCE must be defined prior to the inclusion of string.h + * so that strnlen is available with glibc */ +#define _GNU_SOURCE +#include +#include +#include "xray_priv.h" + +#if defined(XRAY) + +struct XRayStringPoolNode { + struct XRayStringPoolNode* next; + char strings[XRAY_STRING_POOL_NODE_SIZE]; +}; + + +struct XRayStringPool { + struct XRayStringPoolNode* head; + struct XRayStringPoolNode* current; + int index; +}; + + +static struct XRayStringPoolNode* XRayStringPoolAllocNode() { + struct XRayStringPoolNode* s; + s = (struct XRayStringPoolNode *)XRayMalloc(sizeof(*s)); + s->next = NULL; + return s; +} + + +static int XRayStringPoolCurrentNodeSpaceAvail(struct XRayStringPool* pool) { + int i = pool->index; + return (XRAY_STRING_POOL_NODE_SIZE - i) - 1; +} + + +/* Append a string to the string pool. */ +char* XRayStringPoolAppend(struct XRayStringPool* pool, const char* src) { + /* Add +1 to STRING_POOL_NODE_SIZE to detect large strings */ + /* Add +1 to strnlen result to account for string termination */ + int n = strnlen(src, XRAY_STRING_POOL_NODE_SIZE + 1) + 1; + int a = XRayStringPoolCurrentNodeSpaceAvail(pool); + char* dst; + /* Don't accept strings larger than the pool node. */ + if (n >= (XRAY_STRING_POOL_NODE_SIZE - 1)) + return NULL; + /* If string doesn't fit, alloc a new node. */ + if (n > a) { + pool->current->next = XRayStringPoolAllocNode(); + pool->current = pool->current->next; + pool->index = 0; + } + /* Copy string and return a pointer to copy. */ + dst = &pool->current->strings[pool->index]; + strcpy(dst, src); + pool->index += n; + return dst; +} + + +/* Create & initialize a string pool instance. */ +struct XRayStringPool* XRayStringPoolCreate() { + struct XRayStringPool* pool; + pool = (struct XRayStringPool*)XRayMalloc(sizeof(*pool)); + pool->head = XRayStringPoolAllocNode(); + pool->current = pool->head; + return pool; +} + + +/* Free a string pool. */ +void XRayStringPoolFree(struct XRayStringPool* pool) { + struct XRayStringPoolNode* n = pool->head; + while (NULL != n) { + struct XRayStringPoolNode* c = n; + n = n->next; + XRayFree(c); + } + XRayFree(pool); +} + +#endif /* XRAY */ + diff --git a/hermit/usr/xray/symtable.c b/hermit/usr/xray/symtable.c new file mode 100644 index 000000000..37edba704 --- /dev/null +++ b/hermit/usr/xray/symtable.c @@ -0,0 +1,200 @@ +/* Copyright (c) 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +/* XRay symbol table */ + +#define _GNU_SOURCE +#include +#include +#include +#include + +#if defined(__GLIBC__) +#include +#endif + +#include "xray_priv.h" +#define PNACL_STRING_OFFSET (0x10000000) + +#if defined(XRAY) + +bool g_symtable_debug = false; + +struct XRayFrameInfo { + int times_called; + int total_ticks; +}; + + +struct XRaySymbol { + const char* name; + struct XRayFrameInfo frames[XRAY_MAX_FRAMES]; +}; + + +struct XRaySymbolPoolNode { + struct XRaySymbolPoolNode* next; + struct XRaySymbol symbols[XRAY_SYMBOL_POOL_NODE_SIZE]; +}; + + +struct XRaySymbolPool { + struct XRaySymbolPoolNode* head; + struct XRaySymbolPoolNode* current; + int index; +}; + + +struct XRaySymbolTable { + int num_symbols; + struct XRayHashTable* hash_table; + struct XRayStringPool* string_pool; + struct XRaySymbolPool* symbol_pool; +}; + + +const char* XRaySymbolGetName(struct XRaySymbol* symbol) { + return (NULL == symbol) ? "(null)" : symbol->name; +} + + +struct XRaySymbol* XRaySymbolCreate(struct XRaySymbolPool* sympool, + const char* name) +{ + struct XRaySymbol* symbol; + symbol = XRaySymbolPoolAlloc(sympool); + symbol->name = name; + return symbol; +} + + +struct XRaySymbol* XRaySymbolPoolAlloc(struct XRaySymbolPool* sympool) { + struct XRaySymbol* symbol; + if (sympool->index >= XRAY_SYMBOL_POOL_NODE_SIZE) { + struct XRaySymbolPoolNode* new_pool; + new_pool = (struct XRaySymbolPoolNode*)XRayMalloc(sizeof(*new_pool)); + sympool->current->next = new_pool; + sympool->current = new_pool; + sympool->index = 0; + } + symbol = &sympool->current->symbols[sympool->index]; + ++sympool->index; + return symbol; +} + + +struct XRaySymbolPool* XRaySymbolPoolCreate() { + struct XRaySymbolPool* sympool; + struct XRaySymbolPoolNode* node; + sympool = (struct XRaySymbolPool*)XRayMalloc(sizeof(*sympool)); + node = (struct XRaySymbolPoolNode*)XRayMalloc(sizeof(*node)); + sympool->head = node; + sympool->current = node; + sympool->index = 0; + return sympool; +} + + +void XRaySymbolPoolFree(struct XRaySymbolPool* pool) { + struct XRaySymbolPoolNode* n = pool->head; + while (NULL != n) { + struct XRaySymbolPoolNode* c = n; + n = n->next; + XRayFree(c); + } + XRayFree(pool); +} + + +int XRaySymbolTableGetCount(struct XRaySymbolTable* symtab) { + return XRayHashTableGetCount(symtab->hash_table); +} + + +struct XRaySymbol* XRaySymbolTableAtIndex(struct XRaySymbolTable* symtab, + int i) { + return (struct XRaySymbol*)XRayHashTableAtIndex(symtab->hash_table, i); +} + +struct XRaySymbol* XRaySymbolTableAdd(struct XRaySymbolTable* symtab, + struct XRaySymbol* symbol, + uint32_t addr) { + struct XRaySymbol* sym = (struct XRaySymbol*) + XRayHashTableInsert(symtab->hash_table, symbol, addr); + symtab->num_symbols = XRayHashTableGetCount(symtab->hash_table); + return sym; +} + +struct XRaySymbol* XRaySymbolTableAddByName(struct XRaySymbolTable* symtab, + const char* name, uint32_t addr) { + char* recorded_name; + struct XRaySymbol* symbol; + char buffer[XRAY_LINE_SIZE]; + const char* demangled_name = XRayDemangle(buffer, XRAY_LINE_SIZE, name); + /* record the demangled symbol name into the string pool */ + recorded_name = XRayStringPoolAppend(symtab->string_pool, demangled_name); + if (g_symtable_debug) + printf("adding symbol %s\n", recorded_name); + /* construct a symbol and put it in the symbol table */ + symbol = XRaySymbolCreate(symtab->symbol_pool, recorded_name); + return XRaySymbolTableAdd(symtab, symbol, addr); +} + +struct XRaySymbol* XRaySymbolTableLookup(struct XRaySymbolTable* symtab, + uint32_t addr) { + void *x = XRayHashTableLookup(symtab->hash_table, addr); + struct XRaySymbol* r = (struct XRaySymbol*)x; + +#if defined(__pnacl__) + if (r == NULL) { + /* Addresses are trimed to 24 bits for internal storage, so we need to + * add this offset back in order to get the real address. + */ + addr |= PNACL_STRING_OFFSET; + const char* name = (const char*)addr; + struct XRaySymbol* symbol = XRaySymbolCreate(symtab->symbol_pool, name); + r = XRaySymbolTableAdd(symtab, symbol, addr); + } +#endif + +#if defined(__GLIBC__) + if (r == NULL) { + Dl_info info; + if (dladdr((const void*)addr, &info) != 0) + if (info.dli_sname) + r = XRaySymbolTableAddByName(symtab, info.dli_sname, addr); + } +#endif + return r; +} + + +/* Returns total number of symbols in the table. */ +int XRaySymbolCount(struct XRaySymbolTable* symtab) { + return symtab->num_symbols; +} + + +/* Creates and inializes a symbol table. */ +struct XRaySymbolTable* XRaySymbolTableCreate(int size) { + struct XRaySymbolTable* symtab; + symtab = (struct XRaySymbolTable*)XRayMalloc(sizeof(*symtab)); + symtab->num_symbols = 0; + symtab->string_pool = XRayStringPoolCreate(); + symtab->hash_table = XRayHashTableCreate(size); + symtab->symbol_pool = XRaySymbolPoolCreate(); + return symtab; +} + + +/* Frees a symbol table. */ +void XRaySymbolTableFree(struct XRaySymbolTable* symtab) { + XRayStringPoolFree(symtab->string_pool); + XRaySymbolPoolFree(symtab->symbol_pool); + XRayHashTableFree(symtab->hash_table); + symtab->num_symbols = 0; + XRayFree(symtab); +} + +#endif /* XRAY */ diff --git a/hermit/usr/xray/xray.c b/hermit/usr/xray/xray.c new file mode 100644 index 000000000..6b48dcb56 --- /dev/null +++ b/hermit/usr/xray/xray.c @@ -0,0 +1,809 @@ +/* Copyright (c) 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + + +/* XRay -- a simple profiler for Native Client */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "xray_priv.h" + +#if defined(XRAY) + +/* GTSC - Get Time Stamp Counter */ +#if defined(__amd64__) && !defined(XRAY_NO_RDTSC) +XRAY_INLINE uint64_t RDTSC64(); +uint64_t RDTSC64() { + uint64_t a, d; + __asm__ __volatile__("rdtsc" : "=a" (a), "=d" (d)); + return ((uint64_t)a) | (((uint64_t)d) << 32); +} +#define GTSC(_x) _x = RDTSC64() +#elif defined(__i386__) && !defined(XRAY_NO_RDTSC) +#define GTSC(_x) __asm__ __volatile__ ("rdtsc" : "=A" (_x)); +#else +XRAY_INLINE uint64_t GTOD(); +uint64_t GTOD() { + struct timeval tv; + gettimeofday(&tv, NULL); + return (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec; +} +#define GTSC(_x) _x = GTOD(); +#endif + +/* Use a TLS variable for cheap thread uid. */ +__thread struct XRayTraceCapture* g_xray_capture = NULL; +__thread int g_xray_thread_id_placeholder = 0; + + +struct XRayTraceStackEntry { + uint32_t depth_addr; + uint64_t tsc; + uint32_t dest; + uint32_t annotation_index; +}; + + +struct XRayTraceFrameEntry { + /* Indices into global tracebuffer */ + int start; + int end; + uint64_t start_tsc; + uint64_t end_tsc; + uint64_t total_ticks; + int annotation_count; + bool valid; + +#ifndef XRAY_DISABLE_BROWSER_INTEGRATION + struct XRayTimestampPair start_time; + struct XRayTimestampPair end_time; +#endif +}; + + +struct XRayTraceFrame { + struct XRayTraceFrameEntry* entry; + int head; + int tail; + int count; +}; + + +struct XRayTraceCapture { + /* Common variables share cache line */ + bool recording; + uint32_t stack_depth; + uint32_t max_stack_depth; + int buffer_index; + int buffer_size; + int disabled; + int annotation_count; + struct XRaySymbolTable* symbols; + bool initialized; + uint32_t annotation_filter; + uint32_t guard0; + struct XRayTraceStackEntry stack[XRAY_TRACE_STACK_SIZE] XRAY_ALIGN64; + uint32_t guard1; + uint32_t guard2; + char annotation[XRAY_ANNOTATION_STACK_SIZE] XRAY_ALIGN64; + uint32_t guard3; + struct XRayTraceBufferEntry* buffer; + struct XRayTraceFrame frame; + char frame_labels[XRAY_FRAME_LBL_BUFSIZE][XRAY_MAX_LABEL]; + +#ifndef XRAY_DISABLE_BROWSER_INTEGRATION + int32_t thread_id; +#endif +} XRAY_ALIGN64; + + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__pnacl__) +XRAY_NO_INSTRUMENT void __pnacl_profile_func_enter(const char* fname); +XRAY_NO_INSTRUMENT void __pnacl_profile_func_exit(const char* fname); +#else +XRAY_NO_INSTRUMENT void __cyg_profile_func_enter(void* this_fn, + void* call_site); +XRAY_NO_INSTRUMENT void __cyg_profile_func_exit(void* this_fn, + void* call_site); +#endif + +XRAY_INLINE int XRayTraceDecrementIndexInline( + struct XRayTraceCapture* capture, int index); +XRAY_INLINE int XRayTraceIncrementIndexInline( + struct XRayTraceCapture* capture, int index); + + +XRAY_NO_INSTRUMENT void __xray_profile_append_annotation( + struct XRayTraceCapture* capture, + struct XRayTraceStackEntry* se, + struct XRayTraceBufferEntry* be); + +#ifdef __cplusplus +} +#endif + +/* Asserts that the guard values haven't changed. */ +void XRayCheckGuards(struct XRayTraceCapture* capture) { + assert(capture->guard0 == XRAY_GUARD_VALUE_0x12345678); + assert(capture->guard1 == XRAY_GUARD_VALUE_0x12345678); + assert(capture->guard2 == XRAY_GUARD_VALUE_0x87654321); + assert(capture->guard3 == XRAY_GUARD_VALUE_0x12345678); +} + +/* Decrements the trace index, wrapping around if needed. */ +int XRayTraceDecrementIndexInline( + struct XRayTraceCapture* capture, int index) { + --index; + if (index < 0) + index = capture->buffer_size - 1; + return index; +} + +/* Increments the trace index, wrapping around if needed. */ +int XRayTraceIncrementIndexInline( + struct XRayTraceCapture* capture, int index) { + ++index; + if (index >= capture->buffer_size) + index = 0; + return index; +} + +/* Returns true if the trace entry is an annotation string. */ +bool XRayTraceIsAnnotation( + struct XRayTraceCapture* capture, int index) { + struct XRayTraceBufferEntry* be = &capture->buffer[index]; + char* dst = (char*)be; + return 0 == *dst; +} + +int XRayTraceIncrementIndex(struct XRayTraceCapture* capture, int index) { + return XRayTraceIncrementIndexInline(capture, index); +} + +int XRayTraceDecrementIndex(struct XRayTraceCapture* capture, int index) { + return XRayTraceDecrementIndexInline(capture, index); +} + +/* The entry in the tracebuffer at index is an annotation string. */ +/* Calculate the next index value representing the next trace entry. */ +int XRayTraceSkipAnnotation(struct XRayTraceCapture* capture, int index) { + /* Annotations are strings embedded in the trace buffer. */ + /* An annotation string can span multiple trace entries. */ + /* Skip over the string by looking for zero termination. */ + assert(capture); + assert(XRayTraceIsAnnotation(capture, index)); + bool done = false; + int start_index = 1; + int i; + while (!done) { + char* str = (char*) &capture->buffer[index]; + const int num = sizeof(capture->buffer[index]); + for (i = start_index; i < num; ++i) { + if (0 == str[i]) { + done = true; + break; + } + } + index = XRayTraceIncrementIndexInline(capture, index); + start_index = 0; + } + return index; +} + + +struct XRayTraceBufferEntry* XRayTraceGetEntry( + struct XRayTraceCapture* capture, int index) { + return &capture->buffer[index]; +} + +/* Starting at index, return the index into the trace buffer */ +/* for the next trace entry. Index can wrap (ringbuffer) */ +int XRayTraceNextEntry(struct XRayTraceCapture* capture, int index) { + if (XRayTraceIsAnnotation(capture, index)) + index = XRayTraceSkipAnnotation(capture, index); + else + index = XRayTraceIncrementIndexInline(capture, index); + return index; +} + +int XRayFrameGetTraceStartIndex(struct XRayTraceCapture* capture, int frame) { + assert(capture); + assert(capture->initialized); + assert(!capture->recording); + return capture->frame.entry[frame].start; +} + +int XRayFrameGetTraceEndIndex(struct XRayTraceCapture* capture, int frame) { + assert(capture); + assert(capture->initialized); + assert(!capture->recording); + return capture->frame.entry[frame].end; +} + +/* Not very accurate, annotation strings will also be counted as "entries" */ +int XRayFrameGetTraceCount( + struct XRayTraceCapture* capture, int frame) { + assert(true == capture->initialized); + assert(frame >= 0); + assert(frame < capture->frame.count); + assert(!capture->recording); + int start = capture->frame.entry[frame].start; + int end = capture->frame.entry[frame].end; + int num; + if (start < end) + num = end - start; + else + num = capture->buffer_size - (start - end); + return num; +} + +/* Append a string to trace buffer. */ +void XRayTraceAppendString(struct XRayTraceCapture* capture, char* src) { + int index = capture->buffer_index; + bool done = false; + int start_index = 1; + int s = 0; + int i; + char* dst = (char*)&capture->buffer[index]; + const int num = sizeof(capture->buffer[index]); + dst[0] = 0; + while (!done) { + for (i = start_index; i < num; ++i) { + dst[i] = src[s]; + if (0 == src[s]) { + dst[i] = 0; + done = true; + break; + } + ++s; + } + index = XRayTraceIncrementIndexInline(capture, index); + dst = (char*)&capture->buffer[index]; + start_index = 0; + } + capture->buffer_index = index; +} + +/* Copies annotation from trace buffer to output string. */ +int XRayTraceCopyToString( + struct XRayTraceCapture* capture, int index, char* dst) { + assert(XRayTraceIsAnnotation(capture, index)); + bool done = false; + int i; + int d = 0; + int start_index = 1; + while (!done) { + char* src = (char*) &capture->buffer[index]; + const int num = sizeof(capture->buffer[index]); + for (i = start_index; i < num; ++i) { + dst[d] = src[i]; + if (0 == src[i]) { + done = true; + break; + } + ++d; + } + index = XRayTraceIncrementIndexInline(capture, index); + start_index = 0; + } + return index; +} + + +/* Generic memory malloc for XRay */ +/* validates pointer returned by malloc */ +/* memsets memory block to zero */ +void* XRayMalloc(size_t t) { + void* data; + data = calloc(1, t); + if (NULL == data) { + printf("XRay: malloc(%d) failed, panic shutdown!\n", t); + exit(-1); + } + return data; +} + + +/* Generic memory free for XRay */ +void XRayFree(void* data) { + assert(NULL != data); + free(data); +} + + +/* Main profile capture function that is called at the start */ +/* of every instrumented function. This function is implicitly */ +/* called when code is compilied with the -finstrument-functions option */ +#if defined(__pnacl__) +void __pnacl_profile_func_enter(const char* this_fn) { +#else +void __cyg_profile_func_enter(void* this_fn, void* call_site) { +#endif + struct XRayTraceCapture* capture = g_xray_capture; + if (capture && capture->recording) { + uint32_t depth = capture->stack_depth; + if (depth < capture->max_stack_depth) { + struct XRayTraceStackEntry* se = &capture->stack[depth]; + uint32_t addr = (uint32_t)(uintptr_t)this_fn; + se->depth_addr = XRAY_PACK_DEPTH_ADDR(depth, addr); + se->dest = capture->buffer_index; + se->annotation_index = 0; + GTSC(se->tsc); + capture->buffer_index = + XRayTraceIncrementIndexInline(capture, capture->buffer_index); + } + ++capture->stack_depth; + } +} + + +/* Main profile capture function that is called at the exit of */ +/* every instrumented function. This function is implicity called */ +/* when the code is compiled with the -finstrument-functions option */ +#if defined(__pnacl__) +void __pnacl_profile_func_exit(const char* this_fn) { +#else +void __cyg_profile_func_exit(void* this_fn, void* call_site) { +#endif + struct XRayTraceCapture* capture = g_xray_capture; + if (capture && capture->recording) { + --capture->stack_depth; + if (capture->stack_depth < capture->max_stack_depth) { + uint32_t depth = capture->stack_depth; + struct XRayTraceStackEntry* se = &capture->stack[depth]; + uint32_t buffer_index = se->dest; + uint64_t tsc; + struct XRayTraceBufferEntry* be = &capture->buffer[buffer_index]; + GTSC(tsc); + be->depth_addr = se->depth_addr; + be->start_tick = se->tsc; + be->end_tick = tsc; + be->annotation_index = 0; + if (0 != se->annotation_index) + __xray_profile_append_annotation(capture, se, be); + } + } +} + +#ifndef XRAY_DISABLE_BROWSER_INTEGRATION +void XRayGetTSC(uint64_t* tsc) { + GTSC(*tsc); +} + +int32_t XRayGetSavedThreadID(struct XRayTraceCapture* capture) { + return capture->thread_id; +} + +struct XRayTimestampPair XRayFrameGetStartTimestampPair( + struct XRayTraceCapture* capture, int frame) { + return capture->frame.entry[frame].start_time; +} + +struct XRayTimestampPair XRayFrameGetEndTimestampPair( + struct XRayTraceCapture* capture, int frame) { + return capture->frame.entry[frame].end_time; +} +#endif + +/* Special case appending annotation string to trace buffer */ +/* this function should only ever be called from __cyg_profile_func_exit() */ +void __xray_profile_append_annotation(struct XRayTraceCapture* capture, + struct XRayTraceStackEntry* se, + struct XRayTraceBufferEntry* be) { + struct XRayTraceStackEntry* parent = se - 1; + int start = parent->annotation_index; + be->annotation_index = capture->buffer_index; + char* str = &capture->annotation[start]; + XRayTraceAppendString(capture, str); + *str = 0; + ++capture->annotation_count; +} + + + +/* Annotates the trace buffer. no filtering. */ +void __XRayAnnotate(const char* fmt, ...) { + va_list args; + struct XRayTraceCapture* capture = g_xray_capture; + /* Only annotate functions recorded in the trace buffer. */ + if (capture && capture->initialized) { + if (0 == capture->disabled) { + if (capture->recording) { + char buffer[1024]; + int r; + va_start(args, fmt); + r = vsnprintf(buffer, sizeof(buffer), fmt, args); + va_end(args); + { + /* Get current string ptr */ + int depth = capture->stack_depth - 1; + struct XRayTraceStackEntry* se = &capture->stack[depth]; + if (0 == se->annotation_index) { + struct XRayTraceStackEntry* parent = se - 1; + se->annotation_index = parent->annotation_index; + } + char* dst = &capture->annotation[se->annotation_index]; + strcpy(dst, buffer); + int len = strlen(dst); + se->annotation_index += len; + } + } + } + } +} + + +/* Annotates the trace buffer with user strings. Can be filtered. */ +void __XRayAnnotateFiltered(const uint32_t filter, const char* fmt, ...) { + va_list args; + struct XRayTraceCapture* capture = g_xray_capture; + if (capture && capture->initialized) { + if (0 != (filter & capture->annotation_filter)) { + if (0 == capture->disabled) { + if (capture->recording) { + char buffer[XRAY_TRACE_ANNOTATION_LENGTH]; + int r; + va_start(args, fmt); + r = vsnprintf(buffer, sizeof(buffer), fmt, args); + va_end(args); + { + /* get current string ptr */ + int depth = capture->stack_depth - 1; + struct XRayTraceStackEntry* se = &capture->stack[depth]; + if (0 == se->annotation_index) { + struct XRayTraceStackEntry* parent = se - 1; + se->annotation_index = parent->annotation_index; + } + char* dst = &capture->annotation[se->annotation_index]; + strcpy(dst, buffer); + int len = strlen(dst); + se->annotation_index += len; + } + } + } + } + } +} + + +/* Allows user to specify annotation filter value, a 32 bit mask. */ +void XRaySetAnnotationFilter(struct XRayTraceCapture* capture, + uint32_t filter) { + capture->annotation_filter = filter; +} + + +/* Reset xray profiler. */ +void XRayReset(struct XRayTraceCapture* capture) { + assert(capture); + assert(capture->initialized); + assert(!capture->recording); + capture->buffer_index = 0; + capture->stack_depth = 0; + capture->disabled = 0; + capture->frame.head = 0; + capture->frame.tail = 0; + memset(capture->frame.entry, 0, + sizeof(capture->frame.entry[0]) * capture->frame.count); + memset(&capture->stack, 0, + sizeof(capture->stack[0]) * XRAY_TRACE_STACK_SIZE); + XRayCheckGuards(capture); +} + + +/* Change the maximum stack depth captures are made. */ +void XRaySetMaxStackDepth(struct XRayTraceCapture* capture, int stack_depth) { + assert(capture); + assert(capture->initialized); + assert(!capture->recording); + if (stack_depth < 1) + stack_depth = 1; + if (stack_depth >= XRAY_TRACE_STACK_SIZE) + stack_depth = (XRAY_TRACE_STACK_SIZE - 1); + capture->max_stack_depth = stack_depth; +} + + +int XRayFrameGetCount(struct XRayTraceCapture* capture) { + return capture->frame.count; +} + +int XRayFrameGetTail(struct XRayTraceCapture* capture) { + return capture->frame.tail; +} + +int XRayFrameGetHead(struct XRayTraceCapture* capture) { + return capture->frame.head; +} + +int XRayFrameGetPrev(struct XRayTraceCapture* capture, int i) { + i = i - 1; + if (i < 0) + i = capture->frame.count - 1; + return i; +} + +int XRayFrameGetNext(struct XRayTraceCapture* capture, int i) { + i = i + 1; + if (i >= capture->frame.count) + i = 0; + return i; +} + +bool XRayFrameIsValid(struct XRayTraceCapture* capture, int i) { + return capture->frame.entry[i].valid; +} + +uint64_t XRayFrameGetTotalTicks(struct XRayTraceCapture* capture, int i) { + return capture->frame.entry[i].total_ticks; +} + +int XRayFrameGetAnnotationCount(struct XRayTraceCapture* capture, int i) { + return capture->frame.entry[i].annotation_count; +} + +void XRayFrameMakeLabel(struct XRayTraceCapture* capture, + int counter, + char* label) { + if(counter < sizeof(capture->frame_labels) && capture->frame_labels[counter][0]) { + snprintf(label, XRAY_MAX_LABEL, "%s", capture->frame_labels[counter]); + } else { + snprintf(label, XRAY_MAX_LABEL, "frame_%i", counter); + } +} +void XRayLabelFrame(const char* fmt, ...) +{ + char buffer[32]; + int r; + va_list args; + + va_start(args, fmt); + r = vsnprintf(buffer, sizeof(buffer), fmt, args); + if(r != 0) { + const int n = XRayFrameGetHead(g_xray_capture); + if(n < sizeof(g_xray_capture->frame_labels)) { + strcpy(g_xray_capture->frame_labels[n], buffer); + } else { + puts("XRay: Not enough entries in frame label buffer"); + puts(" Add -DXRAY_FRAME_LBL_BUFSIZE=[n] to your CFLAGS"); + } + } + va_end(args); +} + + +/* Scans the ring buffer going backwards to find last valid complete frame. */ +/* Will mark whether frames are valid or invalid during the traversal. */ +int XRayFrameFindTail(struct XRayTraceCapture* capture) { + int head = capture->frame.head; + int index = XRayFrameGetPrev(capture, head); + int total_capture = 0; + int last_valid_frame = index; + /* Check for no captures */ + if (capture->frame.head == capture->frame.tail) + return capture->frame.head; + /* Go back and invalidate all captures that have been stomped. */ + while (index != head) { + bool valid = capture->frame.entry[index].valid; + if (valid) { + total_capture += XRayFrameGetTraceCount(capture, index) + 1; + if (total_capture < capture->buffer_size) { + last_valid_frame = index; + capture->frame.entry[index].valid = true; + } else { + capture->frame.entry[index].valid = false; + } + } + index = XRayFrameGetPrev(capture, index); + } + return last_valid_frame; +} + + +/* Starts a new frame and enables capturing, and must be paired with */ +/* XRayEndFrame() Trace capturing only occurs on the thread which called */ +/* XRayBeginFrame() and each instance of capture can only trace one thread */ +/* at a time. */ +void XRayStartFrame(struct XRayTraceCapture* capture) { + int i; + assert(NULL == g_xray_capture); + assert(capture->initialized); + assert(!capture->recording); + i = capture->frame.head; + XRayCheckGuards(capture); + /* Add a trace entry marker so we can detect wrap around stomping */ + struct XRayTraceBufferEntry* be = &capture->buffer[capture->buffer_index]; + be->depth_addr = XRAY_FRAME_MARKER; + capture->buffer_index = + XRayTraceIncrementIndex(capture, capture->buffer_index); + /* Set start of the frame we're about to trace */ + capture->frame.entry[i].start = capture->buffer_index; + capture->disabled = 0; + capture->stack_depth = 1; + + /* The trace stack[0] is reserved */ + memset(&capture->stack[0], 0, sizeof(capture->stack[0])); + /* Annotation index 0 is reserved to indicate no annotation */ + capture->stack[0].annotation_index = 1; + capture->annotation[0] = 0; + capture->annotation[1] = 0; + capture->annotation_count = 0; + capture->recording = true; + GTSC(capture->frame.entry[i].start_tsc); + g_xray_capture = capture; + + // initialize frame label + if(i < sizeof(capture->frame_labels)) { + capture->frame_labels[i][0] = 0; + } + +#ifndef XRAY_DISABLE_BROWSER_INTEGRATION + capture->frame.entry[i].start_time = XRayGenerateTimestampsNow(); +#endif +} + + +/* Ends a frame and disables capturing. Advances to the next frame. */ +/* Must be paired with XRayStartFrame(), and called from the same thread. */ +void XRayEndFrame(struct XRayTraceCapture* capture) { + int i; + assert(capture); + assert(capture->initialized); + assert(capture->recording); + assert(g_xray_capture == capture); + assert(0 == capture->disabled); + assert(1 == capture->stack_depth); + i = capture->frame.head; + GTSC(capture->frame.entry[i].end_tsc); + capture->frame.entry[i].total_ticks = + capture->frame.entry[i].end_tsc - capture->frame.entry[i].start_tsc; + capture->recording = NULL; + capture->frame.entry[i].end = capture->buffer_index; + capture->frame.entry[i].valid = true; + capture->frame.entry[i].annotation_count = capture->annotation_count; + capture->frame.head = XRayFrameGetNext(capture, capture->frame.head); + /* If the table is filled, bump the tail. */ + if (capture->frame.head == capture->frame.tail) + capture->frame.tail = XRayFrameGetNext(capture, capture->frame.tail); + capture->frame.tail = XRayFrameFindTail(capture); + /* Check that we didn't stomp over trace entry marker. */ + int marker = XRayTraceDecrementIndex(capture, capture->frame.entry[i].start); + struct XRayTraceBufferEntry* be = &capture->buffer[marker]; + if (be->depth_addr != XRAY_FRAME_MARKER) { + fprintf(stderr, + "XRay: XRayStopFrame() detects insufficient trace buffer size!\n"); + XRayReset(capture); + } else { + /* Replace marker with an empty annotation string. */ + be->depth_addr = XRAY_NULL_ANNOTATION; + XRayCheckGuards(capture); + } + g_xray_capture = NULL; + +#ifndef XRAY_DISABLE_BROWSER_INTEGRATION + capture->frame.entry[i].end_time = XRayGenerateTimestampsNow(); +#endif +} + + +/* Get the last frame captured. Do not call while capturing. */ +/* (ie call outside of XRayStartFrame() / XRayStopFrame() pair) */ +int XRayGetLastFrame(struct XRayTraceCapture* capture) { + assert(capture); + assert(capture->initialized); + assert(!capture->recording); + assert(0 == capture->disabled); + assert(1 == capture->stack_depth); + int last_frame = XRayFrameGetPrev(capture, capture->frame.head); + return last_frame; +} + + +/* Disables capturing until a paired XRayEnableCapture() is called */ +/* This call can be nested, but must be paired with an enable */ +/* (If you need to just exclude a specific function and not its */ +/* children, the XRAY_NO_INSTRUMENT modifier might be better) */ +/* Must be called from same thread as XRayBeginFrame() / XRayEndFrame() */ +void XRayDisableCapture(struct XRayTraceCapture* capture) { + assert(capture); + assert(capture == g_xray_capture); + assert(capture->initialized); + ++capture->disabled; + capture->recording = false; +} + + +/* Re-enables capture. Must be paired with XRayDisableCapture() */ +void XRayEnableCapture(struct XRayTraceCapture* capture) { + assert(capture); + assert(capture == g_xray_capture); + assert(capture->initialized); + assert(0 < capture->disabled); + --capture->disabled; + if (0 == capture->disabled) { + capture->recording = true; + } +} + + + +struct XRaySymbolTable* XRayGetSymbolTable(struct XRayTraceCapture* capture) { + return capture->symbols; +} + + +/* Initialize XRay */ +struct XRayTraceCapture* XRayInit(int stack_depth, + int buffer_size, + int frame_count, + const char* mapfilename) { + struct XRayTraceCapture* capture; + capture = (struct XRayTraceCapture*)XRayMalloc( + sizeof(struct XRayTraceCapture)); + int adj_frame_count = frame_count + 1; + size_t buffer_size_in_bytes = + sizeof(capture->buffer[0]) * buffer_size; + size_t frame_size_in_bytes = + sizeof(capture->frame.entry[0]) * adj_frame_count; + capture->buffer = + (struct XRayTraceBufferEntry *)XRayMalloc(buffer_size_in_bytes); + capture->frame.entry = + (struct XRayTraceFrameEntry *)XRayMalloc(frame_size_in_bytes); + capture->buffer_size = buffer_size; + capture->frame.count = adj_frame_count; + capture->frame.head = 0; + capture->frame.tail = 0; + capture->disabled = 0; + capture->annotation_filter = 0xFFFFFFFF; + capture->guard0 = XRAY_GUARD_VALUE_0x12345678; + capture->guard1 = XRAY_GUARD_VALUE_0x12345678; + capture->guard2 = XRAY_GUARD_VALUE_0x87654321; + capture->guard3 = XRAY_GUARD_VALUE_0x12345678; + capture->initialized = true; + capture->recording = false; + XRaySetMaxStackDepth(capture, stack_depth); + XRayReset(capture); + + /* Mapfile is optional; we don't need it for captures, only for reports. */ + capture->symbols = + XRaySymbolTableCreate(XRAY_DEFAULT_SYMBOL_TABLE_SIZE); + if (NULL != mapfilename) + XRaySymbolTableParseMapfile(capture->symbols, mapfilename); + +#ifndef XRAY_DISABLE_BROWSER_INTEGRATION + /* Use the address of a thread local variable as a fake thread id. */ + capture->thread_id = (int32_t)(&g_xray_thread_id_placeholder); +#endif + + return capture; +} + + +/* Shut down and free memory used by XRay. */ +void XRayShutdown(struct XRayTraceCapture* capture) { + assert(capture); + assert(capture->initialized); + assert(!capture->recording); + XRayCheckGuards(capture); + if (NULL != capture->symbols) { + XRaySymbolTableFree(capture->symbols); + } + XRayFree(capture->frame.entry); + XRayFree(capture->buffer); + capture->initialized = false; + XRayFree(capture); +} + +#endif /* XRAY */ diff --git a/hermit/usr/xray/xray.h b/hermit/usr/xray/xray.h new file mode 100644 index 000000000..6e0991f0c --- /dev/null +++ b/hermit/usr/xray/xray.h @@ -0,0 +1,125 @@ +/* Copyright (c) 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +/* XRay -- a simple profiler for Native Client */ + + +#ifndef LIBRARIES_XRAY_XRAY_H_ +#define LIBRARIES_XRAY_XRAY_H_ + +#include + +// we don't want that +#ifndef XRAY_DISABLE_BROWSER_INTEGRATION +#define XRAY_DISABLE_BROWSER_INTEGRATION +#endif + +#ifndef XRAY_DISABLE_BROWSER_INTEGRATION +#include "ppapi/c/ppb.h" +#endif + +#if defined(__arm__) +#undef XRAY +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define XRAY_NO_INSTRUMENT __attribute__((no_instrument_function)) +#define XRAY_INLINE __attribute__((always_inline, no_instrument_function)) + +#if defined(XRAY) + +/* Do not call __XRayAnnotate* directly; instead use the */ +/* XRayAnnotate() macros below. */ +XRAY_NO_INSTRUMENT void __XRayAnnotate(const char* str, ...) + __attribute__ ((format(printf, 1, 2))); +XRAY_NO_INSTRUMENT void __XRayAnnotateFiltered(const uint32_t filter, + const char* str, ...) __attribute__ ((format(printf, 2, 3))); + +/* This is the beginning of the public XRay API */ + +/* Ok if mapfilename is NULL, no symbols will be loaded. On glibc builds, + * XRay will also attempt to populate the symbol table with dladdr() + */ +XRAY_NO_INSTRUMENT struct XRayTraceCapture* XRayInit(int stack_size, + int buffer_size, + int frame_count, + const char* mapfilename); +XRAY_NO_INSTRUMENT void XRayShutdown(struct XRayTraceCapture* capture); +XRAY_NO_INSTRUMENT void XRayStartFrame(struct XRayTraceCapture* capture); +XRAY_NO_INSTRUMENT void XRayEndFrame(struct XRayTraceCapture* capture); +XRAY_NO_INSTRUMENT void XRayLabelFrame(const char* fmt, ...); +XRAY_NO_INSTRUMENT void XRaySetAnnotationFilter( + struct XRayTraceCapture* capture, uint32_t filter); +XRAY_NO_INSTRUMENT void XRaySaveReport(struct XRayTraceCapture* capture, + const char* filename, + float percent_cutoff, + int cycle_cutoff); +XRAY_NO_INSTRUMENT void XRayReport(struct XRayTraceCapture* capture, + FILE* f, + float percent_cutoff, + int ticks_cutoff); + +#ifndef XRAY_DISABLE_BROWSER_INTEGRATION +XRAY_NO_INSTRUMENT void XRayBrowserTraceReport( + struct XRayTraceCapture* capture); +XRAY_NO_INSTRUMENT void XRayRegisterBrowserInterface( + PPB_GetInterface get_browser_interface); +#endif /* XRAY_DISABLE_BROWSER_INTEGRATION */ + + +#if defined(XRAY_ANNOTATE) +#define XRayAnnotate(...) __XRayAnnotate(__VA_ARGS__) +#define XRayAnnotateFiltered(...) __XRayAnnotateFiltered(__VA_ARGS__) +#else +#define XRayAnnotate(...) +#define XRayAnnotateFiltered(...) +#endif +/* This is the end of the public XRay API */ + +#else /* defined(XRAY) */ + +/* Builds that don't define XRAY will use these 'null' functions instead. */ + +#define XRayAnnotate(...) +#define XRayAnnotateFiltered(...) + +inline struct XRayTraceCapture* XRayInit(int stack_size, + int buffer_size, + int frame_count, + const char* mapfilename) { + return NULL; +} +inline void XRayShutdown(struct XRayTraceCapture* capture) {} +inline void XRayStartFrame(struct XRayTraceCapture* capture) {} +inline void XRayEndFrame(struct XRayTraceCapture* capture) {} +inline void XRayLabelFrame(const char* fmt, ...) {} + +inline void XRaySetAnnotationFilter(struct XRayTraceCapture* capture, + uint32_t filter) {} +inline void XRaySaveReport(struct XRayTraceCapture* capture, + const char* filename, + float percent_cutoff, + int cycle_cutoff) {} +inline void XRayReport(struct XRayTraceCapture* capture, + FILE* f, + float percent_cutoff, + int ticks_cutoff) {} + +#ifndef XRAY_DISABLE_BROWSER_INTEGRATION +inline void XRayBrowserTraceReport(struct XRayTraceCapture* capture) {} +inline void XRayRegisterBrowserInterface( + PPB_GetInterface get_browser_interface) {} +#endif /* XRAY_DISABLE_BROWSER_INTEGRATION */ + + +#endif /* defined(XRAY) */ + +#ifdef __cplusplus +} +#endif + +#endif /* LIBRARIES_XRAY_XRAY_H_ */ diff --git a/hermit/usr/xray/xray.odt b/hermit/usr/xray/xray.odt new file mode 100644 index 000000000..a7b1deee2 Binary files /dev/null and b/hermit/usr/xray/xray.odt differ diff --git a/hermit/usr/xray/xray_priv.h b/hermit/usr/xray/xray_priv.h new file mode 100644 index 000000000..8d2829e43 --- /dev/null +++ b/hermit/usr/xray/xray_priv.h @@ -0,0 +1,210 @@ +/* Copyright (c) 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +/* XRay -- a simple profiler for Native Client */ + +/* This header file is the private internal interface. */ + +#ifndef LIBRARIES_XRAY_XRAY_PRIV_H_ +#define LIBRARIES_XRAY_XRAY_PRIV_H_ + +#include +#include +#include +#include +#include "xray.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(XRAY) + +#define XRAY_FORCE_INLINE __attribute__((always_inline, no_instrument_function)) + +#define XRAY_TRACE_STACK_SIZE (256) +#define XRAY_TRACE_ANNOTATION_LENGTH (2048) +#define XRAY_TRACE_BUFFER_SIZE (1048576) +#define XRAY_ANNOTATION_STACK_SIZE ((XRAY_TRACE_STACK_SIZE) * \ + (XRAY_TRACE_ANNOTATION_LENGTH)) +#define XRAY_STRING_POOL_NODE_SIZE (32768) +#define XRAY_FRAME_MARKER (0xFFFFFFFF) +#define XRAY_NULL_ANNOTATION (0x0) +#define XRAY_FUNCTION_ALIGNMENT_BITS (4) +#define XRAY_ADDR_MASK (0xFFFFFF00) +#define XRAY_ADDR_SHIFT (4) +#define XRAY_DEPTH_MASK (0x000000FF) +#define XRAY_SYMBOL_TABLE_MAX_RATIO (0.66f) +#define XRAY_LINE_SIZE (1024) +#define XRAY_MAX_FRAMES (60) +#define XRAY_MAX_LABEL (32) +#define XRAY_DEFAULT_SYMBOL_TABLE_SIZE (4096) +#define XRAY_SYMBOL_POOL_NODE_SIZE (1024) +#define XRAY_GUARD_VALUE_0x12345678 (0x12345678) +#define XRAY_GUARD_VALUE_0x87654321 (0x87654321) +#define XRAY_EXTRACT_ADDR(x) (((x) & XRAY_ADDR_MASK) >> XRAY_ADDR_SHIFT) +#define XRAY_EXTRACT_DEPTH(x) ((x) & XRAY_DEPTH_MASK) +#define XRAY_PACK_ADDR(x) (((x) << XRAY_ADDR_SHIFT) & XRAY_ADDR_MASK) +#define XRAY_PACK_DEPTH(x) ((x) & XRAY_DEPTH_MASK) +#define XRAY_PACK_DEPTH_ADDR(d, a) (XRAY_PACK_DEPTH(d) | XRAY_PACK_ADDR(a)) +#define XRAY_ALIGN64 __attribute((aligned(64))) + +struct XRayStringPool; +struct XRayHashTable; +struct XRaySymbolPool; +struct XRaySymbol; +struct XRaySymbolTable; +struct XRayTraceCapture; + +struct XRayTraceBufferEntry { + uint32_t depth_addr; + uint32_t annotation_index; + uint64_t start_tick; + uint64_t end_tick; +}; + + +/* Important: don't instrument xray itself, so use */ +/* XRAY_NO_INSTRUMENT on all xray functions */ + +XRAY_NO_INSTRUMENT char* XRayStringPoolAppend(struct XRayStringPool* pool, + const char* src); +XRAY_NO_INSTRUMENT struct XRayStringPool* XRayStringPoolCreate(); +XRAY_NO_INSTRUMENT void XRayStringPoolFree(struct XRayStringPool* pool); + +XRAY_NO_INSTRUMENT void* XRayHashTableLookup(struct XRayHashTable* table, + uint32_t addr); +XRAY_NO_INSTRUMENT void* XRayHashTableInsert(struct XRayHashTable* table, + void* data, uint32_t addr); +XRAY_NO_INSTRUMENT void* XRayHashTableAtIndex( + struct XRayHashTable* table, int i); +XRAY_NO_INSTRUMENT int XRayHashTableGetCapacity(struct XRayHashTable* table); +XRAY_NO_INSTRUMENT int XRayHashTableGetCount(struct XRayHashTable* table); +XRAY_NO_INSTRUMENT struct XRayHashTable* XRayHashTableCreate(int capacity); +XRAY_NO_INSTRUMENT void XRayHashTableFree(struct XRayHashTable* table); +XRAY_NO_INSTRUMENT void XRayHashTableHisto(FILE* f); + +XRAY_NO_INSTRUMENT struct XRaySymbol* XRaySymbolPoolAlloc( + struct XRaySymbolPool* sympool); +XRAY_NO_INSTRUMENT struct XRaySymbolPool* XRaySymbolPoolCreate(); +XRAY_NO_INSTRUMENT void XRaySymbolPoolFree(struct XRaySymbolPool* sympool); + +XRAY_NO_INSTRUMENT const char* XRayDemangle(char* demangle, size_t buffersize, + const char* symbol); + +XRAY_NO_INSTRUMENT const char* XRaySymbolGetName(struct XRaySymbol* symbol); +XRAY_NO_INSTRUMENT struct XRaySymbol* XRaySymbolCreate( + struct XRaySymbolPool* sympool, const char* name); +XRAY_NO_INSTRUMENT void XRaySymbolFree(struct XRaySymbol* symbol); +XRAY_NO_INSTRUMENT int XRaySymbolCount(struct XRaySymbolTable* symtab); + +XRAY_NO_INSTRUMENT struct XRaySymbol* XRaySymbolTableCreateEntry( + struct XRaySymbolTable* symtab, char* line); +XRAY_NO_INSTRUMENT void XRaySymbolTableParseMapfile( + struct XRaySymbolTable* symbols, const char* mapfilename); + +XRAY_NO_INSTRUMENT struct XRaySymbol* XRaySymbolTableAddByName( + struct XRaySymbolTable* symtab, const char* name, uint32_t addr); + +XRAY_NO_INSTRUMENT int XRaySymbolTableGetCount(struct XRaySymbolTable* symtab); +XRAY_NO_INSTRUMENT struct XRaySymbol* XRaySymbolTableLookup( + struct XRaySymbolTable* symbols, uint32_t addr); +XRAY_NO_INSTRUMENT struct XRaySymbol* XRaySymbolTableAtIndex( + struct XRaySymbolTable* symbols, int i); +XRAY_NO_INSTRUMENT struct XRaySymbolTable* XRaySymbolTableCreate(int size); +XRAY_NO_INSTRUMENT void XRaySymbolTableFree(struct XRaySymbolTable* symbtab); + +XRAY_NO_INSTRUMENT struct XRaySymbolTable* XRayGetSymbolTable( + struct XRayTraceCapture* capture); + +XRAY_NO_INSTRUMENT void XRayCheckGuards(struct XRayTraceCapture* capture); + +XRAY_NO_INSTRUMENT struct XRayTraceBufferEntry* XRayTraceGetEntry( + struct XRayTraceCapture* capture, int index); +XRAY_NO_INSTRUMENT int XRayTraceIncrementIndex( + struct XRayTraceCapture* capture, int i); +XRAY_NO_INSTRUMENT int XRayTraceDecrementIndex( + struct XRayTraceCapture* capture, int i); +XRAY_NO_INSTRUMENT bool XRayTraceIsAnnotation( + struct XRayTraceCapture* capture, int index); +XRAY_NO_INSTRUMENT void XRayTraceAppendString( + struct XRayTraceCapture* capture, char* src); +XRAY_NO_INSTRUMENT int XRayTraceCopyToString( + struct XRayTraceCapture* capture, int index, char* dst); +XRAY_NO_INSTRUMENT int XRayTraceSkipAnnotation( + struct XRayTraceCapture* capture, int index); +XRAY_NO_INSTRUMENT int XRayTraceNextEntry( + struct XRayTraceCapture* capture, int index); + +XRAY_NO_INSTRUMENT void XRayFrameMakeLabel(struct XRayTraceCapture* capture, + int counter, + char* label); +XRAY_NO_INSTRUMENT int XRayFrameFindTail(struct XRayTraceCapture* capture); + +XRAY_NO_INSTRUMENT int XRayFrameGetCount(struct XRayTraceCapture* capture); +XRAY_NO_INSTRUMENT int XRayFrameGetHead(struct XRayTraceCapture* capture); +XRAY_NO_INSTRUMENT int XRayFrameGetTail(struct XRayTraceCapture* capture); +XRAY_NO_INSTRUMENT int XRayFrameGetNext( + struct XRayTraceCapture* capture, int index); +XRAY_NO_INSTRUMENT uint64_t XRayFrameGetTotalTicks( + struct XRayTraceCapture* capture, int frame); +XRAY_NO_INSTRUMENT int XRayFrameGetTraceCount( + struct XRayTraceCapture* capture, int frame); +XRAY_NO_INSTRUMENT int XRayFrameGetTraceStartIndex( + struct XRayTraceCapture* capture, int frame); +XRAY_NO_INSTRUMENT int XRayFrameGetTraceEndIndex( + struct XRayTraceCapture* capture, int frame); +XRAY_NO_INSTRUMENT int XRayFrameGetAnnotationCount( + struct XRayTraceCapture* capture, int frame); +XRAY_NO_INSTRUMENT bool XRayFrameIsValid( + struct XRayTraceCapture* capture, int frame); + + +XRAY_NO_INSTRUMENT void XRayTraceReport(struct XRayTraceCapture* capture, + FILE* f, + int frame, + char* label, + float percent_cutoff, + int ticks_cutoff); +XRAY_NO_INSTRUMENT void XRayFrameReport(struct XRayTraceCapture* capture, + FILE* f); + +XRAY_NO_INSTRUMENT void* XRayMalloc(size_t t); +XRAY_NO_INSTRUMENT void XRayFree(void* data); + +XRAY_NO_INSTRUMENT void XRaySetMaxStackDepth( + struct XRayTraceCapture* capture, int stack_depth); +XRAY_NO_INSTRUMENT int XRayGetLastFrame(struct XRayTraceCapture* capture); +XRAY_NO_INSTRUMENT void XRayDisableCapture(struct XRayTraceCapture* capture); +XRAY_NO_INSTRUMENT void XRayEnableCapture(struct XRayTraceCapture* capture); +XRAY_NO_INSTRUMENT void XRayLoadMapfile( + struct XRayTraceCapture* capture, const char* mapfilename); + +struct XRayTimestampPair { + uint64_t xray; /* internal xray timestamp */ + int64_t pepper; /* corresponding timestamp from PPAPI interface */ +}; + +#ifndef XRAY_DISABLE_BROWSER_INTEGRATION +XRAY_NO_INSTRUMENT void XRayGetTSC(uint64_t* tsc); +XRAY_NO_INSTRUMENT int32_t XRayGetSavedThreadID( + struct XRayTraceCapture* capture); +XRAY_NO_INSTRUMENT struct XRayTimestampPair XRayFrameGetStartTimestampPair( + struct XRayTraceCapture* capture, int frame); +XRAY_NO_INSTRUMENT struct XRayTimestampPair XRayFrameGetEndTimestampPair( + struct XRayTraceCapture* capture, int frame); +XRAY_NO_INSTRUMENT struct XRayTimestampPair XRayGenerateTimestampsNow(void); +#endif + +#ifndef XRAY_FRAME_LBL_BUFSIZE +#define XRAY_FRAME_LBL_BUFSIZE 16 +#endif + +#endif /* defined(XRAY) */ + +#ifdef __cplusplus +} +#endif + +#endif /* LIBRARIES_XRAY_XRAY_PRIV_H_ */