summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Rowand <frank.rowand@am.sony.com>2012-08-13 13:38:25 -0700
committerJohn Kacur <jkacur@redhat.com>2012-10-17 00:25:26 +0200
commit9854a61da92d80ccce74e091ddc9d4c0e3983e79 (patch)
tree2bda419ed279e176d4edee9e59274dcbaf43049c
parentfcdef80f5f3910f2a9a8f6fcc7045bd068a9bce5 (diff)
downloadrt-tests-9854a61da92d80ccce74e091ddc9d4c0e3983e79.tar.gz
V3: cyclictest: report large measured clock latency
V3: Use src/lib/error.c functions instead of fprintf. Fix printf format warnings for 32 bit vs 64 bit systems with cast. One issue with using warn() and info() instead of fprintf is that the compiler no longer warns about format mismatches. Fix bad continuation line white space prefix. Remove unused variable zero_diff. cyclictest: ARM panda clock resolution will be ~30 usec unless CONFIG_OMAP_32K_TIMER=n, resulting in a poor latency report. This patch does _not_ fix the problem, it merely provides the instrumentation to make it visible. The value of measured resolution is useful information for any system. Signed-off-by: Frank Rowand <frank.rowand@am.sony.com> - Fixed up minor white space problem. Signed-off-by: John Kacur <jkacur@redhat.com>
-rw-r--r--src/cyclictest/cyclictest.c109
1 files changed, 108 insertions, 1 deletions
diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c
index e53e1ce..807041d 100644
--- a/src/cyclictest/cyclictest.c
+++ b/src/cyclictest/cyclictest.c
@@ -176,6 +176,8 @@ static int use_nsecs = 0;
static int refresh_on_max;
static int force_sched_other;
static int priospread = 0;
+static int check_clock_resolution;
+static int ct_debug;
static pthread_cond_t refresh_on_max_cond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t refresh_on_max_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -949,6 +951,9 @@ static void display_help(int error)
"-q --quiet print only a summary on exit\n"
"-Q --priospread spread priority levels starting at specified value\n"
"-r --relative use relative timer instead of absolute\n"
+ "-R --resolution check clock resolution, calling clock_gettime() many\n"
+ " times. list of clock_gettime() values will be\n"
+ " reported with -X\n"
"-s --system use sys_nanosleep and sys_setitimer\n"
"-S --smp Standard SMP testing: options -a -t -n and\n"
" same priority of all threads\n"
@@ -965,6 +970,7 @@ static void display_help(int error)
" format: n:c:v n=tasknum c=count v=value in us\n"
"-w --wakeup task wakeup tracing (used with -b)\n"
"-W --wakeuprt rt task wakeup tracing (used with -b)\n"
+ "-X --dbg_cyclictest print info useful for debugging cyclictest\n"
"-y POLI --policy=POLI policy of realtime thread, POLI may be fifo(default) or rr\n"
" format: --policy=fifo(default) or --policy=rr\n",
tracers
@@ -1081,6 +1087,7 @@ static void process_options (int argc, char *argv[])
{"quiet", no_argument, NULL, 'q'},
{"priospread", no_argument, NULL, 'Q'},
{"relative", no_argument, NULL, 'r'},
+ {"resolution", no_argument, NULL, 'R'},
{"system", no_argument, NULL, 's'},
{"smp", no_argument, NULL, 'S'},
{"threads", optional_argument, NULL, 't'},
@@ -1090,11 +1097,12 @@ static void process_options (int argc, char *argv[])
{"verbose", no_argument, NULL, 'v'},
{"wakeup", no_argument, NULL, 'w'},
{"wakeuprt", no_argument, NULL, 'W'},
+ {"dbg_cyclictest", no_argument, NULL, 'X'},
{"policy", required_argument, NULL, 'y'},
{"help", no_argument, NULL, '?'},
{NULL, 0, NULL, 0}
};
- int c = getopt_long(argc, argv, "a::b:Bc:Cd:D:e:Efh:H:i:Il:MnNo:O:p:PmqQrsSt::uUvD:wWT:y:",
+ int c = getopt_long(argc, argv, "a::b:Bc:Cd:D:e:Efh:H:i:Il:MnNo:O:p:PmqQrRsSt::uUvD:wWXT:y:",
long_options, &option_index);
if (c == -1)
break;
@@ -1163,6 +1171,7 @@ static void process_options (int argc, char *argv[])
case 'q': quiet = 1; break;
case 'Q': priospread = 1; break;
case 'r': timermode = TIMER_RELTIME; break;
+ case 'R': check_clock_resolution = 1; break;
case 's': use_system = MODE_SYS_OFFSET; break;
case 'S': /* SMP testing */
if (numa)
@@ -1207,6 +1216,7 @@ static void process_options (int argc, char *argv[])
case 'v': verbose = 1; break;
case 'w': tracetype = WAKEUP; break;
case 'W': tracetype = WAKEUPRT; break;
+ case 'X': ct_debug = 1; break;
case 'y': handlepolicy(optarg); break;
case '?': display_help(0); break;
@@ -1499,6 +1509,103 @@ int main(int argc, char **argv)
if (check_timer())
warn("High resolution timers not available\n");
+ if (check_clock_resolution) {
+ int clock;
+ uint64_t diff;
+ int k;
+ uint64_t min_non_zero_diff = UINT64_MAX;
+ struct timespec now;
+ struct timespec prev;
+ uint64_t reported_resolution = UINT64_MAX;
+ struct timespec res;
+ struct timespec *time;
+ int times;
+
+ clock = clocksources[clocksel];
+
+ if (clock_getres(clock, &res)) {
+ warn("clock_getres failed");
+ } else {
+ reported_resolution = (NSEC_PER_SEC * res.tv_sec) + res.tv_nsec;
+ }
+
+
+ /*
+ * Calculate how many calls to clock_gettime are needed.
+ * Then call it that many times.
+ * Goal is to collect timestamps for ~ 0.001 sec.
+ * This will reliably capture resolution <= 500 usec.
+ */
+ times = 1000;
+ clock_gettime(clock, &prev);
+ for (k=0; k < times; k++) {
+ clock_gettime(clock, &now);
+ }
+
+ diff = calcdiff_ns(now, prev);
+ if (diff == 0) {
+ /*
+ * No clock rollover occurred.
+ * Use the default value for times.
+ */
+ times = -1;
+ } else {
+ int call_time;
+ call_time = diff / times; /* duration 1 call */
+ times = NSEC_PER_SEC / call_time; /* calls per second */
+ times /= 1000; /* calls per msec */
+ if (times < 1000)
+ times = 1000;
+ }
+ /* sanity check */
+ if ((times <= 0) || (times > 100000))
+ times = 100000;
+
+ time = calloc(times, sizeof(*time));
+
+ for (k=0; k < times; k++) {
+ clock_gettime(clock, &time[k]);
+ }
+
+ if (ct_debug) {
+ info("For %d consecutive calls to clock_gettime():\n", times);
+ info("time, delta time (nsec)\n");
+ }
+
+ prev = time[0];
+ for (k=1; k < times; k++) {
+
+ diff = calcdiff_ns(time[k], prev);
+ prev = time[k];
+
+ if (diff && (diff < min_non_zero_diff)) {
+ min_non_zero_diff = diff;
+ }
+
+ if (ct_debug)
+ info("%ld.%06ld %5llu\n",
+ time[k].tv_sec, time[k].tv_nsec,
+ (unsigned long long)diff);
+ }
+
+ free(time);
+
+
+ if (verbose ||
+ (min_non_zero_diff && (min_non_zero_diff > reported_resolution))) {
+ /*
+ * Measured clock resolution includes the time to call
+ * clock_gettime(), so it will be slightly larger than
+ * actual resolution.
+ */
+ warn("reported clock resolution: %llu nsec\n",
+ (unsigned long long)reported_resolution);
+ warn("measured clock resolution approximately: %llu nsec\n",
+ (unsigned long long)min_non_zero_diff);
+ }
+
+ }
+
mode = use_nanosleep + use_system;
sigemptyset(&sigset);