xref: /aosp_15_r20/external/ltp/testcases/kernel/sched/cfs-scheduler/hackbench.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
2*49cdfc7eSAndroid Build Coastguard Worker /* Copyright Rusty Russell,                                                   */
3*49cdfc7eSAndroid Build Coastguard Worker /* Copyright Pierre Peiffer                                                   */
4*49cdfc7eSAndroid Build Coastguard Worker /* Copyright Zhang, Yanmin,                                                   */
5*49cdfc7eSAndroid Build Coastguard Worker /* Copyright Ingo Molnar,                                                     */
6*49cdfc7eSAndroid Build Coastguard Worker /* Copyright Arjan van de Ven,                                                */
7*49cdfc7eSAndroid Build Coastguard Worker /* Copyright (c) International Business Machines  Corp., 2008                 */
8*49cdfc7eSAndroid Build Coastguard Worker /*                                                                            */
9*49cdfc7eSAndroid Build Coastguard Worker /* This program is free software;  you can redistribute it and/or modify      */
10*49cdfc7eSAndroid Build Coastguard Worker /* it under the terms of the GNU General Public License as published by       */
11*49cdfc7eSAndroid Build Coastguard Worker /* the Free Software Foundation; either version 2 of the License, or          */
12*49cdfc7eSAndroid Build Coastguard Worker /* (at your option) any later version.                                        */
13*49cdfc7eSAndroid Build Coastguard Worker /*                                                                            */
14*49cdfc7eSAndroid Build Coastguard Worker /* This program is distributed in the hope that it will be useful,            */
15*49cdfc7eSAndroid Build Coastguard Worker /* but WITHOUT ANY WARRANTY;  without even the implied warranty of            */
16*49cdfc7eSAndroid Build Coastguard Worker /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See                  */
17*49cdfc7eSAndroid Build Coastguard Worker /* the GNU General Public License for more details.                           */
18*49cdfc7eSAndroid Build Coastguard Worker /*                                                                            */
19*49cdfc7eSAndroid Build Coastguard Worker /* You should have received a copy of the GNU General Public License          */
20*49cdfc7eSAndroid Build Coastguard Worker /* along with this program;  if not, write to the Free Software               */
21*49cdfc7eSAndroid Build Coastguard Worker /* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA    */
22*49cdfc7eSAndroid Build Coastguard Worker /*                                                                            */
23*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
24*49cdfc7eSAndroid Build Coastguard Worker 
25*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
26*49cdfc7eSAndroid Build Coastguard Worker /*                                                                            */
27*49cdfc7eSAndroid Build Coastguard Worker /* File:        hackbench.c                                                   */
28*49cdfc7eSAndroid Build Coastguard Worker /*                                                                            */
29*49cdfc7eSAndroid Build Coastguard Worker /* Description: hackbench tests the Linux scheduler. Test groups of 20        */
30*49cdfc7eSAndroid Build Coastguard Worker /*              processes spraying to 20 receivers                            */
31*49cdfc7eSAndroid Build Coastguard Worker /*                                                                            */
32*49cdfc7eSAndroid Build Coastguard Worker /* Total Tests: 1                                                             */
33*49cdfc7eSAndroid Build Coastguard Worker /*                                                                            */
34*49cdfc7eSAndroid Build Coastguard Worker /* Test Name:   hackbench01 and hackbench02                                   */
35*49cdfc7eSAndroid Build Coastguard Worker /*                                                                            */
36*49cdfc7eSAndroid Build Coastguard Worker /* Test Assertion:                                                            */
37*49cdfc7eSAndroid Build Coastguard Worker /*                                                                            */
38*49cdfc7eSAndroid Build Coastguard Worker /* Author(s):   Rusty Russell <[email protected]>,                        */
39*49cdfc7eSAndroid Build Coastguard Worker /*              Pierre Peiffer <[email protected]>,                     */
40*49cdfc7eSAndroid Build Coastguard Worker /*              Ingo Molnar <[email protected]>,                                  */
41*49cdfc7eSAndroid Build Coastguard Worker /*              Arjan van de Ven <[email protected]>,                       */
42*49cdfc7eSAndroid Build Coastguard Worker /*              "Zhang, Yanmin" <[email protected]>,               */
43*49cdfc7eSAndroid Build Coastguard Worker /*              Nathan Lynch <[email protected]>                                  */
44*49cdfc7eSAndroid Build Coastguard Worker /*                                                                            */
45*49cdfc7eSAndroid Build Coastguard Worker /* History:     Included into LTP                                             */
46*49cdfc7eSAndroid Build Coastguard Worker /*                  - June 26 2008 - Subrata Modak<[email protected]>*/
47*49cdfc7eSAndroid Build Coastguard Worker /*                                                                            */
48*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************/
49*49cdfc7eSAndroid Build Coastguard Worker #include <pthread.h>
50*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
51*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
52*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
53*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
54*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
55*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
56*49cdfc7eSAndroid Build Coastguard Worker #include <sys/socket.h>
57*49cdfc7eSAndroid Build Coastguard Worker #include <sys/wait.h>
58*49cdfc7eSAndroid Build Coastguard Worker #include <sys/time.h>
59*49cdfc7eSAndroid Build Coastguard Worker #include <sys/poll.h>
60*49cdfc7eSAndroid Build Coastguard Worker #include <limits.h>
61*49cdfc7eSAndroid Build Coastguard Worker 
62*49cdfc7eSAndroid Build Coastguard Worker #define SAFE_FREE(p) { if (p) { free(p); (p)=NULL; } }
63*49cdfc7eSAndroid Build Coastguard Worker #define DATASIZE 100
64*49cdfc7eSAndroid Build Coastguard Worker static struct sender_context **snd_ctx_tab;	/*Table for sender context pointers. */
65*49cdfc7eSAndroid Build Coastguard Worker static struct receiver_context **rev_ctx_tab;	/*Table for receiver context pointers. */
66*49cdfc7eSAndroid Build Coastguard Worker static int gr_num = 0;		/*For group calculation */
67*49cdfc7eSAndroid Build Coastguard Worker static unsigned int loops = 100;
68*49cdfc7eSAndroid Build Coastguard Worker /*
69*49cdfc7eSAndroid Build Coastguard Worker  * 0 means thread mode and others mean process (default)
70*49cdfc7eSAndroid Build Coastguard Worker  */
71*49cdfc7eSAndroid Build Coastguard Worker static unsigned int process_mode = 1;
72*49cdfc7eSAndroid Build Coastguard Worker 
73*49cdfc7eSAndroid Build Coastguard Worker static int use_pipes = 0;
74*49cdfc7eSAndroid Build Coastguard Worker 
75*49cdfc7eSAndroid Build Coastguard Worker struct sender_context {
76*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int num_fds;
77*49cdfc7eSAndroid Build Coastguard Worker 	int ready_out;
78*49cdfc7eSAndroid Build Coastguard Worker 	int wakefd;
79*49cdfc7eSAndroid Build Coastguard Worker 	int out_fds[0];
80*49cdfc7eSAndroid Build Coastguard Worker };
81*49cdfc7eSAndroid Build Coastguard Worker 
82*49cdfc7eSAndroid Build Coastguard Worker struct receiver_context {
83*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int num_packets;
84*49cdfc7eSAndroid Build Coastguard Worker 	int in_fds[2];
85*49cdfc7eSAndroid Build Coastguard Worker 	int ready_out;
86*49cdfc7eSAndroid Build Coastguard Worker 	int wakefd;
87*49cdfc7eSAndroid Build Coastguard Worker };
88*49cdfc7eSAndroid Build Coastguard Worker 
barf(const char * msg)89*49cdfc7eSAndroid Build Coastguard Worker static void barf(const char *msg)
90*49cdfc7eSAndroid Build Coastguard Worker {
91*49cdfc7eSAndroid Build Coastguard Worker 	fprintf(stderr, "%s (error: %s)\n", msg, strerror(errno));
92*49cdfc7eSAndroid Build Coastguard Worker 	exit(1);
93*49cdfc7eSAndroid Build Coastguard Worker }
94*49cdfc7eSAndroid Build Coastguard Worker 
print_usage_exit(void)95*49cdfc7eSAndroid Build Coastguard Worker static void print_usage_exit(void)
96*49cdfc7eSAndroid Build Coastguard Worker {
97*49cdfc7eSAndroid Build Coastguard Worker 	printf
98*49cdfc7eSAndroid Build Coastguard Worker 	    ("Usage: hackbench [-pipe] <num groups> [process|thread] [loops]\n");
99*49cdfc7eSAndroid Build Coastguard Worker 	exit(1);
100*49cdfc7eSAndroid Build Coastguard Worker }
101*49cdfc7eSAndroid Build Coastguard Worker 
fdpair(int fds[2])102*49cdfc7eSAndroid Build Coastguard Worker static void fdpair(int fds[2])
103*49cdfc7eSAndroid Build Coastguard Worker {
104*49cdfc7eSAndroid Build Coastguard Worker 	if (use_pipes) {
105*49cdfc7eSAndroid Build Coastguard Worker 		if (pipe(fds) == 0)
106*49cdfc7eSAndroid Build Coastguard Worker 			return;
107*49cdfc7eSAndroid Build Coastguard Worker 	} else {
108*49cdfc7eSAndroid Build Coastguard Worker 		if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0)
109*49cdfc7eSAndroid Build Coastguard Worker 			return;
110*49cdfc7eSAndroid Build Coastguard Worker 	}
111*49cdfc7eSAndroid Build Coastguard Worker 	barf("Creating fdpair");
112*49cdfc7eSAndroid Build Coastguard Worker }
113*49cdfc7eSAndroid Build Coastguard Worker 
114*49cdfc7eSAndroid Build Coastguard Worker /* Block until we're ready to go */
ready(int ready_out,int wakefd)115*49cdfc7eSAndroid Build Coastguard Worker static void ready(int ready_out, int wakefd)
116*49cdfc7eSAndroid Build Coastguard Worker {
117*49cdfc7eSAndroid Build Coastguard Worker 	char dummy;
118*49cdfc7eSAndroid Build Coastguard Worker 	struct pollfd pollfd = {.fd = wakefd,.events = POLLIN };
119*49cdfc7eSAndroid Build Coastguard Worker 
120*49cdfc7eSAndroid Build Coastguard Worker 	/* Tell them we're ready. */
121*49cdfc7eSAndroid Build Coastguard Worker 	if (write(ready_out, &dummy, 1) != 1)
122*49cdfc7eSAndroid Build Coastguard Worker 		barf("CLIENT: ready write");
123*49cdfc7eSAndroid Build Coastguard Worker 
124*49cdfc7eSAndroid Build Coastguard Worker 	/* Wait for "GO" signal */
125*49cdfc7eSAndroid Build Coastguard Worker 	if (poll(&pollfd, 1, -1) != 1)
126*49cdfc7eSAndroid Build Coastguard Worker 		barf("poll");
127*49cdfc7eSAndroid Build Coastguard Worker }
128*49cdfc7eSAndroid Build Coastguard Worker 
129*49cdfc7eSAndroid Build Coastguard Worker /* Sender sprays loops messages down each file descriptor */
sender(struct sender_context * ctx)130*49cdfc7eSAndroid Build Coastguard Worker static void *sender(struct sender_context *ctx)
131*49cdfc7eSAndroid Build Coastguard Worker {
132*49cdfc7eSAndroid Build Coastguard Worker 	char data[DATASIZE];
133*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int i, j;
134*49cdfc7eSAndroid Build Coastguard Worker 
135*49cdfc7eSAndroid Build Coastguard Worker 	ready(ctx->ready_out, ctx->wakefd);
136*49cdfc7eSAndroid Build Coastguard Worker 
137*49cdfc7eSAndroid Build Coastguard Worker 	/* Now pump to every receiver. */
138*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < loops; i++) {
139*49cdfc7eSAndroid Build Coastguard Worker 		for (j = 0; j < ctx->num_fds; j++) {
140*49cdfc7eSAndroid Build Coastguard Worker 			int ret, done = 0;
141*49cdfc7eSAndroid Build Coastguard Worker 
142*49cdfc7eSAndroid Build Coastguard Worker again:
143*49cdfc7eSAndroid Build Coastguard Worker 			ret =
144*49cdfc7eSAndroid Build Coastguard Worker 			    write(ctx->out_fds[j], data + done,
145*49cdfc7eSAndroid Build Coastguard Worker 				  sizeof(data) - done);
146*49cdfc7eSAndroid Build Coastguard Worker 			if (ret < 0)
147*49cdfc7eSAndroid Build Coastguard Worker 				barf("SENDER: write");
148*49cdfc7eSAndroid Build Coastguard Worker 			done += ret;
149*49cdfc7eSAndroid Build Coastguard Worker 			if (done < sizeof(data))
150*49cdfc7eSAndroid Build Coastguard Worker 				goto again;
151*49cdfc7eSAndroid Build Coastguard Worker 		}
152*49cdfc7eSAndroid Build Coastguard Worker 	}
153*49cdfc7eSAndroid Build Coastguard Worker 
154*49cdfc7eSAndroid Build Coastguard Worker 	return NULL;
155*49cdfc7eSAndroid Build Coastguard Worker }
156*49cdfc7eSAndroid Build Coastguard Worker 
157*49cdfc7eSAndroid Build Coastguard Worker /* One receiver per fd */
receiver(struct receiver_context * ctx)158*49cdfc7eSAndroid Build Coastguard Worker static void *receiver(struct receiver_context *ctx)
159*49cdfc7eSAndroid Build Coastguard Worker {
160*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int i;
161*49cdfc7eSAndroid Build Coastguard Worker 
162*49cdfc7eSAndroid Build Coastguard Worker 	if (process_mode)
163*49cdfc7eSAndroid Build Coastguard Worker 		close(ctx->in_fds[1]);
164*49cdfc7eSAndroid Build Coastguard Worker 
165*49cdfc7eSAndroid Build Coastguard Worker 	/* Wait for start... */
166*49cdfc7eSAndroid Build Coastguard Worker 	ready(ctx->ready_out, ctx->wakefd);
167*49cdfc7eSAndroid Build Coastguard Worker 
168*49cdfc7eSAndroid Build Coastguard Worker 	/* Receive them all */
169*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < ctx->num_packets; i++) {
170*49cdfc7eSAndroid Build Coastguard Worker 		char data[DATASIZE];
171*49cdfc7eSAndroid Build Coastguard Worker 		int ret, done = 0;
172*49cdfc7eSAndroid Build Coastguard Worker 
173*49cdfc7eSAndroid Build Coastguard Worker again:
174*49cdfc7eSAndroid Build Coastguard Worker 		ret = read(ctx->in_fds[0], data + done, DATASIZE - done);
175*49cdfc7eSAndroid Build Coastguard Worker 		if (ret < 0)
176*49cdfc7eSAndroid Build Coastguard Worker 			barf("SERVER: read");
177*49cdfc7eSAndroid Build Coastguard Worker 		done += ret;
178*49cdfc7eSAndroid Build Coastguard Worker 		if (done < DATASIZE)
179*49cdfc7eSAndroid Build Coastguard Worker 			goto again;
180*49cdfc7eSAndroid Build Coastguard Worker 	}
181*49cdfc7eSAndroid Build Coastguard Worker 
182*49cdfc7eSAndroid Build Coastguard Worker 	return NULL;
183*49cdfc7eSAndroid Build Coastguard Worker }
184*49cdfc7eSAndroid Build Coastguard Worker 
create_worker(void * ctx,void * (* func)(void *))185*49cdfc7eSAndroid Build Coastguard Worker pthread_t create_worker(void *ctx, void *(*func) (void *))
186*49cdfc7eSAndroid Build Coastguard Worker {
187*49cdfc7eSAndroid Build Coastguard Worker 	pthread_attr_t attr;
188*49cdfc7eSAndroid Build Coastguard Worker 	pthread_t childid;
189*49cdfc7eSAndroid Build Coastguard Worker 	int err;
190*49cdfc7eSAndroid Build Coastguard Worker 
191*49cdfc7eSAndroid Build Coastguard Worker 	if (process_mode) {
192*49cdfc7eSAndroid Build Coastguard Worker 		/* process mode */
193*49cdfc7eSAndroid Build Coastguard Worker 		/* Fork the receiver. */
194*49cdfc7eSAndroid Build Coastguard Worker 		switch (fork()) {
195*49cdfc7eSAndroid Build Coastguard Worker 		case -1:
196*49cdfc7eSAndroid Build Coastguard Worker 			barf("fork()");
197*49cdfc7eSAndroid Build Coastguard Worker 		case 0:
198*49cdfc7eSAndroid Build Coastguard Worker 			(*func) (ctx);
199*49cdfc7eSAndroid Build Coastguard Worker 			exit(0);
200*49cdfc7eSAndroid Build Coastguard Worker 		}
201*49cdfc7eSAndroid Build Coastguard Worker 
202*49cdfc7eSAndroid Build Coastguard Worker 		return (pthread_t) 0;
203*49cdfc7eSAndroid Build Coastguard Worker 	}
204*49cdfc7eSAndroid Build Coastguard Worker 
205*49cdfc7eSAndroid Build Coastguard Worker 	if (pthread_attr_init(&attr) != 0)
206*49cdfc7eSAndroid Build Coastguard Worker 		barf("pthread_attr_init:");
207*49cdfc7eSAndroid Build Coastguard Worker 
208*49cdfc7eSAndroid Build Coastguard Worker #ifndef __ia64__
209*49cdfc7eSAndroid Build Coastguard Worker 	if (pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN) != 0)
210*49cdfc7eSAndroid Build Coastguard Worker 		barf("pthread_attr_setstacksize");
211*49cdfc7eSAndroid Build Coastguard Worker #endif
212*49cdfc7eSAndroid Build Coastguard Worker 
213*49cdfc7eSAndroid Build Coastguard Worker 	if ((err = pthread_create(&childid, &attr, func, ctx)) != 0) {
214*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "pthread_create failed: %s (%d)\n",
215*49cdfc7eSAndroid Build Coastguard Worker 			strerror(err), err);
216*49cdfc7eSAndroid Build Coastguard Worker 		exit(-1);
217*49cdfc7eSAndroid Build Coastguard Worker 	}
218*49cdfc7eSAndroid Build Coastguard Worker 	return (childid);
219*49cdfc7eSAndroid Build Coastguard Worker }
220*49cdfc7eSAndroid Build Coastguard Worker 
reap_worker(pthread_t id)221*49cdfc7eSAndroid Build Coastguard Worker void reap_worker(pthread_t id)
222*49cdfc7eSAndroid Build Coastguard Worker {
223*49cdfc7eSAndroid Build Coastguard Worker 	int status;
224*49cdfc7eSAndroid Build Coastguard Worker 
225*49cdfc7eSAndroid Build Coastguard Worker 	if (process_mode) {
226*49cdfc7eSAndroid Build Coastguard Worker 		/* process mode */
227*49cdfc7eSAndroid Build Coastguard Worker 		wait(&status);
228*49cdfc7eSAndroid Build Coastguard Worker 		if (!WIFEXITED(status))
229*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);
230*49cdfc7eSAndroid Build Coastguard Worker 	} else {
231*49cdfc7eSAndroid Build Coastguard Worker 		void *status;
232*49cdfc7eSAndroid Build Coastguard Worker 
233*49cdfc7eSAndroid Build Coastguard Worker 		pthread_join(id, &status);
234*49cdfc7eSAndroid Build Coastguard Worker 	}
235*49cdfc7eSAndroid Build Coastguard Worker }
236*49cdfc7eSAndroid Build Coastguard Worker 
237*49cdfc7eSAndroid Build Coastguard Worker /* One group of senders and receivers */
group(pthread_t * pth,unsigned int num_fds,int ready_out,int wakefd)238*49cdfc7eSAndroid Build Coastguard Worker static unsigned int group(pthread_t * pth,
239*49cdfc7eSAndroid Build Coastguard Worker 			  unsigned int num_fds, int ready_out, int wakefd)
240*49cdfc7eSAndroid Build Coastguard Worker {
241*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int i;
242*49cdfc7eSAndroid Build Coastguard Worker 	struct sender_context *snd_ctx = malloc(sizeof(struct sender_context) + num_fds * sizeof(int));
243*49cdfc7eSAndroid Build Coastguard Worker 	if (!snd_ctx)
244*49cdfc7eSAndroid Build Coastguard Worker 		barf("malloc()");
245*49cdfc7eSAndroid Build Coastguard Worker 	else
246*49cdfc7eSAndroid Build Coastguard Worker 		snd_ctx_tab[gr_num] = snd_ctx;
247*49cdfc7eSAndroid Build Coastguard Worker 
248*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < num_fds; i++) {
249*49cdfc7eSAndroid Build Coastguard Worker 		int fds[2];
250*49cdfc7eSAndroid Build Coastguard Worker 		struct receiver_context *ctx = malloc(sizeof(*ctx));
251*49cdfc7eSAndroid Build Coastguard Worker 
252*49cdfc7eSAndroid Build Coastguard Worker 		if (!ctx)
253*49cdfc7eSAndroid Build Coastguard Worker 			barf("malloc()");
254*49cdfc7eSAndroid Build Coastguard Worker 		else
255*49cdfc7eSAndroid Build Coastguard Worker 			rev_ctx_tab[gr_num * num_fds + i] = ctx;
256*49cdfc7eSAndroid Build Coastguard Worker 
257*49cdfc7eSAndroid Build Coastguard Worker 		/* Create the pipe between client and server */
258*49cdfc7eSAndroid Build Coastguard Worker 		fdpair(fds);
259*49cdfc7eSAndroid Build Coastguard Worker 
260*49cdfc7eSAndroid Build Coastguard Worker 		ctx->num_packets = num_fds * loops;
261*49cdfc7eSAndroid Build Coastguard Worker 		ctx->in_fds[0] = fds[0];
262*49cdfc7eSAndroid Build Coastguard Worker 		ctx->in_fds[1] = fds[1];
263*49cdfc7eSAndroid Build Coastguard Worker 		ctx->ready_out = ready_out;
264*49cdfc7eSAndroid Build Coastguard Worker 		ctx->wakefd = wakefd;
265*49cdfc7eSAndroid Build Coastguard Worker 
266*49cdfc7eSAndroid Build Coastguard Worker 		pth[i] = create_worker(ctx, (void *)(void *)receiver);
267*49cdfc7eSAndroid Build Coastguard Worker 
268*49cdfc7eSAndroid Build Coastguard Worker 		snd_ctx->out_fds[i] = fds[1];
269*49cdfc7eSAndroid Build Coastguard Worker 		if (process_mode)
270*49cdfc7eSAndroid Build Coastguard Worker 			close(fds[0]);
271*49cdfc7eSAndroid Build Coastguard Worker 	}
272*49cdfc7eSAndroid Build Coastguard Worker 
273*49cdfc7eSAndroid Build Coastguard Worker 	/* Now we have all the fds, fork the senders */
274*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < num_fds; i++) {
275*49cdfc7eSAndroid Build Coastguard Worker 		snd_ctx->ready_out = ready_out;
276*49cdfc7eSAndroid Build Coastguard Worker 		snd_ctx->wakefd = wakefd;
277*49cdfc7eSAndroid Build Coastguard Worker 		snd_ctx->num_fds = num_fds;
278*49cdfc7eSAndroid Build Coastguard Worker 
279*49cdfc7eSAndroid Build Coastguard Worker 		pth[num_fds + i] =
280*49cdfc7eSAndroid Build Coastguard Worker 		    create_worker(snd_ctx, (void *)(void *)sender);
281*49cdfc7eSAndroid Build Coastguard Worker 	}
282*49cdfc7eSAndroid Build Coastguard Worker 
283*49cdfc7eSAndroid Build Coastguard Worker 	/* Close the fds we have left */
284*49cdfc7eSAndroid Build Coastguard Worker 	if (process_mode)
285*49cdfc7eSAndroid Build Coastguard Worker 		for (i = 0; i < num_fds; i++)
286*49cdfc7eSAndroid Build Coastguard Worker 			close(snd_ctx->out_fds[i]);
287*49cdfc7eSAndroid Build Coastguard Worker 
288*49cdfc7eSAndroid Build Coastguard Worker 	gr_num++;
289*49cdfc7eSAndroid Build Coastguard Worker 	/* Return number of children to reap */
290*49cdfc7eSAndroid Build Coastguard Worker 	return num_fds * 2;
291*49cdfc7eSAndroid Build Coastguard Worker }
292*49cdfc7eSAndroid Build Coastguard Worker 
main(int argc,char * argv[])293*49cdfc7eSAndroid Build Coastguard Worker int main(int argc, char *argv[])
294*49cdfc7eSAndroid Build Coastguard Worker {
295*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int i, j, num_groups = 10, total_children;
296*49cdfc7eSAndroid Build Coastguard Worker 	struct timeval start, stop, diff;
297*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int num_fds = 20;
298*49cdfc7eSAndroid Build Coastguard Worker 	int readyfds[2], wakefds[2];
299*49cdfc7eSAndroid Build Coastguard Worker 	char dummy;
300*49cdfc7eSAndroid Build Coastguard Worker 	pthread_t *pth_tab;
301*49cdfc7eSAndroid Build Coastguard Worker 
302*49cdfc7eSAndroid Build Coastguard Worker 	if (argv[1] && strcmp(argv[1], "-pipe") == 0) {
303*49cdfc7eSAndroid Build Coastguard Worker 		use_pipes = 1;
304*49cdfc7eSAndroid Build Coastguard Worker 		argc--;
305*49cdfc7eSAndroid Build Coastguard Worker 		argv++;
306*49cdfc7eSAndroid Build Coastguard Worker 	}
307*49cdfc7eSAndroid Build Coastguard Worker 
308*49cdfc7eSAndroid Build Coastguard Worker 	if (argc >= 2 && (num_groups = atoi(argv[1])) == 0)
309*49cdfc7eSAndroid Build Coastguard Worker 		print_usage_exit();
310*49cdfc7eSAndroid Build Coastguard Worker 
311*49cdfc7eSAndroid Build Coastguard Worker 	printf("Running with %d*40 (== %d) tasks.\n",
312*49cdfc7eSAndroid Build Coastguard Worker 	       num_groups, num_groups * 40);
313*49cdfc7eSAndroid Build Coastguard Worker 
314*49cdfc7eSAndroid Build Coastguard Worker 	fflush(NULL);
315*49cdfc7eSAndroid Build Coastguard Worker 
316*49cdfc7eSAndroid Build Coastguard Worker 	if (argc > 2) {
317*49cdfc7eSAndroid Build Coastguard Worker 		if (!strcmp(argv[2], "process"))
318*49cdfc7eSAndroid Build Coastguard Worker 			process_mode = 1;
319*49cdfc7eSAndroid Build Coastguard Worker 		else if (!strcmp(argv[2], "thread"))
320*49cdfc7eSAndroid Build Coastguard Worker 			process_mode = 0;
321*49cdfc7eSAndroid Build Coastguard Worker 		else
322*49cdfc7eSAndroid Build Coastguard Worker 			print_usage_exit();
323*49cdfc7eSAndroid Build Coastguard Worker 	}
324*49cdfc7eSAndroid Build Coastguard Worker 
325*49cdfc7eSAndroid Build Coastguard Worker 	if (argc > 3)
326*49cdfc7eSAndroid Build Coastguard Worker 		loops = atoi(argv[3]);
327*49cdfc7eSAndroid Build Coastguard Worker 
328*49cdfc7eSAndroid Build Coastguard Worker 	pth_tab = malloc(num_fds * 2 * num_groups * sizeof(pthread_t));
329*49cdfc7eSAndroid Build Coastguard Worker 	snd_ctx_tab = malloc(num_groups * sizeof(void *));
330*49cdfc7eSAndroid Build Coastguard Worker 	rev_ctx_tab = malloc(num_groups * num_fds * sizeof(void *));
331*49cdfc7eSAndroid Build Coastguard Worker 	if (!pth_tab || !snd_ctx_tab || !rev_ctx_tab)
332*49cdfc7eSAndroid Build Coastguard Worker 		barf("main:malloc()");
333*49cdfc7eSAndroid Build Coastguard Worker 
334*49cdfc7eSAndroid Build Coastguard Worker 	fdpair(readyfds);
335*49cdfc7eSAndroid Build Coastguard Worker 	fdpair(wakefds);
336*49cdfc7eSAndroid Build Coastguard Worker 
337*49cdfc7eSAndroid Build Coastguard Worker 	total_children = 0;
338*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < num_groups; i++)
339*49cdfc7eSAndroid Build Coastguard Worker 		total_children +=
340*49cdfc7eSAndroid Build Coastguard Worker 		    group(pth_tab + total_children, num_fds, readyfds[1],
341*49cdfc7eSAndroid Build Coastguard Worker 			  wakefds[0]);
342*49cdfc7eSAndroid Build Coastguard Worker 
343*49cdfc7eSAndroid Build Coastguard Worker 	/* Wait for everyone to be ready */
344*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < total_children; i++)
345*49cdfc7eSAndroid Build Coastguard Worker 		if (read(readyfds[0], &dummy, 1) != 1)
346*49cdfc7eSAndroid Build Coastguard Worker 			barf("Reading for readyfds");
347*49cdfc7eSAndroid Build Coastguard Worker 
348*49cdfc7eSAndroid Build Coastguard Worker 	gettimeofday(&start, NULL);
349*49cdfc7eSAndroid Build Coastguard Worker 
350*49cdfc7eSAndroid Build Coastguard Worker 	/* Kick them off */
351*49cdfc7eSAndroid Build Coastguard Worker 	if (write(wakefds[1], &dummy, 1) != 1)
352*49cdfc7eSAndroid Build Coastguard Worker 		barf("Writing to start them");
353*49cdfc7eSAndroid Build Coastguard Worker 
354*49cdfc7eSAndroid Build Coastguard Worker 	/* Reap them all */
355*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < total_children; i++)
356*49cdfc7eSAndroid Build Coastguard Worker 		reap_worker(pth_tab[i]);
357*49cdfc7eSAndroid Build Coastguard Worker 
358*49cdfc7eSAndroid Build Coastguard Worker 	gettimeofday(&stop, NULL);
359*49cdfc7eSAndroid Build Coastguard Worker 
360*49cdfc7eSAndroid Build Coastguard Worker 	/* Print time... */
361*49cdfc7eSAndroid Build Coastguard Worker 	timersub(&stop, &start, &diff);
362*49cdfc7eSAndroid Build Coastguard Worker 	printf("Time: %lu.%03lu\n", diff.tv_sec, diff.tv_usec / 1000);
363*49cdfc7eSAndroid Build Coastguard Worker 
364*49cdfc7eSAndroid Build Coastguard Worker 	/* free the memory */
365*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < num_groups; i++) {
366*49cdfc7eSAndroid Build Coastguard Worker 		for (j = 0; j < num_fds; j++) {
367*49cdfc7eSAndroid Build Coastguard Worker 			SAFE_FREE(rev_ctx_tab[i * num_fds + j])
368*49cdfc7eSAndroid Build Coastguard Worker 		}
369*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_FREE(snd_ctx_tab[i]);
370*49cdfc7eSAndroid Build Coastguard Worker 	}
371*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FREE(pth_tab);
372*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FREE(snd_ctx_tab);
373*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FREE(rev_ctx_tab);
374*49cdfc7eSAndroid Build Coastguard Worker 	exit(0);
375*49cdfc7eSAndroid Build Coastguard Worker }
376