aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/bench/sched-pipe.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/bench/sched-pipe.c')
-rw-r--r--tools/perf/bench/sched-pipe.c115
1 files changed, 86 insertions, 29 deletions
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index 69cfba8d4c6c..07a8d7646a15 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -7,9 +7,7 @@
7 * Based on pipe-test-1m.c by Ingo Molnar <mingo@redhat.com> 7 * Based on pipe-test-1m.c by Ingo Molnar <mingo@redhat.com>
8 * http://people.redhat.com/mingo/cfs-scheduler/tools/pipe-test-1m.c 8 * http://people.redhat.com/mingo/cfs-scheduler/tools/pipe-test-1m.c
9 * Ported to perf by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> 9 * Ported to perf by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
10 *
11 */ 10 */
12
13#include "../perf.h" 11#include "../perf.h"
14#include "../util/util.h" 12#include "../util/util.h"
15#include "../util/parse-options.h" 13#include "../util/parse-options.h"
@@ -28,12 +26,24 @@
28#include <sys/time.h> 26#include <sys/time.h>
29#include <sys/types.h> 27#include <sys/types.h>
30 28
29#include <pthread.h>
30
31struct thread_data {
32 int nr;
33 int pipe_read;
34 int pipe_write;
35 pthread_t pthread;
36};
37
31#define LOOPS_DEFAULT 1000000 38#define LOOPS_DEFAULT 1000000
32static int loops = LOOPS_DEFAULT; 39static int loops = LOOPS_DEFAULT;
40
41/* Use processes by default: */
42static bool threaded;
33 43
34static const struct option options[] = { 44static const struct option options[] = {
35 OPT_INTEGER('l', "loop", &loops, 45 OPT_INTEGER('l', "loop", &loops, "Specify number of loops"),
36 "Specify number of loops"), 46 OPT_BOOLEAN('T', "threaded", &threaded, "Specify threads/process based task setup"),
37 OPT_END() 47 OPT_END()
38}; 48};
39 49
@@ -42,13 +52,37 @@ static const char * const bench_sched_pipe_usage[] = {
42 NULL 52 NULL
43}; 53};
44 54
45int bench_sched_pipe(int argc, const char **argv, 55static void *worker_thread(void *__tdata)
46 const char *prefix __maybe_unused)
47{ 56{
48 int pipe_1[2], pipe_2[2]; 57 struct thread_data *td = __tdata;
49 int m = 0, i; 58 int m = 0, i;
59 int ret;
60
61 for (i = 0; i < loops; i++) {
62 if (!td->nr) {
63 ret = read(td->pipe_read, &m, sizeof(int));
64 BUG_ON(ret != sizeof(int));
65 ret = write(td->pipe_write, &m, sizeof(int));
66 BUG_ON(ret != sizeof(int));
67 } else {
68 ret = write(td->pipe_write, &m, sizeof(int));
69 BUG_ON(ret != sizeof(int));
70 ret = read(td->pipe_read, &m, sizeof(int));
71 BUG_ON(ret != sizeof(int));
72 }
73 }
74
75 return NULL;
76}
77
78int bench_sched_pipe(int argc, const char **argv, const char *prefix __maybe_unused)
79{
80 struct thread_data threads[2], *td;
81 int pipe_1[2], pipe_2[2];
50 struct timeval start, stop, diff; 82 struct timeval start, stop, diff;
51 unsigned long long result_usec = 0; 83 unsigned long long result_usec = 0;
84 int nr_threads = 2;
85 int t;
52 86
53 /* 87 /*
54 * why does "ret" exist? 88 * why does "ret" exist?
@@ -58,43 +92,66 @@ int bench_sched_pipe(int argc, const char **argv,
58 int __maybe_unused ret, wait_stat; 92 int __maybe_unused ret, wait_stat;
59 pid_t pid, retpid __maybe_unused; 93 pid_t pid, retpid __maybe_unused;
60 94
61 argc = parse_options(argc, argv, options, 95 argc = parse_options(argc, argv, options, bench_sched_pipe_usage, 0);
62 bench_sched_pipe_usage, 0);
63 96
64 BUG_ON(pipe(pipe_1)); 97 BUG_ON(pipe(pipe_1));
65 BUG_ON(pipe(pipe_2)); 98 BUG_ON(pipe(pipe_2));
66 99
67 pid = fork();
68 assert(pid >= 0);
69
70 gettimeofday(&start, NULL); 100 gettimeofday(&start, NULL);
71 101
72 if (!pid) { 102 for (t = 0; t < nr_threads; t++) {
73 for (i = 0; i < loops; i++) { 103 td = threads + t;
74 ret = read(pipe_1[0], &m, sizeof(int)); 104
75 ret = write(pipe_2[1], &m, sizeof(int)); 105 td->nr = t;
76 } 106
77 } else { 107 if (t == 0) {
78 for (i = 0; i < loops; i++) { 108 td->pipe_read = pipe_1[0];
79 ret = write(pipe_1[1], &m, sizeof(int)); 109 td->pipe_write = pipe_2[1];
80 ret = read(pipe_2[0], &m, sizeof(int)); 110 } else {
111 td->pipe_write = pipe_1[1];
112 td->pipe_read = pipe_2[0];
81 } 113 }
82 } 114 }
83 115
84 gettimeofday(&stop, NULL);
85 timersub(&stop, &start, &diff);
86 116
87 if (pid) { 117 if (threaded) {
118
119 for (t = 0; t < nr_threads; t++) {
120 td = threads + t;
121
122 ret = pthread_create(&td->pthread, NULL, worker_thread, td);
123 BUG_ON(ret);
124 }
125
126 for (t = 0; t < nr_threads; t++) {
127 td = threads + t;
128
129 ret = pthread_join(td->pthread, NULL);
130 BUG_ON(ret);
131 }
132
133 } else {
134 pid = fork();
135 assert(pid >= 0);
136
137 if (!pid) {
138 worker_thread(threads + 0);
139 exit(0);
140 } else {
141 worker_thread(threads + 1);
142 }
143
88 retpid = waitpid(pid, &wait_stat, 0); 144 retpid = waitpid(pid, &wait_stat, 0);
89 assert((retpid == pid) && WIFEXITED(wait_stat)); 145 assert((retpid == pid) && WIFEXITED(wait_stat));
90 } else {
91 exit(0);
92 } 146 }
93 147
148 gettimeofday(&stop, NULL);
149 timersub(&stop, &start, &diff);
150
94 switch (bench_format) { 151 switch (bench_format) {
95 case BENCH_FORMAT_DEFAULT: 152 case BENCH_FORMAT_DEFAULT:
96 printf("# Executed %d pipe operations between two tasks\n\n", 153 printf("# Executed %d pipe operations between two %s\n\n",
97 loops); 154 loops, threaded ? "threads" : "processes");
98 155
99 result_usec = diff.tv_sec * 1000000; 156 result_usec = diff.tv_sec * 1000000;
100 result_usec += diff.tv_usec; 157 result_usec += diff.tv_usec;