1c2a08203SDavidlohr Bueso /*
2c2a08203SDavidlohr Bueso *
3c2a08203SDavidlohr Bueso * syscall.c
4c2a08203SDavidlohr Bueso *
5c2a08203SDavidlohr Bueso * syscall: Benchmark for system call performance
6c2a08203SDavidlohr Bueso */
7c2a08203SDavidlohr Bueso #include "../perf.h"
8c2a08203SDavidlohr Bueso #include "../util/util.h"
9c2a08203SDavidlohr Bueso #include <subcmd/parse-options.h>
10c2a08203SDavidlohr Bueso #include "../builtin.h"
11c2a08203SDavidlohr Bueso #include "bench.h"
12c2a08203SDavidlohr Bueso
13c2a08203SDavidlohr Bueso #include <stdio.h>
14c2a08203SDavidlohr Bueso #include <sys/time.h>
15c2a08203SDavidlohr Bueso #include <sys/syscall.h>
16c2a08203SDavidlohr Bueso #include <sys/types.h>
17540f8b56STiezhu Yang #include <sys/wait.h>
18c2a08203SDavidlohr Bueso #include <unistd.h>
19c2a08203SDavidlohr Bueso #include <stdlib.h>
20c2a08203SDavidlohr Bueso
21*ece7f7c0STiezhu Yang #ifndef __NR_fork
22*ece7f7c0STiezhu Yang #define __NR_fork -1
23*ece7f7c0STiezhu Yang #endif
24*ece7f7c0STiezhu Yang
25c2a08203SDavidlohr Bueso #define LOOPS_DEFAULT 10000000
26c2a08203SDavidlohr Bueso static int loops = LOOPS_DEFAULT;
27c2a08203SDavidlohr Bueso
28c2a08203SDavidlohr Bueso static const struct option options[] = {
29c2a08203SDavidlohr Bueso OPT_INTEGER('l', "loop", &loops, "Specify number of loops"),
30c2a08203SDavidlohr Bueso OPT_END()
31c2a08203SDavidlohr Bueso };
32c2a08203SDavidlohr Bueso
33c2a08203SDavidlohr Bueso static const char * const bench_syscall_usage[] = {
34c2a08203SDavidlohr Bueso "perf bench syscall <options>",
35c2a08203SDavidlohr Bueso NULL
36c2a08203SDavidlohr Bueso };
37c2a08203SDavidlohr Bueso
test_fork(void)38*ece7f7c0STiezhu Yang static void test_fork(void)
39*ece7f7c0STiezhu Yang {
40*ece7f7c0STiezhu Yang pid_t pid = fork();
41*ece7f7c0STiezhu Yang
42*ece7f7c0STiezhu Yang if (pid < 0) {
43*ece7f7c0STiezhu Yang fprintf(stderr, "fork failed\n");
44*ece7f7c0STiezhu Yang exit(1);
45*ece7f7c0STiezhu Yang } else if (pid == 0) {
46*ece7f7c0STiezhu Yang exit(0);
47*ece7f7c0STiezhu Yang } else {
48*ece7f7c0STiezhu Yang if (waitpid(pid, NULL, 0) < 0) {
49*ece7f7c0STiezhu Yang fprintf(stderr, "waitpid failed\n");
50*ece7f7c0STiezhu Yang exit(1);
51*ece7f7c0STiezhu Yang }
52*ece7f7c0STiezhu Yang }
53*ece7f7c0STiezhu Yang }
54*ece7f7c0STiezhu Yang
test_execve(void)55540f8b56STiezhu Yang static void test_execve(void)
56540f8b56STiezhu Yang {
57540f8b56STiezhu Yang const char *pathname = "/bin/true";
58540f8b56STiezhu Yang char *const argv[] = { (char *)pathname, NULL };
59540f8b56STiezhu Yang pid_t pid = fork();
60540f8b56STiezhu Yang
61540f8b56STiezhu Yang if (pid < 0) {
62540f8b56STiezhu Yang fprintf(stderr, "fork failed\n");
63540f8b56STiezhu Yang exit(1);
64540f8b56STiezhu Yang } else if (pid == 0) {
65540f8b56STiezhu Yang execve(pathname, argv, NULL);
66540f8b56STiezhu Yang fprintf(stderr, "execve /bin/true failed\n");
67540f8b56STiezhu Yang exit(1);
68540f8b56STiezhu Yang } else {
69540f8b56STiezhu Yang if (waitpid(pid, NULL, 0) < 0) {
70540f8b56STiezhu Yang fprintf(stderr, "waitpid failed\n");
71540f8b56STiezhu Yang exit(1);
72540f8b56STiezhu Yang }
73540f8b56STiezhu Yang }
74540f8b56STiezhu Yang }
75540f8b56STiezhu Yang
bench_syscall_common(int argc,const char ** argv,int syscall)763fe91f32STiezhu Yang static int bench_syscall_common(int argc, const char **argv, int syscall)
77c2a08203SDavidlohr Bueso {
78c2a08203SDavidlohr Bueso struct timeval start, stop, diff;
79c2a08203SDavidlohr Bueso unsigned long long result_usec = 0;
803fe91f32STiezhu Yang const char *name = NULL;
81c2a08203SDavidlohr Bueso int i;
82c2a08203SDavidlohr Bueso
83c2a08203SDavidlohr Bueso argc = parse_options(argc, argv, options, bench_syscall_usage, 0);
84c2a08203SDavidlohr Bueso
85c2a08203SDavidlohr Bueso gettimeofday(&start, NULL);
86c2a08203SDavidlohr Bueso
873fe91f32STiezhu Yang for (i = 0; i < loops; i++) {
883fe91f32STiezhu Yang switch (syscall) {
893fe91f32STiezhu Yang case __NR_getppid:
90c2a08203SDavidlohr Bueso getppid();
913fe91f32STiezhu Yang break;
92391f84e5STiezhu Yang case __NR_getpgid:
93391f84e5STiezhu Yang getpgid(0);
94391f84e5STiezhu Yang break;
95*ece7f7c0STiezhu Yang case __NR_fork:
96*ece7f7c0STiezhu Yang test_fork();
97*ece7f7c0STiezhu Yang /* Only loop 10000 times to save time */
98*ece7f7c0STiezhu Yang if (i == 10000)
99*ece7f7c0STiezhu Yang loops = 10000;
100*ece7f7c0STiezhu Yang break;
101540f8b56STiezhu Yang case __NR_execve:
102540f8b56STiezhu Yang test_execve();
103540f8b56STiezhu Yang /* Only loop 10000 times to save time */
104540f8b56STiezhu Yang if (i == 10000)
105540f8b56STiezhu Yang loops = 10000;
106540f8b56STiezhu Yang break;
1073fe91f32STiezhu Yang default:
1083fe91f32STiezhu Yang break;
1093fe91f32STiezhu Yang }
1103fe91f32STiezhu Yang }
111c2a08203SDavidlohr Bueso
112c2a08203SDavidlohr Bueso gettimeofday(&stop, NULL);
113c2a08203SDavidlohr Bueso timersub(&stop, &start, &diff);
114c2a08203SDavidlohr Bueso
1153fe91f32STiezhu Yang switch (syscall) {
1163fe91f32STiezhu Yang case __NR_getppid:
1173fe91f32STiezhu Yang name = "getppid()";
1183fe91f32STiezhu Yang break;
119391f84e5STiezhu Yang case __NR_getpgid:
120391f84e5STiezhu Yang name = "getpgid()";
121391f84e5STiezhu Yang break;
122*ece7f7c0STiezhu Yang case __NR_fork:
123*ece7f7c0STiezhu Yang name = "fork()";
124*ece7f7c0STiezhu Yang break;
125540f8b56STiezhu Yang case __NR_execve:
126540f8b56STiezhu Yang name = "execve()";
127540f8b56STiezhu Yang break;
1283fe91f32STiezhu Yang default:
1293fe91f32STiezhu Yang break;
1303fe91f32STiezhu Yang }
1313fe91f32STiezhu Yang
132c2a08203SDavidlohr Bueso switch (bench_format) {
133c2a08203SDavidlohr Bueso case BENCH_FORMAT_DEFAULT:
1343fe91f32STiezhu Yang printf("# Executed %'d %s calls\n", loops, name);
135c2a08203SDavidlohr Bueso
136c2a08203SDavidlohr Bueso result_usec = diff.tv_sec * 1000000;
137c2a08203SDavidlohr Bueso result_usec += diff.tv_usec;
138c2a08203SDavidlohr Bueso
139c2a08203SDavidlohr Bueso printf(" %14s: %lu.%03lu [sec]\n\n", "Total time",
140ded2e511SPierre Gondois (unsigned long) diff.tv_sec,
141c2a08203SDavidlohr Bueso (unsigned long) (diff.tv_usec/1000));
142c2a08203SDavidlohr Bueso
143c2a08203SDavidlohr Bueso printf(" %14lf usecs/op\n",
144c2a08203SDavidlohr Bueso (double)result_usec / (double)loops);
145c2a08203SDavidlohr Bueso printf(" %'14d ops/sec\n",
146c2a08203SDavidlohr Bueso (int)((double)loops /
147c2a08203SDavidlohr Bueso ((double)result_usec / (double)1000000)));
148c2a08203SDavidlohr Bueso break;
149c2a08203SDavidlohr Bueso
150c2a08203SDavidlohr Bueso case BENCH_FORMAT_SIMPLE:
151c2a08203SDavidlohr Bueso printf("%lu.%03lu\n",
152ded2e511SPierre Gondois (unsigned long) diff.tv_sec,
153c2a08203SDavidlohr Bueso (unsigned long) (diff.tv_usec / 1000));
154c2a08203SDavidlohr Bueso break;
155c2a08203SDavidlohr Bueso
156c2a08203SDavidlohr Bueso default:
157c2a08203SDavidlohr Bueso /* reaching here is something disaster */
158c2a08203SDavidlohr Bueso fprintf(stderr, "Unknown format:%d\n", bench_format);
159c2a08203SDavidlohr Bueso exit(1);
160c2a08203SDavidlohr Bueso break;
161c2a08203SDavidlohr Bueso }
162c2a08203SDavidlohr Bueso
163c2a08203SDavidlohr Bueso return 0;
164c2a08203SDavidlohr Bueso }
1653fe91f32STiezhu Yang
bench_syscall_basic(int argc,const char ** argv)1663fe91f32STiezhu Yang int bench_syscall_basic(int argc, const char **argv)
1673fe91f32STiezhu Yang {
1683fe91f32STiezhu Yang return bench_syscall_common(argc, argv, __NR_getppid);
1693fe91f32STiezhu Yang }
170391f84e5STiezhu Yang
bench_syscall_getpgid(int argc,const char ** argv)171391f84e5STiezhu Yang int bench_syscall_getpgid(int argc, const char **argv)
172391f84e5STiezhu Yang {
173391f84e5STiezhu Yang return bench_syscall_common(argc, argv, __NR_getpgid);
174391f84e5STiezhu Yang }
175540f8b56STiezhu Yang
bench_syscall_fork(int argc,const char ** argv)176*ece7f7c0STiezhu Yang int bench_syscall_fork(int argc, const char **argv)
177*ece7f7c0STiezhu Yang {
178*ece7f7c0STiezhu Yang return bench_syscall_common(argc, argv, __NR_fork);
179*ece7f7c0STiezhu Yang }
180*ece7f7c0STiezhu Yang
bench_syscall_execve(int argc,const char ** argv)181540f8b56STiezhu Yang int bench_syscall_execve(int argc, const char **argv)
182540f8b56STiezhu Yang {
183540f8b56STiezhu Yang return bench_syscall_common(argc, argv, __NR_execve);
184540f8b56STiezhu Yang }
185