aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/tools/perf/bench/syscall.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tools/perf/bench/syscall.c115
1 files changed, 109 insertions, 6 deletions
diff --git a/tools/perf/bench/syscall.c b/tools/perf/bench/syscall.c
index 5fe621cff8e9..ea4dfc07cbd6 100644
--- a/tools/perf/bench/syscall.c
+++ b/tools/perf/bench/syscall.c
@@ -14,9 +14,14 @@
#include <sys/time.h>
#include <sys/syscall.h>
#include <sys/types.h>
+#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
+#ifndef __NR_fork
+#define __NR_fork -1
+#endif
+
#define LOOPS_DEFAULT 10000000
static int loops = LOOPS_DEFAULT;
@@ -30,31 +35,109 @@ static const char * const bench_syscall_usage[] = {
NULL
};
-int bench_syscall_basic(int argc, const char **argv)
+static void test_fork(void)
+{
+ pid_t pid = fork();
+
+ if (pid < 0) {
+ fprintf(stderr, "fork failed\n");
+ exit(1);
+ } else if (pid == 0) {
+ exit(0);
+ } else {
+ if (waitpid(pid, NULL, 0) < 0) {
+ fprintf(stderr, "waitpid failed\n");
+ exit(1);
+ }
+ }
+}
+
+static void test_execve(void)
+{
+ const char *pathname = "/bin/true";
+ char *const argv[] = { (char *)pathname, NULL };
+ pid_t pid = fork();
+
+ if (pid < 0) {
+ fprintf(stderr, "fork failed\n");
+ exit(1);
+ } else if (pid == 0) {
+ execve(pathname, argv, NULL);
+ fprintf(stderr, "execve /bin/true failed\n");
+ exit(1);
+ } else {
+ if (waitpid(pid, NULL, 0) < 0) {
+ fprintf(stderr, "waitpid failed\n");
+ exit(1);
+ }
+ }
+}
+
+static int bench_syscall_common(int argc, const char **argv, int syscall)
{
struct timeval start, stop, diff;
unsigned long long result_usec = 0;
+ const char *name = NULL;
int i;
argc = parse_options(argc, argv, options, bench_syscall_usage, 0);
gettimeofday(&start, NULL);
- for (i = 0; i < loops; i++)
- getppid();
+ for (i = 0; i < loops; i++) {
+ switch (syscall) {
+ case __NR_getppid:
+ getppid();
+ break;
+ case __NR_getpgid:
+ getpgid(0);
+ break;
+ case __NR_fork:
+ test_fork();
+ /* Only loop 10000 times to save time */
+ if (i == 10000)
+ loops = 10000;
+ break;
+ case __NR_execve:
+ test_execve();
+ /* Only loop 10000 times to save time */
+ if (i == 10000)
+ loops = 10000;
+ break;
+ default:
+ break;
+ }
+ }
gettimeofday(&stop, NULL);
timersub(&stop, &start, &diff);
+ switch (syscall) {
+ case __NR_getppid:
+ name = "getppid()";
+ break;
+ case __NR_getpgid:
+ name = "getpgid()";
+ break;
+ case __NR_fork:
+ name = "fork()";
+ break;
+ case __NR_execve:
+ name = "execve()";
+ break;
+ default:
+ break;
+ }
+
switch (bench_format) {
case BENCH_FORMAT_DEFAULT:
- printf("# Executed %'d getppid() calls\n", loops);
+ printf("# Executed %'d %s calls\n", loops, name);
result_usec = diff.tv_sec * 1000000;
result_usec += diff.tv_usec;
printf(" %14s: %lu.%03lu [sec]\n\n", "Total time",
- diff.tv_sec,
+ (unsigned long) diff.tv_sec,
(unsigned long) (diff.tv_usec/1000));
printf(" %14lf usecs/op\n",
@@ -66,7 +149,7 @@ int bench_syscall_basic(int argc, const char **argv)
case BENCH_FORMAT_SIMPLE:
printf("%lu.%03lu\n",
- diff.tv_sec,
+ (unsigned long) diff.tv_sec,
(unsigned long) (diff.tv_usec / 1000));
break;
@@ -79,3 +162,23 @@ int bench_syscall_basic(int argc, const char **argv)
return 0;
}
+
+int bench_syscall_basic(int argc, const char **argv)
+{
+ return bench_syscall_common(argc, argv, __NR_getppid);
+}
+
+int bench_syscall_getpgid(int argc, const char **argv)
+{
+ return bench_syscall_common(argc, argv, __NR_getpgid);
+}
+
+int bench_syscall_fork(int argc, const char **argv)
+{
+ return bench_syscall_common(argc, argv, __NR_fork);
+}
+
+int bench_syscall_execve(int argc, const char **argv)
+{
+ return bench_syscall_common(argc, argv, __NR_execve);
+}