From 3c9057f3816867fcf94bec3e264c2b7b0873fd29 Mon Sep 17 00:00:00 2001 From: Stan Shebs Date: Mon, 19 Sep 2011 16:55:26 +0000 Subject: [PATCH] * gdb.trace/tspeed.exp: New file. * gdb.trace/tspeed.c: New file. --- gdb/testsuite/ChangeLog | 5 + gdb/testsuite/gdb.trace/tspeed.c | 184 +++++++++++++++++++++++++++++ gdb/testsuite/gdb.trace/tspeed.exp | 140 ++++++++++++++++++++++ 3 files changed, 329 insertions(+) create mode 100644 gdb/testsuite/gdb.trace/tspeed.c create mode 100644 gdb/testsuite/gdb.trace/tspeed.exp diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 477907dbc0a..38e692cc458 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-09-19 Stan Shebs + + * gdb.trace/tspeed.exp: New file. + * gdb.trace/tspeed.c: New file. + 2011-09-18 Yao Qi * gdb.arch/arm-disp-step.S (test_ldr_literal): Test for Thumb diff --git a/gdb/testsuite/gdb.trace/tspeed.c b/gdb/testsuite/gdb.trace/tspeed.c new file mode 100644 index 00000000000..cf698f9cb9e --- /dev/null +++ b/gdb/testsuite/gdb.trace/tspeed.c @@ -0,0 +1,184 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2010, 2011 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* This program tests tracepoint speed. It consists of two identical + loops, which in normal execution will run for exactly the same + amount of time. A tracepoint in the second loop will slow it down + by some amount, and then the program will report the slowdown + observed. */ + +/* While primarily designed for the testsuite, it can also be used + for interactive testing. */ + +#include +#include +#include +#include + +int trace_speed_test (void); + +/* We mark these globals as volatile so the speed-measuring loops + don't get totally emptied out at high optimization levels. */ + +volatile int globfoo, globfoo2, globfoo3; + +volatile short globarr[80000]; + +int init_iters = 10 * 1000; + +int iters; + +int max_iters = 1000 * 1000 * 1000; + +int numtps = 1; + +unsigned long long now2, now3, now4, now5; +int total1, total2, idelta, mindelta, nsdelta; +int nspertp = 0; + +/* Return CPU usage (both user and system - trap-based tracepoints use + a bunch of system time). */ + +unsigned long long +myclock () +{ + struct timeval tm, tm2; + struct rusage ru; + getrusage (RUSAGE_SELF, &ru); + tm = ru.ru_utime; + tm2 = ru.ru_stime; + return (((unsigned long long) tm.tv_sec) * 1000000) + tm.tv_usec + + (((unsigned long long) tm2.tv_sec) * 1000000) + tm2.tv_usec; +} + +int +main(int argc, char **argv) +{ + int problem; + + iters = init_iters; + + while (1) + { + numtps = 1; /* set pre-run breakpoint here */ + + /* Keep trying the speed test, with more iterations, until + we get to a reasonable number. */ + while (problem = trace_speed_test()) + { + /* If iteration isn't working, give up. */ + if (iters > max_iters) + { + printf ("Gone over %d iterations, giving up\n", max_iters); + break; + } + if (problem < 0) + { + printf ("Negative times, giving up\n", max_iters); + break; + } + + iters *= 2; + printf ("Doubled iterations to %d\n", iters); + } + + printf ("Tracepoint time is %d ns\n", nspertp); + + /* This is for the benefit of interactive testing and attaching, + keeps the program from pegging the machine. */ + sleep (1); /* set post-run breakpoint here */ + + /* Issue a little bit of output periodically, so we can see if + program is alive or hung. */ + printf ("%s keeping busy, clock=%llu\n", argv[0], myclock ()); + } + return 0; +} + +int +trace_speed_test (void) +{ + int i; + + /* Overall loop run time deltas under 1 ms are likely noise and + should be ignored. */ + mindelta = 1000; + + // The bodies of the two loops following must be identical. + + now2 = myclock (); + globfoo2 = 1; + for (i = 0; i < iters; ++i) + { + globfoo2 *= 45; + globfoo2 += globfoo + globfoo3; + globfoo2 *= globfoo + globfoo3; + globfoo2 -= globarr[4] + globfoo3; + globfoo2 *= globfoo + globfoo3; + globfoo2 += globfoo + globfoo3; + } + now3 = myclock (); + total1 = now3 - now2; + + now4 = myclock (); + globfoo2 = 1; + for (i = 0; i < iters; ++i) + { + globfoo2 *= 45; + globfoo2 += globfoo + globfoo3; /* set tracepoint here */ + globfoo2 *= globfoo + globfoo3; + globfoo2 -= globarr[4] + globfoo3; + globfoo2 *= globfoo + globfoo3; + globfoo2 += globfoo + globfoo3; + } + now5 = myclock (); + total2 = now5 - now4; + + /* Report on the test results. */ + + nspertp = 0; + + idelta = total2 - total1; + + printf ("Loops took %d usec and %d usec, delta is %d usec, %d iterations\n", + total1, total2, idelta, iters); + + /* If the second loop seems to run faster, things are weird so give up. */ + if (idelta < 0) + return -1; + + if (idelta > mindelta + /* Total test time should be between 2 and 5 seconds. */ + && (total1 + total2) > (2 * 1000000) + && (total1 + total2) < (5 * 1000000)) + { + nsdelta = (((unsigned long long) idelta) * 1000) / iters; + printf ("Second loop took %d ns longer per iter than first\n", nsdelta); + nspertp = nsdelta / numtps; + printf ("%d ns per tracepoint\n", nspertp); + printf ("Base iteration time %d ns\n", + ((int) (((unsigned long long) total1) * 1000) / iters)); + printf ("Total test time %d secs\n", ((int) ((now5 - now2) / 1000000))); + + /* Speed test ran with no problem. */ + return 0; + } + + /* The test run was too brief, or otherwise not useful. */ + return 1; +} diff --git a/gdb/testsuite/gdb.trace/tspeed.exp b/gdb/testsuite/gdb.trace/tspeed.exp new file mode 100644 index 00000000000..9f51a478d06 --- /dev/null +++ b/gdb/testsuite/gdb.trace/tspeed.exp @@ -0,0 +1,140 @@ +# Copyright 2011 +# Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +load_lib "trace-support.exp" + +set testfile "tspeed" +set srcfile ${testfile}.c +set executable $testfile +set binfile $objdir/$subdir/$executable + +set ipalib $objdir/../gdbserver/libinproctrace.so + +if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \ + executable [concat {debug nowarnings c} libs=$ipalib]] != "" } { + untested tspeed.exp + return -1 +} + +# Typically we need a little extra time for this test. +set timeout 180 + +set ws "\[\r\n\t \]+" +set cr "\[\r\n\]+" + +# +# Utility procs +# + +proc prepare_for_trace_test {} { + global executable + + clean_restart $executable + + runto_main + + set testline [gdb_get_line_number "set pre-run breakpoint here"] + + gdb_test "break $testline" ".*" "" + + set testline [gdb_get_line_number "set post-run breakpoint here"] + + gdb_test "break $testline" ".*" "" +} + +proc run_trace_experiment {} { + + gdb_test "continue" \ + ".*Breakpoint \[0-9\]+, main .*" \ + "advance to trace begin" + + gdb_test_no_output "tstart" "start trace experiment" + + gdb_test "continue" \ + ".*Breakpoint \[0-9\]+, main .*" \ + "advance through tracing" + + gdb_test "tstatus" ".*Trace .*" "check on trace status" + + gdb_test "tstop" "" "" +} + +proc gdb_slow_trace_speed_test { } { + + gdb_delete_tracepoints + + gdb_test "print iters = init_iters" ".* = .*"; + + set testline [gdb_get_line_number "set tracepoint here"] + + gdb_test "trace $testline if (globfoo != 12 && globfoo2 == 45)" \ + "Tracepoint \[0-9\]+ at .*" \ + "set slow tracepoint" + + # Begin the test. + run_trace_experiment +} + +proc gdb_fast_trace_speed_test { } { + + gdb_delete_tracepoints + + gdb_test "print iters = init_iters" ".* = .*"; + + set run_ftrace 0 + + set testline [gdb_get_line_number "set tracepoint here"] + + gdb_test_multiple "ftrace $testline if (globfoo != 12 && globfoo2 == 45)" \ + "set conditional fast tracepoint" { + -re "Fast tracepoint \[0-9\]+ at .*" { + pass "set conditional fast tracepoint, done" + set run_ftrace 1 + } + -re "May not have a fast tracepoint at .*" { + pass "set conditional fast tracepoint, not allowed at line" + } + } + + # If the fast tracepoint couldn't be set, don't bother with the run. + if { $run_ftrace == 1 } then { + + # Begin the test. + run_trace_experiment + } +} + +proc gdb_trace_collection_test {} { + + prepare_for_trace_test + + gdb_slow_trace_speed_test + + gdb_fast_trace_speed_test +} + +clean_restart $executable +runto_main + +# We generously give ourselves one "pass" if we successfully +# detect that this test cannot be run on this target! +if { ![gdb_target_supports_trace] } then { + pass "Current target does not support trace" + return 1; +} + +# Body of test encased in a proc so we can return prematurely. +gdb_trace_collection_test -- 2.30.2