#include #include #include #include #define CREATE_TRACE_POINTS #include "trace_benchmark.h" static struct task_struct *bm_event_thread; static char bm_str[BENCHMARK_EVENT_STRLEN] = "START"; static u64 bm_total; static u64 bm_totalsq; static u64 bm_last; static u64 bm_max; static u64 bm_min; static u64 bm_first; static u64 bm_cnt; static u64 bm_stddev; static unsigned int bm_avg; static unsigned int bm_std; static bool ok_to_run; /* * This gets called in a loop recording the time it took to write * the tracepoint. What it writes is the time statistics of the last * tracepoint write. As there is nothing to write the first time * it simply writes "START". As the first write is cold cache and * the rest is hot, we save off that time in bm_first and it is * reported as "first", which is shown in the second write to the * tracepoint. The "first" field is writen within the statics from * then on but never changes. */ static void trace_do_benchmark(void) { u64 start; u64 stop; u64 delta; u64 stddev; u64 seed; u64 last_seed; unsigned int avg; unsigned int std = 0; /* Only run if the tracepoint is actually active */ if (!trace_benchmark_event_enabled() || !tracing_is_on()) return; local_irq_disable(); start = trace_clock_local(); trace_benchmark_event(bm_str); stop = trace_clock_local(); local_irq_enable(); bm_cnt++; delta = stop - start; /* * The first read is cold cached, keep it separate from the * other calculations. */ if (bm_cnt == 1) { bm_first = delta; scnprintf(bm_str, BENCHMARK_EVENT_STRLEN, "first=%llu [COLD CACHED]", bm_first); return; } bm_last = delta; if (delta > bm_max) bm_max = delta; if (!bm_min || delta < bm_min) bm_min = delta; /* * When bm_cnt is greater than UINT_MAX, it breaks the statistics * accounting. Freeze the statistics when that happens. * We should have enough data for the avg and stddev anyway. */ if (bm_cnt > UINT_MAX) { scnprintf(bm_str, BENCHMARK_EVENT_STRLEN, "last=%llu first=%llu max=%llu min=%llu ** avg=%u std=%d std^2=%lld", bm_last, bm_first, bm_max, bm_min, bm_avg, bm_std, bm_stddev); return; } bm_total += delta; bm_totalsq += delta * delta; if (bm_cnt > 1) { /* * Apply Welford's method to calculate standard deviation: * s^2 = 1 / (n * (n-1)) * (n * \Sum (x_i)^2 - (\Sum x_i)^2) */ stddev = (u64)bm_cnt * bm_totalsq - bm_total * bm_total; do_div(stddev, (u32)bm_cnt); do_div(stddev, (u32)bm_cnt - 1); } else stddev = 0; delta = bm_total; do_div(delta, bm_cnt); avg = delta; if (stddev > 0) { int i = 0; /* * stddev is the square of standard deviation but * we want the actualy number. Use the average * as our seed to find the std. * * The next try is: * x = (x + N/x) / 2 * * Where N is the squared number to find the square * root of. */ seed = avg; do { last_seed = seed; seed = stddev; if (!last_seed) break; do_div(seed, last_seed); seed += last_seed; do_div(seed, 2); } while (i++ < 10 && last_seed != seed); std = seed; } scnprintf(bm_str, BENCHMARK_EVENT_STRLEN, "last=%llu first=%llu max=%llu min=%llu avg=%u std=%d std^2=%lld", bm_last, bm_first, bm_max, bm_min, avg, std, stddev); bm_std = std; bm_avg = avg; bm_stddev = stddev; } static int benchmark_event_kthread(void *arg) { /* sleep a bit to make sure the tracepoint gets activated */ msleep(100); while (!kthread_should_stop()) { trace_do_benchmark(); /* * We don't go to sleep, but let others * run as well. */ cond_resched(); } return 0; } /* * When the benchmark tracepoint is enabled, it calls this * function and the thread that calls the tracepoint is created. */ int trace_benchmark_reg(void) { if (!ok_to_run) { pr_warning("trace benchmark cannot be started via kernel command line\n"); return -EBUSY; } bm_event_thread = kthread_run(benchmark_event_kthread, NULL, "event_benchmark"); if (!bm_event_thread) { pr_warning("trace benchmark failed to create kernel thread\n"); return -ENOMEM; } return 0; } /* * When the benchmark tracepoint is disabled, it calls this * function and the thread that calls the tracepoint is deleted * and all the numbers are reset. */ void trace_benchmark_unreg(void) { if (!bm_event_thread) return; kthread_stop(bm_event_thread); bm_event_thread = NULL; strcpy(bm_str, "START"); bm_total = 0; bm_totalsq = 0; bm_last = 0; bm_max = 0; bm_min = 0; bm_cnt = 0; /* These don't need to be reset but reset them anyway */ bm_first = 0; bm_std = 0; bm_avg = 0; bm_stddev = 0; } static __init int ok_to_run_trace_benchmark(void) { ok_to_run = true; return 0; } early_initcall(ok_to_run_trace_benchmark); =8c56ea410efb537e5b4d10365e14b140f110314c'>plain -rw-r--r--ath79-clk.h479logplain -rw-r--r--axis,artpec6-clkctrl.h1112logplain -rw-r--r--bcm-cygnus.h3135logplain -rw-r--r--bcm-ns2.h2915logplain -rw-r--r--bcm-nsp.h2148logplain -rw-r--r--bcm21664.h1984logplain -rw-r--r--bcm281xx.h2456logplain -rw-r--r--bcm2835-aux.h635logplain -rw-r--r--bcm2835.h1962logplain -rw-r--r--berlin2.h1034logplain -rw-r--r--berlin2q.h695logplain -rw-r--r--clps711x-clock.h718logplain -rw-r--r--efm32-cmu.h1112logplain -rw-r--r--exynos-audss-clk.h597logplain -rw-r--r--exynos3250.h9083logplain -rw-r--r--exynos4.h8284logplain -rw-r--r--exynos4415.h9828logplain -rw-r--r--exynos5250.h4616logplain -rw-r--r--exynos5260-clk.h14876logplain -rw-r--r--exynos5410.h1689logplain -rw-r--r--exynos5420.h6857logplain -rw-r--r--exynos5433.h45372logplain -rw-r--r--exynos5440.h1141logplain -rw-r--r--exynos7-clk.h5281logplain -rw-r--r--gxbb-aoclkc.h2866logplain -rw-r--r--gxbb-clkc.h592logplain -rw-r--r--hi3516cv300-clock.h1668logplain -rw-r--r--hi3519-clock.h1328logplain -rw-r--r--hi3620-clock.h4496logplain -rw-r--r--hi6220-clock.h4508logplain -rw-r--r--hip04-clock.h1137logplain -rw-r--r--histb-clock.h2012logplain -rw-r--r--hix5hd2-clock.h2415logplain -rw-r--r--imx1-clock.h1055logplain -rw-r--r--imx21-clock.h2461logplain -rw-r--r--imx27-clock.h3494logplain -rw-r--r--imx5-clock.h7212logplain -rw-r--r--imx6qdl-clock.h9593logplain -rw-r--r--imx6sl-clock.h5849logplain -rw-r--r--imx6sx-clock.h9099logplain -rw-r--r--imx6ul-clock.h8203logplain -rw-r--r--imx7d-clock.h15974logplain -rw-r--r--jz4740-cgu.h1028logplain -rw-r--r--jz4780-cgu.h2470logplain -rw-r--r--lpc18xx-ccu.h2134logplain -rw-r--r--lpc18xx-cgu.h1142logplain -rw-r--r--lpc32xx-clock.h1633logplain -rw-r--r--lsi,axm5516-clks.h974logplain -rw-r--r--marvell,mmp2.h2022logplain -rw-r--r--marvell,pxa168.h1654logplain -rw-r--r--marvell,pxa1928.h1535logplain -rw-r--r--marvell,pxa910.h1598logplain -rw-r--r--maxim,max77620.h632logplain -rw-r--r--maxim,max77686.h648logplain -rw-r--r--maxim,max77802.h630logplain -rw-r--r--meson8b-clkc.h523logplain -rw-r--r--microchip,pic32-clock.h1150logplain -rw-r--r--mpc512x-clock.h2236logplain -rw-r--r--mt2701-clk.h13832logplain -rw-r--r--mt8135-clk.h5641logplain -rw-r--r--mt8173-clk.h9293logplain -rw-r--r--oxsemi,ox810se.h1002logplain -rw-r--r--oxsemi,ox820.h1203logplain -rw-r--r--pistachio-clk.h4863logplain -rw-r--r--pxa-clock.h1715logplain -rw-r--r--qcom,gcc-apq8084.h12872logplain -rw-r--r--qcom,gcc-ipq4019.h5423logplain -rw-r--r--qcom,gcc-ipq806x.h8574logplain -rw-r--r--qcom,gcc-mdm9615.h9497logplain -rw-r--r--qcom,gcc-msm8660.h7932logplain -rw-r--r--qcom,gcc-msm8916.h6190logplain -rw-r--r--qcom,gcc-msm8960.h9342logplain -rw-r--r--qcom,gcc-msm8974.h12340logplain -rw-r--r--qcom,gcc-msm8994.h4858logplain -rw-r--r--qcom,gcc-msm8996.h12575logplain -rw-r--r--qcom,lcc-ipq806x.h899logplain -rw-r--r--qcom,lcc-mdm9615.h1701logplain -rw-r--r--qcom,lcc-msm8960.h1616logplain -rw-r--r--qcom,mmcc-apq8084.h5722logplain -rw-r--r--qcom,mmcc-msm8960.h4109logplain -rw-r--r--qcom,mmcc-msm8974.h5223logplain -rw-r--r--qcom,mmcc-msm8996.h9403logplain -rw-r--r--qcom,rpmcc.h2101logplain -rw-r--r--r7s72100-clock.h1218logplain -rw-r--r--r8a73a4-clock.h1596logplain -rw-r--r--r8a7740-clock.h1992logplain -rw-r--r--r8a7743-cpg-mssr.h1269logplain -rw-r--r--r8a7745-cpg-mssr.h1298logplain -rw-r--r--r8a7778-clock.h1855logplain -rw-r--r--r8a7779-clock.h1647logplain -rw-r--r--r8a7790-clock.h4367logplain -rw-r--r--r8a7791-clock.h4388logplain -rw-r--r--r8a7792-clock.h2562logplain -rw-r--r--r8a7793-clock.h4561logplain -rw-r--r--r8a7794-clock.h3679logplain -rw-r--r--r8a7795-cpg-mssr.h1890logplain -rw-r--r--r8a7796-cpg-mssr.h2066logplain -rw-r--r--renesas-cpg-mssr.h542logplain -rw-r--r--rk1108-cru.h6605logplain -rw-r--r--rk3036-cru.h4584logplain -rw-r--r--rk3066a-cru.h1068logplain -rw-r--r--rk3188-cru-common.h6105logplain -rw-r--r--rk3188-cru.h1435logplain