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