xref: /linux/tools/perf/bench/syscall.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
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