1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2c7d9300fSHitoshi Mitake /*
3c7d9300fSHitoshi Mitake *
42044279dSHitoshi Mitake * sched-pipe.c
5c7d9300fSHitoshi Mitake *
6c7d9300fSHitoshi Mitake * pipe: Benchmark for pipe()
7c7d9300fSHitoshi Mitake *
8c7d9300fSHitoshi Mitake * Based on pipe-test-1m.c by Ingo Molnar <mingo@redhat.com>
9c7d9300fSHitoshi Mitake * http://people.redhat.com/mingo/cfs-scheduler/tools/pipe-test-1m.c
10c7d9300fSHitoshi Mitake * Ported to perf by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
11c7d9300fSHitoshi Mitake */
124b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h>
13c7d9300fSHitoshi Mitake #include "bench.h"
14c7d9300fSHitoshi Mitake
15c7d9300fSHitoshi Mitake #include <unistd.h>
16c7d9300fSHitoshi Mitake #include <stdio.h>
17c7d9300fSHitoshi Mitake #include <stdlib.h>
18c7d9300fSHitoshi Mitake #include <signal.h>
19c7d9300fSHitoshi Mitake #include <sys/wait.h>
20c7d9300fSHitoshi Mitake #include <string.h>
21c7d9300fSHitoshi Mitake #include <errno.h>
22c7d9300fSHitoshi Mitake #include <assert.h>
23c7d9300fSHitoshi Mitake #include <sys/time.h>
245ff0cfc6SHitoshi Mitake #include <sys/types.h>
25ea1fe3a8SVineet Gupta #include <sys/syscall.h>
2616633ccfSArnaldo Carvalho de Melo #include <linux/time64.h>
27c7d9300fSHitoshi Mitake
28a9faa0caSIngo Molnar #include <pthread.h>
29a9faa0caSIngo Molnar
30a9faa0caSIngo Molnar struct thread_data {
31a9faa0caSIngo Molnar int nr;
32a9faa0caSIngo Molnar int pipe_read;
33a9faa0caSIngo Molnar int pipe_write;
34a9faa0caSIngo Molnar pthread_t pthread;
35a9faa0caSIngo Molnar };
36a9faa0caSIngo Molnar
37c7d9300fSHitoshi Mitake #define LOOPS_DEFAULT 1000000
38c7d9300fSHitoshi Mitake static int loops = LOOPS_DEFAULT;
39c7d9300fSHitoshi Mitake
40a9faa0caSIngo Molnar /* Use processes by default: */
41a9faa0caSIngo Molnar static bool threaded;
42a9faa0caSIngo Molnar
43c7d9300fSHitoshi Mitake static const struct option options[] = {
44a9faa0caSIngo Molnar OPT_INTEGER('l', "loop", &loops, "Specify number of loops"),
45a9faa0caSIngo Molnar OPT_BOOLEAN('T', "threaded", &threaded, "Specify threads/process based task setup"),
46c7d9300fSHitoshi Mitake OPT_END()
47c7d9300fSHitoshi Mitake };
48c7d9300fSHitoshi Mitake
49c7d9300fSHitoshi Mitake static const char * const bench_sched_pipe_usage[] = {
50c7d9300fSHitoshi Mitake "perf bench sched pipe <options>",
51c7d9300fSHitoshi Mitake NULL
52c7d9300fSHitoshi Mitake };
53c7d9300fSHitoshi Mitake
worker_thread(void * __tdata)54a9faa0caSIngo Molnar static void *worker_thread(void *__tdata)
55c7d9300fSHitoshi Mitake {
56a9faa0caSIngo Molnar struct thread_data *td = __tdata;
57c7d9300fSHitoshi Mitake int m = 0, i;
58a9faa0caSIngo Molnar int ret;
59a9faa0caSIngo Molnar
60a9faa0caSIngo Molnar for (i = 0; i < loops; i++) {
61a9faa0caSIngo Molnar if (!td->nr) {
62a9faa0caSIngo Molnar ret = read(td->pipe_read, &m, sizeof(int));
63a9faa0caSIngo Molnar BUG_ON(ret != sizeof(int));
64a9faa0caSIngo Molnar ret = write(td->pipe_write, &m, sizeof(int));
65a9faa0caSIngo Molnar BUG_ON(ret != sizeof(int));
66a9faa0caSIngo Molnar } else {
67a9faa0caSIngo Molnar ret = write(td->pipe_write, &m, sizeof(int));
68a9faa0caSIngo Molnar BUG_ON(ret != sizeof(int));
69a9faa0caSIngo Molnar ret = read(td->pipe_read, &m, sizeof(int));
70a9faa0caSIngo Molnar BUG_ON(ret != sizeof(int));
71a9faa0caSIngo Molnar }
72a9faa0caSIngo Molnar }
73a9faa0caSIngo Molnar
74a9faa0caSIngo Molnar return NULL;
75a9faa0caSIngo Molnar }
76a9faa0caSIngo Molnar
bench_sched_pipe(int argc,const char ** argv)77b0ad8ea6SArnaldo Carvalho de Melo int bench_sched_pipe(int argc, const char **argv)
78a9faa0caSIngo Molnar {
79a9faa0caSIngo Molnar struct thread_data threads[2], *td;
80a9faa0caSIngo Molnar int pipe_1[2], pipe_2[2];
81c7d9300fSHitoshi Mitake struct timeval start, stop, diff;
82c7d9300fSHitoshi Mitake unsigned long long result_usec = 0;
83a9faa0caSIngo Molnar int nr_threads = 2;
84a9faa0caSIngo Molnar int t;
85c7d9300fSHitoshi Mitake
86c7d9300fSHitoshi Mitake /*
87c7d9300fSHitoshi Mitake * why does "ret" exist?
88c7d9300fSHitoshi Mitake * discarding returned value of read(), write()
89c7d9300fSHitoshi Mitake * causes error in building environment for perf
90c7d9300fSHitoshi Mitake */
911d037ca1SIrina Tirdea int __maybe_unused ret, wait_stat;
921d037ca1SIrina Tirdea pid_t pid, retpid __maybe_unused;
93c7d9300fSHitoshi Mitake
94a9faa0caSIngo Molnar argc = parse_options(argc, argv, options, bench_sched_pipe_usage, 0);
95c7d9300fSHitoshi Mitake
968bf98b89SIrina Tirdea BUG_ON(pipe(pipe_1));
978bf98b89SIrina Tirdea BUG_ON(pipe(pipe_2));
98c7d9300fSHitoshi Mitake
99a9faa0caSIngo Molnar gettimeofday(&start, NULL);
100a9faa0caSIngo Molnar
101a9faa0caSIngo Molnar for (t = 0; t < nr_threads; t++) {
102a9faa0caSIngo Molnar td = threads + t;
103a9faa0caSIngo Molnar
104a9faa0caSIngo Molnar td->nr = t;
105a9faa0caSIngo Molnar
106a9faa0caSIngo Molnar if (t == 0) {
107a9faa0caSIngo Molnar td->pipe_read = pipe_1[0];
108a9faa0caSIngo Molnar td->pipe_write = pipe_2[1];
109a9faa0caSIngo Molnar } else {
110a9faa0caSIngo Molnar td->pipe_write = pipe_1[1];
111a9faa0caSIngo Molnar td->pipe_read = pipe_2[0];
112a9faa0caSIngo Molnar }
113a9faa0caSIngo Molnar }
114a9faa0caSIngo Molnar
115a9faa0caSIngo Molnar
116a9faa0caSIngo Molnar if (threaded) {
117a9faa0caSIngo Molnar
118a9faa0caSIngo Molnar for (t = 0; t < nr_threads; t++) {
119a9faa0caSIngo Molnar td = threads + t;
120a9faa0caSIngo Molnar
121a9faa0caSIngo Molnar ret = pthread_create(&td->pthread, NULL, worker_thread, td);
122a9faa0caSIngo Molnar BUG_ON(ret);
123a9faa0caSIngo Molnar }
124a9faa0caSIngo Molnar
125a9faa0caSIngo Molnar for (t = 0; t < nr_threads; t++) {
126a9faa0caSIngo Molnar td = threads + t;
127a9faa0caSIngo Molnar
128a9faa0caSIngo Molnar ret = pthread_join(td->pthread, NULL);
129a9faa0caSIngo Molnar BUG_ON(ret);
130a9faa0caSIngo Molnar }
131a9faa0caSIngo Molnar
132a9faa0caSIngo Molnar } else {
133c7d9300fSHitoshi Mitake pid = fork();
134c7d9300fSHitoshi Mitake assert(pid >= 0);
135c7d9300fSHitoshi Mitake
136c7d9300fSHitoshi Mitake if (!pid) {
137a9faa0caSIngo Molnar worker_thread(threads + 0);
138a9faa0caSIngo Molnar exit(0);
139c7d9300fSHitoshi Mitake } else {
140a9faa0caSIngo Molnar worker_thread(threads + 1);
141c7d9300fSHitoshi Mitake }
142a9faa0caSIngo Molnar
143a9faa0caSIngo Molnar retpid = waitpid(pid, &wait_stat, 0);
144a9faa0caSIngo Molnar assert((retpid == pid) && WIFEXITED(wait_stat));
145c7d9300fSHitoshi Mitake }
146c7d9300fSHitoshi Mitake
147c7d9300fSHitoshi Mitake gettimeofday(&stop, NULL);
148c7d9300fSHitoshi Mitake timersub(&stop, &start, &diff);
149c7d9300fSHitoshi Mitake
150158ba827SHitoshi Mitake switch (bench_format) {
151158ba827SHitoshi Mitake case BENCH_FORMAT_DEFAULT:
152a9faa0caSIngo Molnar printf("# Executed %d pipe operations between two %s\n\n",
153a9faa0caSIngo Molnar loops, threaded ? "threads" : "processes");
154c7d9300fSHitoshi Mitake
15516633ccfSArnaldo Carvalho de Melo result_usec = diff.tv_sec * USEC_PER_SEC;
156c7d9300fSHitoshi Mitake result_usec += diff.tv_usec;
157c7d9300fSHitoshi Mitake
158ff676b19SHitoshi Mitake printf(" %14s: %lu.%03lu [sec]\n\n", "Total time",
159*ded2e511SPierre Gondois (unsigned long) diff.tv_sec,
16016633ccfSArnaldo Carvalho de Melo (unsigned long) (diff.tv_usec / USEC_PER_MSEC));
161ff676b19SHitoshi Mitake
162ff676b19SHitoshi Mitake printf(" %14lf usecs/op\n",
163c7d9300fSHitoshi Mitake (double)result_usec / (double)loops);
164ff676b19SHitoshi Mitake printf(" %14d ops/sec\n",
165c7d9300fSHitoshi Mitake (int)((double)loops /
16616633ccfSArnaldo Carvalho de Melo ((double)result_usec / (double)USEC_PER_SEC)));
167158ba827SHitoshi Mitake break;
168158ba827SHitoshi Mitake
169158ba827SHitoshi Mitake case BENCH_FORMAT_SIMPLE:
170158ba827SHitoshi Mitake printf("%lu.%03lu\n",
171*ded2e511SPierre Gondois (unsigned long) diff.tv_sec,
17216633ccfSArnaldo Carvalho de Melo (unsigned long) (diff.tv_usec / USEC_PER_MSEC));
173158ba827SHitoshi Mitake break;
174158ba827SHitoshi Mitake
175158ba827SHitoshi Mitake default:
176158ba827SHitoshi Mitake /* reaching here is something disaster */
177158ba827SHitoshi Mitake fprintf(stderr, "Unknown format:%d\n", bench_format);
178158ba827SHitoshi Mitake exit(1);
179158ba827SHitoshi Mitake break;
180c7d9300fSHitoshi Mitake }
181c7d9300fSHitoshi Mitake
182c7d9300fSHitoshi Mitake return 0;
183c7d9300fSHitoshi Mitake }
184