summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@kernel.org>2015-04-20 16:53:55 -0700
committerAndy Lutomirski <luto@kernel.org>2015-04-20 16:53:55 -0700
commit53e5b21fd612efea629630ae9ac24df3c32f63fd (patch)
treef54fe25b18e60b8681743ed423ee480d21526df5
parent21ebbf09a504143cc9fe91a466311488e90ff311 (diff)
downloadmisc-tests-53e5b21fd612efea629630ae9ac24df3c32f63fd.tar.gz
perf_self_monitor: Wait for a count to settle down at startup
Signed-off-by: Andy Lutomirski <luto@kernel.org>
-rw-r--r--tight_loop/perf_self_monitor.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/tight_loop/perf_self_monitor.c b/tight_loop/perf_self_monitor.c
index 52d338b..f3de608 100644
--- a/tight_loop/perf_self_monitor.c
+++ b/tight_loop/perf_self_monitor.c
@@ -79,6 +79,10 @@ static inline uint64_t psm_rdpmc(unsigned int ecx)
return (((uint64_t)edx << 32) | eax);
}
+typedef bool (*psm_sample_fn)(uint64_t *count,
+ const struct psm_counter *counter,
+ void *opaque);
+
/*
* psm_atomic is a mechanism for very precise counter measurement of
* very short operations. A psm_atomic interval will fail if the
@@ -140,10 +144,45 @@ static inline bool psm_atomic_elapsed(uint64_t *elapsed_count,
return true;
}
+bool psm_atomic_sample_empty(uint64_t *count,
+ const struct psm_counter *ctr, void *opaque)
+{
+ struct psm_atomic duration = psm_atomic_start(ctr);
+ return psm_atomic_elapsed(count, &duration, ctr);
+}
+
+void psm_settle(const struct psm_counter *ctr, psm_sample_fn fn, void *opaque)
+{
+ uint64_t val = UINT64_MAX;
+ int good_iters = 0;
+ for (int total_iters = 0; total_iters < 500; total_iters++) {
+ uint64_t best = UINT64_MAX;
+ for (int inner = 0; inner < 10; ) {
+ uint64_t count;
+ if (!fn(&count, ctr, opaque))
+ continue; /* Rejected sample */
+ if (count < best)
+ best = count;
+ inner++;
+ }
+
+ if (best != val) {
+ good_iters = 1;
+ val = best;
+ } else {
+ good_iters++;
+ if (good_iters == 10)
+ return;
+ }
+ }
+}
+
int main()
{
struct psm_counter *ctr = psm_counter_create();
+ psm_settle(ctr, psm_atomic_sample_empty, NULL);
+
for (int i = 0; i < 20; i++) {
struct psm_atomic duration = psm_atomic_start(ctr);
unsigned long rax;