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