xref: /dragonfly/test/interbench/hackbench.c (revision 678e8cc6)
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