From 2c08e36088f5b79e1e1998ef59257e5986face0a Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Mon, 13 Jul 2015 19:26:36 -0700 Subject: [PATCH] ipiq: Add simple IPI latency measure sysctls (2) * Add /usr/src/test/sysperf/ipitest test script. * Make adjustments to the sysctl latency code, remove unnecessary critical section and convert the result to nanoseconds. --- sys/kern/lwkt_ipiq.c | 48 +++++++++++++++++++++++++++++--------------- test/sysperf/ipitest | 48 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 16 deletions(-) create mode 100755 test/sysperf/ipitest diff --git a/sys/kern/lwkt_ipiq.c b/sys/kern/lwkt_ipiq.c index b4c341a4be..826dfdfcb0 100644 --- a/sys/kern/lwkt_ipiq.c +++ b/sys/kern/lwkt_ipiq.c @@ -64,6 +64,7 @@ #include #include +#include #include #ifdef _KERNEL_VIRTUAL @@ -1029,43 +1030,58 @@ lwkt_cpusync_remote2(lwkt_cpusync_t cs) } } -#define LWKT_IPIQ_NLATENCY 7 +#define LWKT_IPIQ_NLATENCY 8 +#define LWKT_IPIQ_NLATENCY_MASK (LWKT_IPIQ_NLATENCY - 1) struct lwkt_ipiq_latency_log { - int idx; + int idx; /* unmasked index */ int pad; uint64_t latency[LWKT_IPIQ_NLATENCY]; }; static struct lwkt_ipiq_latency_log lwkt_ipiq_latency_logs[MAXCPU]; +static uint64_t save_tsc; +/* + * IPI callback (already in a critical section) + */ static void -lwkt_ipiq_latency_testfunc(void *arg) +lwkt_ipiq_latency_testfunc(void *arg __unused) { - uint64_t prev_tsc = (uintptr_t)arg; - uint64_t tsc; - struct globaldata *gd = mycpu; + uint64_t delta_tsc; + struct globaldata *gd; struct lwkt_ipiq_latency_log *lat; - lat = &lwkt_ipiq_latency_logs[gd->gd_cpuid]; + /* + * Get delta TSC (assume TSCs are synchronized) as quickly as + * possible and then convert to nanoseconds. + */ + delta_tsc = rdtsc_ordered() - save_tsc; + delta_tsc = delta_tsc * 1000000000LU / tsc_frequency; - crit_enter_gd(gd); - tsc = rdtsc_ordered(); - lat->latency[lat->idx++] = tsc - prev_tsc; - if (lat->idx >= LWKT_IPIQ_NLATENCY) - lat->idx = 0; - crit_exit_gd(gd); + /* + * Record in our save array. + */ + gd = mycpu; + lat = &lwkt_ipiq_latency_logs[gd->gd_cpuid]; + lat->latency[lat->idx & LWKT_IPIQ_NLATENCY_MASK] = delta_tsc; + ++lat->idx; } /* * Send IPI from cpu0 to other cpus + * + * NOTE: Machine must be idle for test to run dependably, and also probably + * a good idea not to be running powerd. + * + * NOTE: Caller should use 'usched :1 ' to lock itself to cpu 0. + * See 'ipitest' script in /usr/src/test/sysperf/ipitest */ static int lwkt_ipiq_latency_test(SYSCTL_HANDLER_ARGS) { struct globaldata *gd; int cpu = 0, orig_cpu, error; - uint64_t tsc; error = sysctl_handle_int(oidp, &cpu, arg2, req); if (error || req->newptr == NULL) @@ -1081,8 +1097,8 @@ lwkt_ipiq_latency_test(SYSCTL_HANDLER_ARGS) gd = globaldata_find(cpu); - tsc = rdtsc_ordered(); - lwkt_send_ipiq(gd, lwkt_ipiq_latency_testfunc, (void *)(uintptr_t)tsc); + save_tsc = rdtsc_ordered(); + lwkt_send_ipiq(gd, lwkt_ipiq_latency_testfunc, NULL); lwkt_migratecpu(orig_cpu); return 0; diff --git a/test/sysperf/ipitest b/test/sysperf/ipitest new file mode 100755 index 0000000000..9bd7bdfb24 --- /dev/null +++ b/test/sysperf/ipitest @@ -0,0 +1,48 @@ +#!/bin/csh +# +# ipitest [ Cmode ] +# +# NOTE: Run from current directory as ./ipitest, output in ipitest.out +# +# NOTE: Running powerd during this test is not recommended. + +# Force test to run from cpu 0 +# +if ( $?DIDUSCHED == 0 ) then + setenv DIDUSCHED ok + usched :1 ./ipitest $argv + exit 0 +endif + +# CX mode can be specified on the command line, if not +# specified test all available CX modes. +# +if ( $#argv == 0 ) then + set modes = "`sysctl -n machdep.mwait.CX.supported`" +else + set modes = "$argv" +endif + +# Start test. Use a sleep to give other cpus time to go +# idle. Try to avoid being on a hardclock boundary. +# +set file = "ipitest.out" +echo "Testing $modes" + +fgrep CPU /var/run/dmesg.boot | fgrep @ | head -1 > ${file} +date >> ${file} + +foreach mode ( $modes ) + echo "Testing mode $mode" + sysctl machdep.mwait.CX.idle=$mode + foreach i ( 1 2 3 ) + foreach j ( x x x x x x x x x ) + sleep 0.200010 + sysctl debug.ipiq.latency_test=$i >& /dev/null + end + end + sleep 0.2 + echo "Testing mode $mode" >> ${file} + sysctl debug.ipiq >> ${file} + echo "" +end -- 2.41.0