summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@kernel.org>2017-06-26 18:19:03 -0700
committerAndy Lutomirski <luto@kernel.org>2017-06-26 18:19:03 -0700
commitcb7f9f0592f8a75949919618f3b74121b3fc1a4a (patch)
tree2b3d5824b0bd44ce31e84c4335d5a4307d8d256e
parent61397cab91021109604e9365feff0bc112842f25 (diff)
downloadmisc-tests-cb7f9f0592f8a75949919618f3b74121b3fc1a4a.tar.gz
Add madvise_bounce
Signed-off-by: Andy Lutomirski <luto@kernel.org>
-rw-r--r--Makefile2
-rw-r--r--madvise_bounce.cc86
2 files changed, 87 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 82382aa..c31760f 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ SIMPLE_C_TARGETS := dump-vsyscall context_switch_latency kernel_pf user_visible_
SIMPLE_CC_TARGETS := evil-clock-test
SPLIT_C_TARGETS := dump-vdso dump-vvar syscall_exit_regs dump_all_pmcs ntflag sysret_ss_attrs
-SPLIT_CC_TARGETS := timing_test test_vsyscall test_vdso_parser
+SPLIT_CC_TARGETS := timing_test test_vsyscall test_vdso_parser madvise_bounce
ALL_TARGETS := $(SIMPLE_C_TARGETS) $(SIMPLE_CC_TARGETS) $(SPLIT_C_TARGETS:%=%_64) $(SPLIT_CC_TARGETS:%=%_64) $(SPLIT_C_TARGETS:%=%_32) $(SPLIT_CC_TARGETS:%=%_32) syscall32_from_64 segregs
diff --git a/madvise_bounce.cc b/madvise_bounce.cc
new file mode 100644
index 0000000..1888fc7
--- /dev/null
+++ b/madvise_bounce.cc
@@ -0,0 +1,86 @@
+#define __STDC_FORMAT_MACROS
+
+#include <sys/time.h>
+#include <time.h>
+#include <stdlib.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <atomic>
+#include <signal.h>
+#include <pthread.h>
+#include <err.h>
+#include <sys/mman.h>
+
+void describe_clock(const char *name, int id)
+{
+ struct timespec res;
+ int ret = clock_getres(id, &res);
+ if (ret < 0) {
+ printf(" %d (%s) [failed to query resolution]\n",
+ id, name);
+ } else {
+ printf(" %d (%s) resolution = %" PRIu64 ".%09u\n",
+ id, name,
+ (uint64_t)res.tv_sec, (unsigned)res.tv_nsec);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ if (argc < 2) {
+ printf("Usage: %s <iters>\n", argv[0]);
+
+ return 1;
+ }
+
+ cpu_set_t cpuset;
+ CPU_ZERO(&cpuset);
+ int cpu = 0;
+
+ long loop_mult = 1;
+ char *loop_arg = strdup(argv[1]);
+ size_t loop_arg_len = strlen(loop_arg);
+ if (loop_arg_len && loop_arg[loop_arg_len-1] == 'k') {
+ loop_mult = 1000;
+ loop_arg[loop_arg_len-1] = '\0';
+ } else if (loop_arg_len && loop_arg[loop_arg_len-1] == 'M') {
+ loop_mult = 1000000;
+ loop_arg[loop_arg_len-1] = '\0';
+ }
+ size_t loops = (size_t)atol(argv[1]) * loop_mult;
+ free(loop_arg);
+
+ char *buf = (char *)mmap(0, 4096, PROT_READ|PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE | MAP_POPULATE,
+ -1, 0);
+ if (buf == MAP_FAILED)
+ err(1, "mmap");
+
+ timespec start;
+ clock_gettime(CLOCK_MONOTONIC, &start);
+
+ for (size_t i = 0; i < loops; ++i) {
+ madvise(buf, 4096, MADV_DONTNEED);
+ buf[0] = 1;
+
+ cpu = !cpu;
+ CPU_SET(cpu, &cpuset);
+ if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0)
+ err(1, "sched_setaffinity");
+ CPU_CLR(cpu, &cpuset);
+ }
+
+ timespec end;
+ clock_gettime(CLOCK_MONOTONIC, &end);
+ unsigned long long duration = (end.tv_nsec - start.tv_nsec) + 1000000000ULL * (end.tv_sec - start.tv_sec);
+ printf("%ld loops in %.5fs = %.2f nsec / loop\n",
+ (long)loops, float(duration) * 1e-9,
+ float(duration) / loops);
+ if (duration == 0)
+ printf("[WARN]\tThe apparent elapsed time was exactly 0. You have precision issues.\n");
+ return 0;
+}