]> rtime.felk.cvut.cz Git - can-benchmark.git/blob - hackbench.c
Merge branch 'master' of rtime.felk.cvut.cz:/can-benchmark
[can-benchmark.git] / hackbench.c
1 /* Test groups of 20 processes spraying to 20 receivers */
2 #include <stdio.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <sys/wait.h>
8 #include <sys/time.h>
9 #include <sys/poll.h>
10
11 #define DATASIZE 100
12 static unsigned int loops = 100;
13 static int use_pipes = 0;
14
15 static void barf(const char *msg)
16 {
17         fprintf(stderr, "%s (error: %s)\n", msg, strerror(errno));
18         exit(1);
19 }
20
21 static void fdpair(int fds[2])
22 {
23         if (use_pipes) {
24                 if (pipe(fds) == 0)
25                         return;
26         } else {
27                 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0)
28                         return;
29         }
30         barf("Creating fdpair");
31 }
32
33 /* Block until we're ready to go */
34 static void ready(int ready_out, int wakefd)
35 {
36         char dummy;
37         struct pollfd pollfd = { .fd = wakefd, .events = POLLIN };
38
39         /* Tell them we're ready. */
40         if (write(ready_out, &dummy, 1) != 1)
41                 barf("CLIENT: ready write");
42
43         /* Wait for "GO" signal */
44         if (poll(&pollfd, 1, -1) != 1)
45                 barf("poll");
46 }
47
48 /* Sender sprays loops messages down each file descriptor */
49 static void sender(unsigned int num_fds,
50                    int out_fd[num_fds],
51                    int ready_out,
52                    int wakefd)
53 {
54         char data[DATASIZE];
55         unsigned int i, j;
56
57         ready(ready_out, wakefd);
58
59         /* Now pump to every receiver. */
60         for (i = 0; i < loops; i++) {
61                 for (j = 0; j < num_fds; j++) {
62                         int ret, done = 0;
63
64                 again:
65                         ret = write(out_fd[j], data + done, sizeof(data)-done);
66                         if (ret < 0)
67                                 barf("SENDER: write");
68                         done += ret;
69                         if (done < sizeof(data))
70                                 goto again;
71                 }
72         }
73 }
74
75 /* One receiver per fd */
76 static void receiver(unsigned int num_packets,
77                      int in_fd,
78                      int ready_out,
79                      int wakefd)
80 {
81         unsigned int i;
82
83         /* Wait for start... */
84         ready(ready_out, wakefd);
85
86         /* Receive them all */
87         for (i = 0; i < num_packets; i++) {
88                 char data[DATASIZE];
89                 int ret, done = 0;
90
91         again:
92                 ret = read(in_fd, data + done, DATASIZE - done);
93                 if (ret < 0)
94                         barf("SERVER: read");
95                 done += ret;
96                 if (done < DATASIZE)
97                         goto again;
98         }
99 }
100
101 /* One group of senders and receivers */
102 static unsigned int group(unsigned int num_fds,
103                           int ready_out,
104                           int wakefd)
105 {
106         unsigned int i;
107         unsigned int out_fds[num_fds];
108
109         for (i = 0; i < num_fds; i++) {
110                 int fds[2];
111
112                 /* Create the pipe between client and server */
113                 fdpair(fds);
114
115                 /* Fork the receiver. */
116                 switch (fork()) {
117                 case -1: barf("fork()");
118                 case 0:
119                         close(fds[1]);
120                         receiver(num_fds*loops, fds[0], ready_out, wakefd);
121                         exit(0);
122                 }
123
124                 out_fds[i] = fds[1];
125                 close(fds[0]);
126         }
127
128         /* Now we have all the fds, fork the senders */
129         for (i = 0; i < num_fds; i++) {
130                 switch (fork()) {
131                 case -1: barf("fork()");
132                 case 0:
133                         sender(num_fds, out_fds, ready_out, wakefd);
134                         exit(0);
135                 }
136         }
137
138         /* Close the fds we have left */
139         for (i = 0; i < num_fds; i++)
140                 close(out_fds[i]);
141
142         /* Return number of children to reap */
143         return num_fds * 2;
144 }
145
146 int main(int argc, char *argv[])
147 {
148         unsigned int i, num_groups, total_children;
149         struct timeval start, stop, diff;
150         unsigned int num_fds = 20;
151         int readyfds[2], wakefds[2];
152         char dummy;
153
154         if (argv[1] && strcmp(argv[1], "-pipe") == 0) {
155                 use_pipes = 1;
156                 argc--;
157                 argv++;
158         }
159
160         if (argc != 2 || (num_groups = atoi(argv[1])) == 0)
161                 barf("Usage: hackbench [-pipe] <num groups>\n");
162
163         fdpair(readyfds);
164         fdpair(wakefds);
165
166         total_children = 0;
167         for (i = 0; i < num_groups; i++)
168                 total_children += group(num_fds, readyfds[1], wakefds[0]);
169
170         /* Wait for everyone to be ready */
171         for (i = 0; i < total_children; i++)
172                 if (read(readyfds[0], &dummy, 1) != 1)
173                         barf("Reading for readyfds");
174
175         gettimeofday(&start, NULL);
176
177         /* Kick them off */
178         if (write(wakefds[1], &dummy, 1) != 1)
179                 barf("Writing to start them");
180
181         /* Reap them all */
182         for (i = 0; i < total_children; i++) {
183                 int status;
184                 wait(&status);
185                 if (!WIFEXITED(status))
186                         exit(1);
187         }
188
189         gettimeofday(&stop, NULL);
190
191         /* Print time... */
192         timersub(&stop, &start, &diff);
193         printf("Time: %lu.%03lu\n", diff.tv_sec, diff.tv_usec/1000);
194         exit(0);
195 }