diff options
author | Andy Lutomirski <luto@kernel.org> | 2015-04-20 16:53:55 -0700 |
---|---|---|
committer | Andy Lutomirski <luto@kernel.org> | 2015-04-20 16:53:55 -0700 |
commit | 53e5b21fd612efea629630ae9ac24df3c32f63fd (patch) | |
tree | f54fe25b18e60b8681743ed423ee480d21526df5 | |
parent | 21ebbf09a504143cc9fe91a466311488e90ff311 (diff) | |
download | misc-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.c | 39 |
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; |