diff options
Diffstat (limited to 'tools/perf/bench/sched-pipe.c')
-rw-r--r-- | tools/perf/bench/sched-pipe.c | 115 |
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 | |||
31 | struct 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 |
32 | static int loops = LOOPS_DEFAULT; | 39 | static int loops = LOOPS_DEFAULT; |
40 | |||
41 | /* Use processes by default: */ | ||
42 | static bool threaded; | ||
33 | 43 | ||
34 | static const struct option options[] = { | 44 | static 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 | ||
45 | int bench_sched_pipe(int argc, const char **argv, | 55 | static 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 | |||
78 | int 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; |