1f45d86eaSAlex Hornung /* Test groups of 20 processes spraying to 20 receivers */
2f45d86eaSAlex Hornung #include <stdio.h>
3f45d86eaSAlex Hornung #include <string.h>
4f45d86eaSAlex Hornung #include <errno.h>
5f45d86eaSAlex Hornung #include <unistd.h>
6f45d86eaSAlex Hornung #include <stdlib.h>
7f45d86eaSAlex Hornung #include <semaphore.h>
8f45d86eaSAlex Hornung #include <sys/types.h>
9f45d86eaSAlex Hornung #include <sys/socket.h>
10f45d86eaSAlex Hornung #include <sys/wait.h>
11f45d86eaSAlex Hornung #include <sys/time.h>
12f45d86eaSAlex Hornung #include <sys/poll.h>
13f45d86eaSAlex Hornung #include "interbench.h"
14f45d86eaSAlex Hornung
15f45d86eaSAlex Hornung #define DATASIZE 100
16f45d86eaSAlex Hornung #define LOOPS 100
17f45d86eaSAlex Hornung #define NUM_FDS 20
18f45d86eaSAlex Hornung
barf(const char * msg)19f45d86eaSAlex Hornung static inline void barf(const char *msg)
20f45d86eaSAlex Hornung {
21f45d86eaSAlex Hornung terminal_error(msg);
22f45d86eaSAlex Hornung }
23f45d86eaSAlex Hornung
fdpair(int fds[2])24f45d86eaSAlex Hornung static void fdpair(int fds[2])
25f45d86eaSAlex Hornung {
26f45d86eaSAlex Hornung if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1)
27f45d86eaSAlex Hornung barf("Creating fdpair");
28f45d86eaSAlex Hornung }
29f45d86eaSAlex Hornung
30f45d86eaSAlex Hornung /* Block until we're ready to go */
ready(int ready_out,int wakefd)31f45d86eaSAlex Hornung static void ready(int ready_out, int wakefd)
32f45d86eaSAlex Hornung {
33f45d86eaSAlex Hornung char dummy;
34f45d86eaSAlex Hornung struct pollfd pollfd = { .fd = wakefd, .events = POLLIN };
35f45d86eaSAlex Hornung
36f45d86eaSAlex Hornung /* Tell them we're ready. */
37f45d86eaSAlex Hornung if (write(ready_out, &dummy, 1) != 1)
38f45d86eaSAlex Hornung barf("CLIENT: ready write");
39f45d86eaSAlex Hornung
40f45d86eaSAlex Hornung /* Wait for "GO" signal */
41f45d86eaSAlex Hornung if (poll(&pollfd, 1, -1) != 1)
42f45d86eaSAlex Hornung barf("poll");
43f45d86eaSAlex Hornung }
44f45d86eaSAlex Hornung
45f45d86eaSAlex Hornung /* Sender sprays LOOPS messages down each file descriptor */
sender(int out_fd[NUM_FDS],int ready_out,int wakefd)46f45d86eaSAlex Hornung static void sender(int out_fd[NUM_FDS],
47f45d86eaSAlex Hornung int ready_out,
48f45d86eaSAlex Hornung int wakefd)
49f45d86eaSAlex Hornung {
50f45d86eaSAlex Hornung char data[DATASIZE];
51f45d86eaSAlex Hornung unsigned int i, j;
52f45d86eaSAlex Hornung
53f45d86eaSAlex Hornung ready(ready_out, wakefd);
54f45d86eaSAlex Hornung
55f45d86eaSAlex Hornung /* Now pump to every receiver. */
56f45d86eaSAlex Hornung for (i = 0; i < LOOPS; i++) {
57f45d86eaSAlex Hornung for (j = 0; j < NUM_FDS; j++) {
58f45d86eaSAlex Hornung int ret;
59f45d86eaSAlex Hornung unsigned long done = 0;
60f45d86eaSAlex Hornung
61f45d86eaSAlex Hornung again:
62f45d86eaSAlex Hornung ret = write(out_fd[j], data + done, sizeof(data)-done);
63f45d86eaSAlex Hornung if (ret < 0)
64f45d86eaSAlex Hornung barf("SENDER: write");
65f45d86eaSAlex Hornung done += ret;
66f45d86eaSAlex Hornung if (done < sizeof(data))
67f45d86eaSAlex Hornung goto again;
68f45d86eaSAlex Hornung }
69f45d86eaSAlex Hornung }
70f45d86eaSAlex Hornung }
71f45d86eaSAlex Hornung
72f45d86eaSAlex Hornung /* One receiver per fd */
receiver(unsigned int num_packets,int in_fd,int ready_out,int wakefd)73f45d86eaSAlex Hornung static void receiver(unsigned int num_packets,
74f45d86eaSAlex Hornung int in_fd,
75f45d86eaSAlex Hornung int ready_out,
76f45d86eaSAlex Hornung int wakefd)
77f45d86eaSAlex Hornung {
78f45d86eaSAlex Hornung unsigned int i;
79f45d86eaSAlex Hornung
80f45d86eaSAlex Hornung /* Wait for start... */
81f45d86eaSAlex Hornung ready(ready_out, wakefd);
82f45d86eaSAlex Hornung
83f45d86eaSAlex Hornung /* Receive them all */
84f45d86eaSAlex Hornung for (i = 0; i < num_packets; i++) {
85f45d86eaSAlex Hornung char data[DATASIZE];
86f45d86eaSAlex Hornung int ret, done = 0;
87f45d86eaSAlex Hornung
88f45d86eaSAlex Hornung again:
89f45d86eaSAlex Hornung ret = Read(in_fd, data + done, DATASIZE - done);
90f45d86eaSAlex Hornung done += ret;
91f45d86eaSAlex Hornung if (done < DATASIZE)
92f45d86eaSAlex Hornung goto again;
93f45d86eaSAlex Hornung }
94f45d86eaSAlex Hornung }
95f45d86eaSAlex Hornung
96f45d86eaSAlex Hornung /* One group of senders and receivers */
group(int ready_out,int wakefd)97f45d86eaSAlex Hornung static unsigned int group(int ready_out,
98f45d86eaSAlex Hornung int wakefd)
99f45d86eaSAlex Hornung {
100f45d86eaSAlex Hornung unsigned int i;
101f45d86eaSAlex Hornung int out_fds[NUM_FDS];
102f45d86eaSAlex Hornung
103f45d86eaSAlex Hornung for (i = 0; i < NUM_FDS; i++) {
104f45d86eaSAlex Hornung int fds[2];
105f45d86eaSAlex Hornung
106f45d86eaSAlex Hornung /* Create the pipe between client and server */
107f45d86eaSAlex Hornung fdpair(fds);
108f45d86eaSAlex Hornung
109f45d86eaSAlex Hornung /* Fork the receiver. */
110f45d86eaSAlex Hornung switch (fork()) {
111f45d86eaSAlex Hornung case -1: barf("fork()");
112f45d86eaSAlex Hornung case 0:
113f45d86eaSAlex Hornung close(fds[1]);
114f45d86eaSAlex Hornung receiver(NUM_FDS*LOOPS, fds[0], ready_out, wakefd);
115f45d86eaSAlex Hornung exit(0);
116f45d86eaSAlex Hornung }
117f45d86eaSAlex Hornung
118f45d86eaSAlex Hornung out_fds[i] = fds[1];
119f45d86eaSAlex Hornung close(fds[0]);
120f45d86eaSAlex Hornung }
121f45d86eaSAlex Hornung
122f45d86eaSAlex Hornung /* Now we have all the fds, fork the senders */
123f45d86eaSAlex Hornung for (i = 0; i < NUM_FDS; i++) {
124f45d86eaSAlex Hornung switch (fork()) {
125f45d86eaSAlex Hornung case -1: barf("fork()");
126f45d86eaSAlex Hornung case 0:
127f45d86eaSAlex Hornung sender(out_fds, ready_out, wakefd);
128f45d86eaSAlex Hornung exit(0);
129f45d86eaSAlex Hornung }
130f45d86eaSAlex Hornung }
131f45d86eaSAlex Hornung
132f45d86eaSAlex Hornung /* Close the fds we have left */
133f45d86eaSAlex Hornung for (i = 0; i < NUM_FDS; i++)
134f45d86eaSAlex Hornung close(out_fds[i]);
135f45d86eaSAlex Hornung
136f45d86eaSAlex Hornung /* Return number of children to reap */
137f45d86eaSAlex Hornung return NUM_FDS * 2;
138f45d86eaSAlex Hornung }
139f45d86eaSAlex Hornung
hackbench_thread(void * t)140f45d86eaSAlex Hornung void *hackbench_thread(void *t)
141f45d86eaSAlex Hornung {
142f45d86eaSAlex Hornung unsigned int i, num_groups, total_children;
143f45d86eaSAlex Hornung int readyfds[2], wakefds[2];
144f45d86eaSAlex Hornung char dummy;
145f45d86eaSAlex Hornung
146f45d86eaSAlex Hornung num_groups = 50;
147*678e8cc6SSascha Wildner t = NULL;
148f45d86eaSAlex Hornung
149f45d86eaSAlex Hornung fdpair(readyfds);
150f45d86eaSAlex Hornung fdpair(wakefds);
151f45d86eaSAlex Hornung
152f45d86eaSAlex Hornung while (1) {
153f45d86eaSAlex Hornung total_children = 0;
154f45d86eaSAlex Hornung for (i = 0; i < num_groups; i++)
155f45d86eaSAlex Hornung total_children += group(readyfds[1], wakefds[0]);
156f45d86eaSAlex Hornung
157f45d86eaSAlex Hornung /* Wait for everyone to be ready */
158f45d86eaSAlex Hornung for (i = 0; i < total_children; i++)
159f45d86eaSAlex Hornung if (Read(readyfds[0], &dummy, 1) != 1)
160f45d86eaSAlex Hornung barf("Reading for readyfds");
161f45d86eaSAlex Hornung
162f45d86eaSAlex Hornung /* Kick them off */
163f45d86eaSAlex Hornung if (write(wakefds[1], &dummy, 1) != 1)
164f45d86eaSAlex Hornung barf("Writing to start them");
165f45d86eaSAlex Hornung
166f45d86eaSAlex Hornung /* Reap them all */
167f45d86eaSAlex Hornung for (i = 0; i < total_children; i++) {
168f45d86eaSAlex Hornung int status;
169f45d86eaSAlex Hornung wait(&status);
170f45d86eaSAlex Hornung if (!WIFEXITED(status))
171f45d86eaSAlex Hornung exit(1);
172f45d86eaSAlex Hornung }
173f45d86eaSAlex Hornung if (!trywait_sem(&hackthread.sem.stop))
174f45d86eaSAlex Hornung break;
175f45d86eaSAlex Hornung }
176f45d86eaSAlex Hornung
177f45d86eaSAlex Hornung post_sem(&hackthread.sem.complete);
178f45d86eaSAlex Hornung return NULL;
179f45d86eaSAlex Hornung }
180