-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
selftests/powerpc: Add Anton's null_syscall benchmark to the selftests
Pull in a version of Anton's null_syscall benchmark: http://ozlabs.org/~anton/junkcode/null_syscall.c Suggested-by: Michael Ellerman <mpe@ellerman.id.au> Signed-off-by: Anton Blanchard <anton@au.ibm.com> Signed-off-by: Rui Teng <rui.teng@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
- Loading branch information
Anton Blanchard
authored and
Michael Ellerman
committed
Nov 14, 2016
1 parent
a25f094
commit d8db9bc
Showing
3 changed files
with
160 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
gettimeofday | ||
context_switch | ||
mmap_bench | ||
futex_bench | ||
futex_bench | ||
null_syscall |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
157 changes: 157 additions & 0 deletions
157
tools/testing/selftests/powerpc/benchmarks/null_syscall.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
/* | ||
* Test null syscall performance | ||
* | ||
* Copyright (C) 2009-2015 Anton Blanchard, IBM | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License | ||
* as published by the Free Software Foundation; either version | ||
* 2 of the License, or (at your option) any later version. | ||
*/ | ||
|
||
#define NR_LOOPS 10000000 | ||
|
||
#include <string.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <unistd.h> | ||
#include <time.h> | ||
#include <sys/types.h> | ||
#include <sys/time.h> | ||
#include <signal.h> | ||
|
||
static volatile int soak_done; | ||
unsigned long long clock_frequency; | ||
unsigned long long timebase_frequency; | ||
double timebase_multiplier; | ||
|
||
static inline unsigned long long mftb(void) | ||
{ | ||
unsigned long low; | ||
|
||
asm volatile("mftb %0" : "=r" (low)); | ||
|
||
return low; | ||
} | ||
|
||
static void sigalrm_handler(int unused) | ||
{ | ||
soak_done = 1; | ||
} | ||
|
||
/* | ||
* Use a timer instead of busy looping on clock_gettime() so we don't | ||
* pollute profiles with glibc and VDSO hits. | ||
*/ | ||
static void cpu_soak_usecs(unsigned long usecs) | ||
{ | ||
struct itimerval val; | ||
|
||
memset(&val, 0, sizeof(val)); | ||
val.it_value.tv_usec = usecs; | ||
|
||
signal(SIGALRM, sigalrm_handler); | ||
setitimer(ITIMER_REAL, &val, NULL); | ||
|
||
while (1) { | ||
if (soak_done) | ||
break; | ||
} | ||
|
||
signal(SIGALRM, SIG_DFL); | ||
} | ||
|
||
/* | ||
* This only works with recent kernels where cpufreq modifies | ||
* /proc/cpuinfo dynamically. | ||
*/ | ||
static void get_proc_frequency(void) | ||
{ | ||
FILE *f; | ||
char line[128]; | ||
char *p, *end; | ||
unsigned long v; | ||
double d; | ||
char *override; | ||
|
||
/* Try to get out of low power/low frequency mode */ | ||
cpu_soak_usecs(0.25 * 1000000); | ||
|
||
f = fopen("/proc/cpuinfo", "r"); | ||
if (f == NULL) | ||
return; | ||
|
||
timebase_frequency = 0; | ||
|
||
while (fgets(line, sizeof(line), f) != NULL) { | ||
if (strncmp(line, "timebase", 8) == 0) { | ||
p = strchr(line, ':'); | ||
if (p != NULL) { | ||
v = strtoull(p + 1, &end, 0); | ||
if (end != p + 1) | ||
timebase_frequency = v; | ||
} | ||
} | ||
|
||
if (((strncmp(line, "clock", 5) == 0) || | ||
(strncmp(line, "cpu MHz", 7) == 0))) { | ||
p = strchr(line, ':'); | ||
if (p != NULL) { | ||
d = strtod(p + 1, &end); | ||
if (end != p + 1) { | ||
/* Find fastest clock frequency */ | ||
if ((d * 1000000ULL) > clock_frequency) | ||
clock_frequency = d * 1000000ULL; | ||
} | ||
} | ||
} | ||
} | ||
|
||
fclose(f); | ||
|
||
override = getenv("FREQUENCY"); | ||
if (override) | ||
clock_frequency = strtoull(override, NULL, 10); | ||
|
||
if (timebase_frequency) | ||
timebase_multiplier = (double)clock_frequency | ||
/ timebase_frequency; | ||
else | ||
timebase_multiplier = 1; | ||
} | ||
|
||
static void do_null_syscall(unsigned long nr) | ||
{ | ||
unsigned long i; | ||
|
||
for (i = 0; i < nr; i++) | ||
getppid(); | ||
} | ||
|
||
#define TIME(A, STR) \ | ||
|
||
int main(void) | ||
{ | ||
unsigned long tb_start, tb_now; | ||
struct timespec tv_start, tv_now; | ||
unsigned long long elapsed_ns, elapsed_tb; | ||
|
||
get_proc_frequency(); | ||
|
||
clock_gettime(CLOCK_MONOTONIC, &tv_start); | ||
tb_start = mftb(); | ||
|
||
do_null_syscall(NR_LOOPS); | ||
|
||
clock_gettime(CLOCK_MONOTONIC, &tv_now); | ||
tb_now = mftb(); | ||
|
||
elapsed_ns = (tv_now.tv_sec - tv_start.tv_sec) * 1000000000ULL + | ||
(tv_now.tv_nsec - tv_start.tv_nsec); | ||
elapsed_tb = tb_now - tb_start; | ||
|
||
printf("%10.2f ns %10.2f cycles\n", (float)elapsed_ns / NR_LOOPS, | ||
(float)elapsed_tb * timebase_multiplier / NR_LOOPS); | ||
|
||
return 0; | ||
} |