1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Test null syscall performance
5 * Copyright (C) 2009-2015 Anton Blanchard, IBM
8 #define NR_LOOPS 10000000
15 #include <sys/types.h>
19 static volatile int soak_done;
20 unsigned long long clock_frequency;
21 unsigned long long timebase_frequency;
22 double timebase_multiplier;
24 static inline unsigned long mftb(void)
28 asm volatile("mftb %0" : "=r" (low));
33 static void sigalrm_handler(int unused)
39 * Use a timer instead of busy looping on clock_gettime() so we don't
40 * pollute profiles with glibc and VDSO hits.
42 static void cpu_soak_usecs(unsigned long usecs)
46 memset(&val, 0, sizeof(val));
47 val.it_value.tv_usec = usecs;
49 signal(SIGALRM, sigalrm_handler);
50 setitimer(ITIMER_REAL, &val, NULL);
57 signal(SIGALRM, SIG_DFL);
61 * This only works with recent kernels where cpufreq modifies
62 * /proc/cpuinfo dynamically.
64 static void get_proc_frequency(void)
73 /* Try to get out of low power/low frequency mode */
74 cpu_soak_usecs(0.25 * 1000000);
76 f = fopen("/proc/cpuinfo", "r");
80 timebase_frequency = 0;
82 while (fgets(line, sizeof(line), f) != NULL) {
83 if (strncmp(line, "timebase", 8) == 0) {
84 p = strchr(line, ':');
86 v = strtoull(p + 1, &end, 0);
88 timebase_frequency = v;
92 if (((strncmp(line, "clock", 5) == 0) ||
93 (strncmp(line, "cpu MHz", 7) == 0))) {
94 p = strchr(line, ':');
96 d = strtod(p + 1, &end);
98 /* Find fastest clock frequency */
99 if ((d * 1000000ULL) > clock_frequency)
100 clock_frequency = d * 1000000ULL;
108 override = getenv("FREQUENCY");
110 clock_frequency = strtoull(override, NULL, 10);
112 if (timebase_frequency)
113 timebase_multiplier = (double)clock_frequency
114 / timebase_frequency;
116 timebase_multiplier = 1;
119 static void do_null_syscall(unsigned long nr)
123 for (i = 0; i < nr; i++)
127 #define TIME(A, STR) \
131 unsigned long tb_start, tb_now;
132 struct timespec tv_start, tv_now;
133 unsigned long long elapsed_ns, elapsed_tb;
135 get_proc_frequency();
137 clock_gettime(CLOCK_MONOTONIC, &tv_start);
140 do_null_syscall(NR_LOOPS);
142 clock_gettime(CLOCK_MONOTONIC, &tv_now);
145 elapsed_ns = (tv_now.tv_sec - tv_start.tv_sec) * 1000000000ULL +
146 (tv_now.tv_nsec - tv_start.tv_nsec);
147 elapsed_tb = tb_now - tb_start;
149 printf("%10.2f ns %10.2f cycles\n", (float)elapsed_ns / NR_LOOPS,
150 (float)elapsed_tb * timebase_multiplier / NR_LOOPS);