1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. 3f08c3bdfSopenharmony_ci * 4f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify it 5f08c3bdfSopenharmony_ci * under the terms of version 2 of the GNU General Public License as 6f08c3bdfSopenharmony_ci * published by the Free Software Foundation. 7f08c3bdfSopenharmony_ci * 8f08c3bdfSopenharmony_ci * This program is distributed in the hope that it would be useful, but 9f08c3bdfSopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 10f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11f08c3bdfSopenharmony_ci * 12f08c3bdfSopenharmony_ci * Further, this software is distributed without any warranty that it is 13f08c3bdfSopenharmony_ci * free of the rightful claim of any third person regarding infringement 14f08c3bdfSopenharmony_ci * or the like. Any license provided herein, whether implied or 15f08c3bdfSopenharmony_ci * otherwise, applies only to this software file. Patent licenses, if 16f08c3bdfSopenharmony_ci * any, provided herein do not apply to combinations of this program with 17f08c3bdfSopenharmony_ci * other software, or any other product whatsoever. 18f08c3bdfSopenharmony_ci * 19f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License along 20f08c3bdfSopenharmony_ci * with this program; if not, write the Free Software Foundation, Inc., 21f08c3bdfSopenharmony_ci * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 22f08c3bdfSopenharmony_ci * 23f08c3bdfSopenharmony_ci * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 24f08c3bdfSopenharmony_ci * Mountain View, CA 94043, or: 25f08c3bdfSopenharmony_ci * 26f08c3bdfSopenharmony_ci * http://www.sgi.com 27f08c3bdfSopenharmony_ci * 28f08c3bdfSopenharmony_ci * For further information regarding this notice, see: 29f08c3bdfSopenharmony_ci * 30f08c3bdfSopenharmony_ci * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ 31f08c3bdfSopenharmony_ci * 32f08c3bdfSopenharmony_ci */ 33f08c3bdfSopenharmony_ci/* $Header: /cvsroot/ltp/ltp/testcases/kernel/ipc/pipeio/pipeio.c,v 1.18 2009/03/19 07:10:02 subrata_modak Exp $ */ 34f08c3bdfSopenharmony_ci/* 35f08c3bdfSopenharmony_ci * This tool can be used to beat on system or named pipes. 36f08c3bdfSopenharmony_ci * See the help() function below for user information. 37f08c3bdfSopenharmony_ci */ 38f08c3bdfSopenharmony_ci#include <stdio.h> 39f08c3bdfSopenharmony_ci#include <fcntl.h> 40f08c3bdfSopenharmony_ci#include <stdlib.h> 41f08c3bdfSopenharmony_ci#include <unistd.h> 42f08c3bdfSopenharmony_ci#include <sys/types.h> 43f08c3bdfSopenharmony_ci#include <sys/param.h> 44f08c3bdfSopenharmony_ci#include <sys/wait.h> 45f08c3bdfSopenharmony_ci#include <time.h> 46f08c3bdfSopenharmony_ci#include <errno.h> 47f08c3bdfSopenharmony_ci#include <string.h> 48f08c3bdfSopenharmony_ci#include <signal.h> 49f08c3bdfSopenharmony_ci#include <sys/stat.h> 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_ci#include "tlibio.h" 52f08c3bdfSopenharmony_ci 53f08c3bdfSopenharmony_ci#include "test.h" 54f08c3bdfSopenharmony_ci#include "safe_macros.h" 55f08c3bdfSopenharmony_ci#include "lapi/sem.h" 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_cichar *TCID = "pipeio"; 58f08c3bdfSopenharmony_ciint TST_TOTAL = 1; 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_ci#define SAFE_FREE(p) { if (p) { free(p); (p)=NULL; } } 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_ci#if defined(__linux__) 63f08c3bdfSopenharmony_ci#define NBPW sizeof(int) 64f08c3bdfSopenharmony_ci#endif 65f08c3bdfSopenharmony_ci 66f08c3bdfSopenharmony_ci#define OCTAL 'o' 67f08c3bdfSopenharmony_ci#define HEX 'x' 68f08c3bdfSopenharmony_ci#define DECIMAL 'd' 69f08c3bdfSopenharmony_ci#define ASCII 'a' 70f08c3bdfSopenharmony_ci#define NO_OUT 'n' 71f08c3bdfSopenharmony_ci 72f08c3bdfSopenharmony_ci#define PIPE_NAMED "named pipe," 73f08c3bdfSopenharmony_ci#define PIPE_UNNAMED "sys pipe," 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci#define BLOCKING_IO "blking," 76f08c3bdfSopenharmony_ci#define NON_BLOCKING_IO "non-blking," 77f08c3bdfSopenharmony_ci#define UNNAMED_IO "" 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ci#define MAX_ERRS 16 80f08c3bdfSopenharmony_ci#define MAX_EMPTY 256 81f08c3bdfSopenharmony_ci 82f08c3bdfSopenharmony_cistatic int parse_options(int argc, char *argv[]); 83f08c3bdfSopenharmony_cistatic void setup(int argc, char *argv[]); 84f08c3bdfSopenharmony_cistatic void cleanup(void); 85f08c3bdfSopenharmony_ci 86f08c3bdfSopenharmony_cistatic void do_child(void); 87f08c3bdfSopenharmony_cistatic void do_parent(void); 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_cistatic void help(void), usage(void), prt_examples(void); 90f08c3bdfSopenharmony_cistatic void prt_buf(char **addr, char *buf, int length, int format); 91f08c3bdfSopenharmony_cistatic void sig_child(int sig); 92f08c3bdfSopenharmony_cistatic int check_rw_buf(void); 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_cistatic volatile sig_atomic_t nchildcompleted; 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_ci/* variables may be modified in setup() */ 97f08c3bdfSopenharmony_cistatic int num_writers = 1; /* number of writers */ 98f08c3bdfSopenharmony_cistatic int num_writes = 1; /* number of writes per child */ 99f08c3bdfSopenharmony_cistatic int loop; /* loop indefinitely */ 100f08c3bdfSopenharmony_cistatic int exit_error = 1; /* exit on error #, zero means no exit */ 101f08c3bdfSopenharmony_cistatic int size = 327; /* default size */ 102f08c3bdfSopenharmony_cistatic int unpipe; /* un-named pipe if non-zero */ 103f08c3bdfSopenharmony_cistatic int verbose; /* verbose mode if set */ 104f08c3bdfSopenharmony_cistatic int quiet; /* quiet mode if set */ 105f08c3bdfSopenharmony_cistatic int num_rpt; /* ping number, how often to print message */ 106f08c3bdfSopenharmony_cistatic int chld_wait; /* max time to wait between writes, 1 == no wait */ 107f08c3bdfSopenharmony_cistatic int parent_wait; /* max time to wait between reads, 1 == no wait */ 108f08c3bdfSopenharmony_cistatic int ndelay = O_NDELAY; /* additional flag to open */ 109f08c3bdfSopenharmony_cistatic char *writebuf; 110f08c3bdfSopenharmony_cistatic char *readbuf; 111f08c3bdfSopenharmony_cistatic char pname[PATH_MAX]; /* contains the name of the named pipe */ 112f08c3bdfSopenharmony_cistatic char *blk_type = NON_BLOCKING_IO; /* blocking i/o or not */ 113f08c3bdfSopenharmony_cistatic char *pipe_type; /* type of pipe under test */ 114f08c3bdfSopenharmony_cistatic int format = HEX; 115f08c3bdfSopenharmony_cistatic int format_size = -1; 116f08c3bdfSopenharmony_cistatic int iotype; /* sync io */ 117f08c3bdfSopenharmony_ci 118f08c3bdfSopenharmony_ci/* variables will be modified in running */ 119f08c3bdfSopenharmony_cistatic int error; 120f08c3bdfSopenharmony_cistatic int count; 121f08c3bdfSopenharmony_cistatic int read_fd; 122f08c3bdfSopenharmony_cistatic int write_fd; 123f08c3bdfSopenharmony_cistatic int empty_read; 124f08c3bdfSopenharmony_cistatic int sem_id; 125f08c3bdfSopenharmony_ci 126f08c3bdfSopenharmony_cistatic union semun u; 127f08c3bdfSopenharmony_ci 128f08c3bdfSopenharmony_ciint main(int ac, char *av[]) 129f08c3bdfSopenharmony_ci{ 130f08c3bdfSopenharmony_ci int i; 131f08c3bdfSopenharmony_ci unsigned int j; 132f08c3bdfSopenharmony_ci unsigned int uwait_iter = 1000, uwait_total = 5000000; 133f08c3bdfSopenharmony_ci pid_t child; 134f08c3bdfSopenharmony_ci 135f08c3bdfSopenharmony_ci setup(ac, av); 136f08c3bdfSopenharmony_ci 137f08c3bdfSopenharmony_ci for (i = num_writers; i > 0; --i) { 138f08c3bdfSopenharmony_ci 139f08c3bdfSopenharmony_ci child = tst_fork(); 140f08c3bdfSopenharmony_ci switch (child) { 141f08c3bdfSopenharmony_ci case -1: 142f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, cleanup, "fork() failed"); 143f08c3bdfSopenharmony_ci case 0: 144f08c3bdfSopenharmony_ci do_child(); 145f08c3bdfSopenharmony_ci exit(0); 146f08c3bdfSopenharmony_ci default: 147f08c3bdfSopenharmony_ci break; 148f08c3bdfSopenharmony_ci } 149f08c3bdfSopenharmony_ci } 150f08c3bdfSopenharmony_ci 151f08c3bdfSopenharmony_ci do_parent(); 152f08c3bdfSopenharmony_ci 153f08c3bdfSopenharmony_ci if (empty_read) 154f08c3bdfSopenharmony_ci tst_resm(TWARN, "%d empty reads", empty_read); 155f08c3bdfSopenharmony_ci 156f08c3bdfSopenharmony_ci if (error) { 157f08c3bdfSopenharmony_ci tst_resm(TFAIL, "%d data errors on pipe, read size = %d, %s %s", 158f08c3bdfSopenharmony_ci error, size, pipe_type, blk_type); 159f08c3bdfSopenharmony_ci } else if (!quiet) { 160f08c3bdfSopenharmony_ci tst_resm(TPASS, "%d pipe reads complete, read size = %d, %s %s", 161f08c3bdfSopenharmony_ci count + 1, size, pipe_type, blk_type); 162f08c3bdfSopenharmony_ci } 163f08c3bdfSopenharmony_ci 164f08c3bdfSopenharmony_ci /* 165f08c3bdfSopenharmony_ci * wait for all children to finish, timeout after uwait_total 166f08c3bdfSopenharmony_ci * semtimedop might not be available everywhere 167f08c3bdfSopenharmony_ci */ 168f08c3bdfSopenharmony_ci for (j = 0; j < uwait_total; j += uwait_iter) { 169f08c3bdfSopenharmony_ci if (semctl(sem_id, 1, GETVAL) == 0) 170f08c3bdfSopenharmony_ci break; 171f08c3bdfSopenharmony_ci usleep(uwait_iter); 172f08c3bdfSopenharmony_ci } 173f08c3bdfSopenharmony_ci 174f08c3bdfSopenharmony_ci if (j >= uwait_total) { 175f08c3bdfSopenharmony_ci tst_resm(TWARN, 176f08c3bdfSopenharmony_ci "Timed out waiting for child processes to exit"); 177f08c3bdfSopenharmony_ci } 178f08c3bdfSopenharmony_ci 179f08c3bdfSopenharmony_ci cleanup(); 180f08c3bdfSopenharmony_ci tst_exit(); 181f08c3bdfSopenharmony_ci} 182f08c3bdfSopenharmony_ci 183f08c3bdfSopenharmony_cistatic int parse_options(int argc, char *argv[]) 184f08c3bdfSopenharmony_ci{ 185f08c3bdfSopenharmony_ci char *cp; 186f08c3bdfSopenharmony_ci int c; 187f08c3bdfSopenharmony_ci int ret = 0; 188f08c3bdfSopenharmony_ci static double d; 189f08c3bdfSopenharmony_ci 190f08c3bdfSopenharmony_ci while ((c = getopt(argc, argv, "T:bc:D:he:Ef:i:I:ln:p:qs:uvW:w:")) 191f08c3bdfSopenharmony_ci != -1) { 192f08c3bdfSopenharmony_ci switch (c) { 193f08c3bdfSopenharmony_ci case 'T': 194f08c3bdfSopenharmony_ci TCID = optarg; 195f08c3bdfSopenharmony_ci break; 196f08c3bdfSopenharmony_ci case 'h': 197f08c3bdfSopenharmony_ci help(); 198f08c3bdfSopenharmony_ci ret = 1; 199f08c3bdfSopenharmony_ci break; 200f08c3bdfSopenharmony_ci case 'D': /* pipe name */ 201f08c3bdfSopenharmony_ci strcpy(pname, optarg); 202f08c3bdfSopenharmony_ci break; 203f08c3bdfSopenharmony_ci case 'b': /* blocked */ 204f08c3bdfSopenharmony_ci ndelay = 0; 205f08c3bdfSopenharmony_ci blk_type = BLOCKING_IO; 206f08c3bdfSopenharmony_ci break; 207f08c3bdfSopenharmony_ci case 'c': /* number childern */ 208f08c3bdfSopenharmony_ci if (sscanf(optarg, "%d", &num_writers) != 1) { 209f08c3bdfSopenharmony_ci fprintf(stderr, 210f08c3bdfSopenharmony_ci "%s: --c option invalid arg '%s'.\n", 211f08c3bdfSopenharmony_ci TCID, optarg); 212f08c3bdfSopenharmony_ci ret = 1; 213f08c3bdfSopenharmony_ci } else if (num_writers <= 0) { 214f08c3bdfSopenharmony_ci fprintf(stderr, "%s: --c option must be " 215f08c3bdfSopenharmony_ci "greater than zero.\n", TCID); 216f08c3bdfSopenharmony_ci ret = 1; 217f08c3bdfSopenharmony_ci } 218f08c3bdfSopenharmony_ci break; 219f08c3bdfSopenharmony_ci case 'e': /* exit on error # */ 220f08c3bdfSopenharmony_ci if (sscanf(optarg, "%d", &exit_error) != 1) { 221f08c3bdfSopenharmony_ci fprintf(stderr, 222f08c3bdfSopenharmony_ci "%s: --e option invalid arg '%s'.\n", 223f08c3bdfSopenharmony_ci TCID, optarg); 224f08c3bdfSopenharmony_ci ret = 1; 225f08c3bdfSopenharmony_ci } else if (exit_error < 0) { 226f08c3bdfSopenharmony_ci fprintf(stderr, "%s: --e option must be " 227f08c3bdfSopenharmony_ci "greater than zero.\n", TCID); 228f08c3bdfSopenharmony_ci ret = 1; 229f08c3bdfSopenharmony_ci } 230f08c3bdfSopenharmony_ci break; 231f08c3bdfSopenharmony_ci case 'E': 232f08c3bdfSopenharmony_ci prt_examples(); 233f08c3bdfSopenharmony_ci ret = 1; 234f08c3bdfSopenharmony_ci break; 235f08c3bdfSopenharmony_ci case 'f': /* format of buffer on error */ 236f08c3bdfSopenharmony_ci switch (optarg[0]) { 237f08c3bdfSopenharmony_ci case 'x': 238f08c3bdfSopenharmony_ci case 'X': 239f08c3bdfSopenharmony_ci format = HEX; 240f08c3bdfSopenharmony_ci break; 241f08c3bdfSopenharmony_ci case 'o': 242f08c3bdfSopenharmony_ci case 'O': 243f08c3bdfSopenharmony_ci format = OCTAL; 244f08c3bdfSopenharmony_ci break; 245f08c3bdfSopenharmony_ci case 'd': 246f08c3bdfSopenharmony_ci case 'D': 247f08c3bdfSopenharmony_ci format = DECIMAL; 248f08c3bdfSopenharmony_ci break; 249f08c3bdfSopenharmony_ci case 'a': 250f08c3bdfSopenharmony_ci case 'A': 251f08c3bdfSopenharmony_ci format = ASCII; 252f08c3bdfSopenharmony_ci break; 253f08c3bdfSopenharmony_ci case 'n': /* not output */ 254f08c3bdfSopenharmony_ci case 'N': 255f08c3bdfSopenharmony_ci format = NO_OUT; 256f08c3bdfSopenharmony_ci break; 257f08c3bdfSopenharmony_ci 258f08c3bdfSopenharmony_ci default: 259f08c3bdfSopenharmony_ci fprintf(stderr, 260f08c3bdfSopenharmony_ci "%s: --f option invalid arg '%s'.\n", 261f08c3bdfSopenharmony_ci TCID, optarg); 262f08c3bdfSopenharmony_ci fprintf(stderr, "\tIt must be x(hex), o(octal)," 263f08c3bdfSopenharmony_ci "d(decimal), a(ascii) or n(none) with " 264f08c3bdfSopenharmony_ci "opt sz\n"); 265f08c3bdfSopenharmony_ci ret = 1; 266f08c3bdfSopenharmony_ci break; 267f08c3bdfSopenharmony_ci } 268f08c3bdfSopenharmony_ci cp = optarg; 269f08c3bdfSopenharmony_ci cp++; 270f08c3bdfSopenharmony_ci if (*cp) { 271f08c3bdfSopenharmony_ci if (sscanf(cp, "%i", &format_size) != 1) { 272f08c3bdfSopenharmony_ci fprintf(stderr, "%s: --f option invalid" 273f08c3bdfSopenharmony_ci "arg '%s'.\n", TCID, optarg); 274f08c3bdfSopenharmony_ci fprintf(stderr, "\tIt must be x(hex)," 275f08c3bdfSopenharmony_ci "o(octal), d(decimal), a(ascii)" 276f08c3bdfSopenharmony_ci " or n(none) with opt sz\n"); 277f08c3bdfSopenharmony_ci ret = 1; 278f08c3bdfSopenharmony_ci break; 279f08c3bdfSopenharmony_ci } 280f08c3bdfSopenharmony_ci } 281f08c3bdfSopenharmony_ci break; 282f08c3bdfSopenharmony_ci 283f08c3bdfSopenharmony_ci case 'I': 284f08c3bdfSopenharmony_ci iotype = lio_parse_io_arg1(optarg); 285f08c3bdfSopenharmony_ci if (iotype == -1) { 286f08c3bdfSopenharmony_ci fprintf(stderr, "%s: --I arg is invalid, " 287f08c3bdfSopenharmony_ci "must be s, p, f, a, l, L or r.\n", 288f08c3bdfSopenharmony_ci TCID); 289f08c3bdfSopenharmony_ci ret = 1; 290f08c3bdfSopenharmony_ci } 291f08c3bdfSopenharmony_ci break; 292f08c3bdfSopenharmony_ci 293f08c3bdfSopenharmony_ci case 'l': /* loop forever */ 294f08c3bdfSopenharmony_ci ++loop; 295f08c3bdfSopenharmony_ci break; 296f08c3bdfSopenharmony_ci 297f08c3bdfSopenharmony_ci case 'i': 298f08c3bdfSopenharmony_ci case 'n': /* number writes per child */ 299f08c3bdfSopenharmony_ci if (sscanf(optarg, "%d", &num_writes) != 1) { 300f08c3bdfSopenharmony_ci fprintf(stderr, "%s: --i/n option invalid " 301f08c3bdfSopenharmony_ci "arg '%s'.\n", TCID, optarg); 302f08c3bdfSopenharmony_ci ret = 1; 303f08c3bdfSopenharmony_ci } else if (num_writes < 0) { 304f08c3bdfSopenharmony_ci fprintf(stderr, "%s: --i/n option must be " 305f08c3bdfSopenharmony_ci "greater than equal to zero.\n", 306f08c3bdfSopenharmony_ci TCID); 307f08c3bdfSopenharmony_ci ret = 1; 308f08c3bdfSopenharmony_ci } 309f08c3bdfSopenharmony_ci 310f08c3bdfSopenharmony_ci if (num_writes == 0) /* loop forever */ 311f08c3bdfSopenharmony_ci ++loop; 312f08c3bdfSopenharmony_ci break; 313f08c3bdfSopenharmony_ci case 'p': /* ping */ 314f08c3bdfSopenharmony_ci if (sscanf(optarg, "%d", &num_rpt) != 1) { 315f08c3bdfSopenharmony_ci fprintf(stderr, 316f08c3bdfSopenharmony_ci "%s: --p option invalid arg '%s'.\n", 317f08c3bdfSopenharmony_ci TCID, optarg); 318f08c3bdfSopenharmony_ci ret = 1; 319f08c3bdfSopenharmony_ci } else if (num_rpt < 0) { 320f08c3bdfSopenharmony_ci fprintf(stderr, "%s: --p option must be greater" 321f08c3bdfSopenharmony_ci " than equal to zero.\n", TCID); 322f08c3bdfSopenharmony_ci ret = 1; 323f08c3bdfSopenharmony_ci } 324f08c3bdfSopenharmony_ci break; 325f08c3bdfSopenharmony_ci case 'q': /* Quiet - NOPASS */ 326f08c3bdfSopenharmony_ci quiet = 1; 327f08c3bdfSopenharmony_ci break; 328f08c3bdfSopenharmony_ci case 's': /* size */ 329f08c3bdfSopenharmony_ci if (sscanf(optarg, "%d", &size) != 1) { 330f08c3bdfSopenharmony_ci fprintf(stderr, 331f08c3bdfSopenharmony_ci "%s: --s option invalid arg '%s'.\n", 332f08c3bdfSopenharmony_ci TCID, optarg); 333f08c3bdfSopenharmony_ci ret = 1; 334f08c3bdfSopenharmony_ci } else if (size <= 0) { 335f08c3bdfSopenharmony_ci fprintf(stderr, "%s: --s option must be greater" 336f08c3bdfSopenharmony_ci " than zero.\n", TCID); 337f08c3bdfSopenharmony_ci ret = 1; 338f08c3bdfSopenharmony_ci } 339f08c3bdfSopenharmony_ci break; 340f08c3bdfSopenharmony_ci case 'u': 341f08c3bdfSopenharmony_ci unpipe = 1; /* un-named pipe */ 342f08c3bdfSopenharmony_ci break; 343f08c3bdfSopenharmony_ci case 'v': /* verbose */ 344f08c3bdfSopenharmony_ci verbose = 1; 345f08c3bdfSopenharmony_ci break; 346f08c3bdfSopenharmony_ci case 'W': /* max wait time between reads */ 347f08c3bdfSopenharmony_ci d = strtod(optarg, &cp); 348f08c3bdfSopenharmony_ci if (*cp != '\0') { 349f08c3bdfSopenharmony_ci fprintf(stderr, 350f08c3bdfSopenharmony_ci "%s: --w option invalid arg '%s'.\n", 351f08c3bdfSopenharmony_ci TCID, optarg); 352f08c3bdfSopenharmony_ci ret = 1; 353f08c3bdfSopenharmony_ci } else if (d < 0) { 354f08c3bdfSopenharmony_ci fprintf(stderr, "%s: --w option must be greater" 355f08c3bdfSopenharmony_ci " than zero.\n", TCID); 356f08c3bdfSopenharmony_ci ret = 1; 357f08c3bdfSopenharmony_ci } 358f08c3bdfSopenharmony_ci parent_wait = (int)(d * 1000000.0); 359f08c3bdfSopenharmony_ci break; 360f08c3bdfSopenharmony_ci case 'w': /* max wait time between writes */ 361f08c3bdfSopenharmony_ci d = strtod(optarg, &cp); 362f08c3bdfSopenharmony_ci if (*cp != '\0') { 363f08c3bdfSopenharmony_ci fprintf(stderr, 364f08c3bdfSopenharmony_ci "%s: --w option invalid arg '%s'.\n", 365f08c3bdfSopenharmony_ci TCID, optarg); 366f08c3bdfSopenharmony_ci ret = 1; 367f08c3bdfSopenharmony_ci } else if (d < 0) { 368f08c3bdfSopenharmony_ci fprintf(stderr, "%s: --w option must be greater" 369f08c3bdfSopenharmony_ci " than zero.\n", TCID); 370f08c3bdfSopenharmony_ci ret = 1; 371f08c3bdfSopenharmony_ci } 372f08c3bdfSopenharmony_ci chld_wait = (int)(d * 1000000.0); 373f08c3bdfSopenharmony_ci break; 374f08c3bdfSopenharmony_ci case '?': 375f08c3bdfSopenharmony_ci ret = 1; 376f08c3bdfSopenharmony_ci break; 377f08c3bdfSopenharmony_ci } 378f08c3bdfSopenharmony_ci 379f08c3bdfSopenharmony_ci if (ret == 1) { 380f08c3bdfSopenharmony_ci usage(); 381f08c3bdfSopenharmony_ci return ret; 382f08c3bdfSopenharmony_ci } 383f08c3bdfSopenharmony_ci } 384f08c3bdfSopenharmony_ci 385f08c3bdfSopenharmony_ci return ret; 386f08c3bdfSopenharmony_ci} 387f08c3bdfSopenharmony_ci 388f08c3bdfSopenharmony_cistatic void setup(int argc, char *argv[]) 389f08c3bdfSopenharmony_ci{ 390f08c3bdfSopenharmony_ci int ret; 391f08c3bdfSopenharmony_ci char *toutput; 392f08c3bdfSopenharmony_ci int fds[2]; 393f08c3bdfSopenharmony_ci 394f08c3bdfSopenharmony_ci tst_sig(FORK, DEF_HANDLER, cleanup); 395f08c3bdfSopenharmony_ci 396f08c3bdfSopenharmony_ci TEST_PAUSE; 397f08c3bdfSopenharmony_ci 398f08c3bdfSopenharmony_ci tst_tmpdir(); 399f08c3bdfSopenharmony_ci 400f08c3bdfSopenharmony_ci if (signal(SIGCHLD, sig_child) == SIG_ERR) { 401f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, cleanup, 402f08c3bdfSopenharmony_ci "set signal handler for SIGCHLD failed"); 403f08c3bdfSopenharmony_ci } 404f08c3bdfSopenharmony_ci 405f08c3bdfSopenharmony_ci toutput = getenv("TOUTPUT"); 406f08c3bdfSopenharmony_ci if (toutput != NULL && strcmp(toutput, "NOPASS") == 0) 407f08c3bdfSopenharmony_ci quiet = 1; 408f08c3bdfSopenharmony_ci 409f08c3bdfSopenharmony_ci sprintf(pname, "%s", "tpipe"); 410f08c3bdfSopenharmony_ci 411f08c3bdfSopenharmony_ci ret = parse_options(argc, argv); 412f08c3bdfSopenharmony_ci if (ret == 1) 413f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, "options parse error"); 414f08c3bdfSopenharmony_ci 415f08c3bdfSopenharmony_ci if (format_size == -1) 416f08c3bdfSopenharmony_ci format_size = size; 417f08c3bdfSopenharmony_ci 418f08c3bdfSopenharmony_ci /* 419f08c3bdfSopenharmony_ci * If there is more than one writer, all writes and reads 420f08c3bdfSopenharmony_ci * must be the same size. Only writes of a size <= PIPE_BUF 421f08c3bdfSopenharmony_ci * are atomic. T 422f08c3bdfSopenharmony_ci * Therefore, if size is greater than PIPE_BUF, we will break 423f08c3bdfSopenharmony_ci * the writes into PIPE_BUF chunks. We will also increase the 424f08c3bdfSopenharmony_ci * number of writes to ensure the same (or more) amount of 425f08c3bdfSopenharmony_ci * data is written. This is the same as erroring and telling 426f08c3bdfSopenharmony_ci * the user the new cmd line to do the same thing. 427f08c3bdfSopenharmony_ci * Example: 428f08c3bdfSopenharmony_ci * pipeio -s 5000 -n 10 -c 5 429f08c3bdfSopenharmony_ci * (each child will write at least 50000 bytes, since all 430f08c3bdfSopenharmony_ci * writes have to be in 4096 chuncks or 13*4096 (53248) 431f08c3bdfSopenharmony_ci * bytes will be written.) This is the same as: 432f08c3bdfSopenharmony_ci * pipeio -s 4096 -n 13 -c 5 433f08c3bdfSopenharmony_ci */ 434f08c3bdfSopenharmony_ci if (size > PIPE_BUF && num_writers > 1) { 435f08c3bdfSopenharmony_ci if (!loop) { 436f08c3bdfSopenharmony_ci /* 437f08c3bdfSopenharmony_ci * we must set num_writes*num_writers 438f08c3bdfSopenharmony_ci * doesn't overflow later 439f08c3bdfSopenharmony_ci */ 440f08c3bdfSopenharmony_ci num_writes = MIN(((long long)num_writes * size + 441f08c3bdfSopenharmony_ci PIPE_BUF - 1) / PIPE_BUF, 442f08c3bdfSopenharmony_ci INT_MAX / num_writers); 443f08c3bdfSopenharmony_ci tst_resm(TINFO, "adjusting i/o size to %d, and # of " 444f08c3bdfSopenharmony_ci "writes to %d", PIPE_BUF, num_writes); 445f08c3bdfSopenharmony_ci } else { 446f08c3bdfSopenharmony_ci tst_resm(TINFO, "adjusting i/o size to %d", PIPE_BUF); 447f08c3bdfSopenharmony_ci } 448f08c3bdfSopenharmony_ci size = PIPE_BUF; 449f08c3bdfSopenharmony_ci } 450f08c3bdfSopenharmony_ci 451f08c3bdfSopenharmony_ci writebuf = SAFE_MALLOC(cleanup, size); 452f08c3bdfSopenharmony_ci readbuf = SAFE_MALLOC(cleanup, size); 453f08c3bdfSopenharmony_ci 454f08c3bdfSopenharmony_ci memset(writebuf, 'Z', size); 455f08c3bdfSopenharmony_ci writebuf[size - 1] = 'A'; 456f08c3bdfSopenharmony_ci 457f08c3bdfSopenharmony_ci sem_id = semget(IPC_PRIVATE, 2, IPC_CREAT | S_IRWXU); 458f08c3bdfSopenharmony_ci if (sem_id == -1) { 459f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, cleanup, 460f08c3bdfSopenharmony_ci "Couldn't allocate semaphore"); 461f08c3bdfSopenharmony_ci } 462f08c3bdfSopenharmony_ci 463f08c3bdfSopenharmony_ci if (semctl(sem_id, 0, SETVAL, u) == -1) { 464f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, cleanup, 465f08c3bdfSopenharmony_ci "Couldn't initialize semaphore 0 value"); 466f08c3bdfSopenharmony_ci } 467f08c3bdfSopenharmony_ci 468f08c3bdfSopenharmony_ci if (semctl(sem_id, 1, SETVAL, u) == -1) { 469f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, cleanup, 470f08c3bdfSopenharmony_ci "Couldn't initialize semaphore 1 value"); 471f08c3bdfSopenharmony_ci } 472f08c3bdfSopenharmony_ci 473f08c3bdfSopenharmony_ci if (unpipe) { 474f08c3bdfSopenharmony_ci SAFE_PIPE(cleanup, fds); 475f08c3bdfSopenharmony_ci read_fd = fds[0]; 476f08c3bdfSopenharmony_ci write_fd = fds[1]; 477f08c3bdfSopenharmony_ci pipe_type = PIPE_UNNAMED; 478f08c3bdfSopenharmony_ci blk_type = UNNAMED_IO; 479f08c3bdfSopenharmony_ci } else { 480f08c3bdfSopenharmony_ci SAFE_MKFIFO(cleanup, pname, 0777); 481f08c3bdfSopenharmony_ci pipe_type = PIPE_NAMED; 482f08c3bdfSopenharmony_ci } 483f08c3bdfSopenharmony_ci} 484f08c3bdfSopenharmony_ci 485f08c3bdfSopenharmony_cistatic void cleanup(void) 486f08c3bdfSopenharmony_ci{ 487f08c3bdfSopenharmony_ci SAFE_FREE(writebuf); 488f08c3bdfSopenharmony_ci SAFE_FREE(readbuf); 489f08c3bdfSopenharmony_ci 490f08c3bdfSopenharmony_ci semctl(sem_id, 0, IPC_RMID); 491f08c3bdfSopenharmony_ci 492f08c3bdfSopenharmony_ci if (!unpipe) 493f08c3bdfSopenharmony_ci unlink(pname); 494f08c3bdfSopenharmony_ci 495f08c3bdfSopenharmony_ci tst_rmdir(); 496f08c3bdfSopenharmony_ci} 497f08c3bdfSopenharmony_ci 498f08c3bdfSopenharmony_cistatic void do_child(void) 499f08c3bdfSopenharmony_ci{ 500f08c3bdfSopenharmony_ci int *count_word; /* holds address where to write writers count */ 501f08c3bdfSopenharmony_ci int *pid_word; /* holds address where to write writers pid */ 502f08c3bdfSopenharmony_ci int nb, j; 503f08c3bdfSopenharmony_ci long clock; 504f08c3bdfSopenharmony_ci char *cp; 505f08c3bdfSopenharmony_ci long int n; 506f08c3bdfSopenharmony_ci struct sembuf sem_op; 507f08c3bdfSopenharmony_ci pid_t self_pid = getpid(); 508f08c3bdfSopenharmony_ci 509f08c3bdfSopenharmony_ci if (!unpipe) { 510f08c3bdfSopenharmony_ci write_fd = open(pname, O_WRONLY); 511f08c3bdfSopenharmony_ci if (write_fd == -1) { 512f08c3bdfSopenharmony_ci fprintf(stderr, "child pipe open(%s, %#o) failed", 513f08c3bdfSopenharmony_ci pname, O_WRONLY | ndelay); 514f08c3bdfSopenharmony_ci exit(1); 515f08c3bdfSopenharmony_ci } 516f08c3bdfSopenharmony_ci if (ndelay && fcntl(write_fd, F_SETFL, O_NONBLOCK) == -1) { 517f08c3bdfSopenharmony_ci fprintf(stderr, "Failed setting the pipe to " 518f08c3bdfSopenharmony_ci "nonblocking mode"); 519f08c3bdfSopenharmony_ci exit(1); 520f08c3bdfSopenharmony_ci } 521f08c3bdfSopenharmony_ci } else { 522f08c3bdfSopenharmony_ci close(read_fd); 523f08c3bdfSopenharmony_ci } 524f08c3bdfSopenharmony_ci 525f08c3bdfSopenharmony_ci sem_op = (struct sembuf) { 526f08c3bdfSopenharmony_ci .sem_num = 0, .sem_op = 1, .sem_flg = 0}; 527f08c3bdfSopenharmony_ci 528f08c3bdfSopenharmony_ci if (semop(sem_id, &sem_op, 1) == -1) { 529f08c3bdfSopenharmony_ci fprintf(stderr, "child: %d couldn't raise the semaphore 0", 530f08c3bdfSopenharmony_ci self_pid); 531f08c3bdfSopenharmony_ci exit(1); 532f08c3bdfSopenharmony_ci } 533f08c3bdfSopenharmony_ci 534f08c3bdfSopenharmony_ci pid_word = (int *)&writebuf[0]; 535f08c3bdfSopenharmony_ci count_word = (int *)&writebuf[NBPW]; 536f08c3bdfSopenharmony_ci 537f08c3bdfSopenharmony_ci for (j = 0; j < num_writes || loop; ++j) { 538f08c3bdfSopenharmony_ci /* 539f08c3bdfSopenharmony_ci * writes are only in one unit when the size of the write 540f08c3bdfSopenharmony_ci * is <= PIPE_BUF. 541f08c3bdfSopenharmony_ci * Therefore, if size is greater than PIPE_BUF, we will break 542f08c3bdfSopenharmony_ci * the writes into PIPE_BUF chunks. 543f08c3bdfSopenharmony_ci * All writes and read need to be same size. 544f08c3bdfSopenharmony_ci */ 545f08c3bdfSopenharmony_ci 546f08c3bdfSopenharmony_ci /* 547f08c3bdfSopenharmony_ci * write pid and count in first two 548f08c3bdfSopenharmony_ci * words of buffer 549f08c3bdfSopenharmony_ci */ 550f08c3bdfSopenharmony_ci *count_word = j; 551f08c3bdfSopenharmony_ci *pid_word = self_pid; 552f08c3bdfSopenharmony_ci 553f08c3bdfSopenharmony_ci nb = lio_write_buffer(write_fd, iotype, writebuf, size, 554f08c3bdfSopenharmony_ci SIGUSR1, &cp, 0); 555f08c3bdfSopenharmony_ci if (nb < 0) { 556f08c3bdfSopenharmony_ci /* 557f08c3bdfSopenharmony_ci * If lio_write_buffer returns a negative number, 558f08c3bdfSopenharmony_ci * the return will be -errno. 559f08c3bdfSopenharmony_ci */ 560f08c3bdfSopenharmony_ci fprintf(stderr, "pass %d: lio_write_buffer(%s) failed;" 561f08c3bdfSopenharmony_ci " it returned %d: %s", 562f08c3bdfSopenharmony_ci j, cp, nb, strerror(-nb)); 563f08c3bdfSopenharmony_ci exit(1); 564f08c3bdfSopenharmony_ci } else if (nb != size) { 565f08c3bdfSopenharmony_ci fprintf(stderr, "pass %d: lio_write_buffer(%s) failed," 566f08c3bdfSopenharmony_ci " write count %d, but expected to write %d", 567f08c3bdfSopenharmony_ci j, cp, nb, size); 568f08c3bdfSopenharmony_ci } 569f08c3bdfSopenharmony_ci if (verbose) { 570f08c3bdfSopenharmony_ci fprintf(stderr, "pass %d: pid %d: wrote %d bytes," 571f08c3bdfSopenharmony_ci "expected %d bytes", 572f08c3bdfSopenharmony_ci j, self_pid, nb, size); 573f08c3bdfSopenharmony_ci } 574f08c3bdfSopenharmony_ci 575f08c3bdfSopenharmony_ci if (chld_wait) { 576f08c3bdfSopenharmony_ci clock = time(0); 577f08c3bdfSopenharmony_ci srand48(clock); 578f08c3bdfSopenharmony_ci n = lrand48() % chld_wait; 579f08c3bdfSopenharmony_ci usleep(n); 580f08c3bdfSopenharmony_ci } 581f08c3bdfSopenharmony_ci fflush(stderr); 582f08c3bdfSopenharmony_ci } 583f08c3bdfSopenharmony_ci 584f08c3bdfSopenharmony_ci /* child waits until parent completes open() */ 585f08c3bdfSopenharmony_ci sem_op = (struct sembuf) { 586f08c3bdfSopenharmony_ci .sem_num = 1, .sem_op = -1, .sem_flg = 0}; 587f08c3bdfSopenharmony_ci if (semop(sem_id, &sem_op, 1) == -1) 588f08c3bdfSopenharmony_ci fprintf(stderr, "Couldn't lower the semaphore 1"); 589f08c3bdfSopenharmony_ci 590f08c3bdfSopenharmony_ci exit(0); 591f08c3bdfSopenharmony_ci} 592f08c3bdfSopenharmony_ci 593f08c3bdfSopenharmony_cistatic int check_rw_buf(void) 594f08c3bdfSopenharmony_ci{ 595f08c3bdfSopenharmony_ci int i; 596f08c3bdfSopenharmony_ci 597f08c3bdfSopenharmony_ci for (i = 2 * NBPW; i < size; ++i) { 598f08c3bdfSopenharmony_ci if (writebuf[i] != readbuf[i]) { 599f08c3bdfSopenharmony_ci ++error; 600f08c3bdfSopenharmony_ci tst_resm(TFAIL, 601f08c3bdfSopenharmony_ci "FAIL data error on byte %d; rd# %d, sz= %d, " 602f08c3bdfSopenharmony_ci "%s %s empty_reads= %d, err= %d", 603f08c3bdfSopenharmony_ci i, count, size, pipe_type, blk_type, 604f08c3bdfSopenharmony_ci empty_read, error); 605f08c3bdfSopenharmony_ci prt_buf(&readbuf, readbuf, format_size, format); 606f08c3bdfSopenharmony_ci fflush(stdout); 607f08c3bdfSopenharmony_ci return 1; 608f08c3bdfSopenharmony_ci } 609f08c3bdfSopenharmony_ci } 610f08c3bdfSopenharmony_ci 611f08c3bdfSopenharmony_ci return 0; 612f08c3bdfSopenharmony_ci} 613f08c3bdfSopenharmony_ci 614f08c3bdfSopenharmony_cistatic void do_parent(void) 615f08c3bdfSopenharmony_ci{ 616f08c3bdfSopenharmony_ci int i, nb; 617f08c3bdfSopenharmony_ci long clock; 618f08c3bdfSopenharmony_ci time_t start_time, current_time, diff_time; 619f08c3bdfSopenharmony_ci char *cp; 620f08c3bdfSopenharmony_ci long int n; 621f08c3bdfSopenharmony_ci struct sembuf sem_op; 622f08c3bdfSopenharmony_ci 623f08c3bdfSopenharmony_ci start_time = time(0); 624f08c3bdfSopenharmony_ci if (!unpipe) { 625f08c3bdfSopenharmony_ci read_fd = SAFE_OPEN(cleanup, pname, O_RDONLY); 626f08c3bdfSopenharmony_ci if (ndelay && fcntl(read_fd, F_SETFL, O_NONBLOCK) == -1) { 627f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, cleanup, 628f08c3bdfSopenharmony_ci "Failed setting the pipe to nonblocking mode"); 629f08c3bdfSopenharmony_ci } 630f08c3bdfSopenharmony_ci } else { 631f08c3bdfSopenharmony_ci SAFE_CLOSE(cleanup, write_fd); 632f08c3bdfSopenharmony_ci } 633f08c3bdfSopenharmony_ci 634f08c3bdfSopenharmony_ci /* raise semaphore so children can exit */ 635f08c3bdfSopenharmony_ci sem_op = (struct sembuf) { 636f08c3bdfSopenharmony_ci .sem_num = 1, .sem_op = num_writers, .sem_flg = 0}; 637f08c3bdfSopenharmony_ci if (semop(sem_id, &sem_op, 1) == -1) { 638f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, cleanup, 639f08c3bdfSopenharmony_ci "Couldn't raise the semaphore 1"); 640f08c3bdfSopenharmony_ci } 641f08c3bdfSopenharmony_ci 642f08c3bdfSopenharmony_ci sem_op = (struct sembuf) { 643f08c3bdfSopenharmony_ci .sem_num = 0, .sem_op = -num_writers, .sem_flg = 0}; 644f08c3bdfSopenharmony_ci 645f08c3bdfSopenharmony_ci while (nchildcompleted < num_writers 646f08c3bdfSopenharmony_ci && semop(sem_id, &sem_op, 1) == -1) { 647f08c3bdfSopenharmony_ci if (errno == EINTR) 648f08c3bdfSopenharmony_ci continue; 649f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, cleanup, 650f08c3bdfSopenharmony_ci "Couldn't wait on semaphore 0"); 651f08c3bdfSopenharmony_ci } 652f08c3bdfSopenharmony_ci 653f08c3bdfSopenharmony_ci /* parent start to read pipe */ 654f08c3bdfSopenharmony_ci for (i = num_writers * num_writes; i > 0 || loop; --i) { 655f08c3bdfSopenharmony_ci if (error >= MAX_ERRS || empty_read >= MAX_EMPTY) 656f08c3bdfSopenharmony_ci break; 657f08c3bdfSopenharmony_ci if (parent_wait) { 658f08c3bdfSopenharmony_ci clock = time(0); 659f08c3bdfSopenharmony_ci srand48(clock); 660f08c3bdfSopenharmony_ci n = lrand48() % parent_wait; 661f08c3bdfSopenharmony_ci usleep(n); 662f08c3bdfSopenharmony_ci } 663f08c3bdfSopenharmony_ci ++count; 664f08c3bdfSopenharmony_ci nb = lio_read_buffer(read_fd, iotype, readbuf, size, 665f08c3bdfSopenharmony_ci SIGUSR1, &cp, 0); 666f08c3bdfSopenharmony_ci if (nb < 0) { 667f08c3bdfSopenharmony_ci /* 668f08c3bdfSopenharmony_ci * If lio_read_buffer returns a negative number, 669f08c3bdfSopenharmony_ci * the return will be -errno. 670f08c3bdfSopenharmony_ci */ 671f08c3bdfSopenharmony_ci tst_resm(TFAIL, "pass %d: lio_read_buffer(%s) failed; " 672f08c3bdfSopenharmony_ci "returned %d: %s", i, cp, nb, strerror(-nb)); 673f08c3bdfSopenharmony_ci ++i; 674f08c3bdfSopenharmony_ci count--; 675f08c3bdfSopenharmony_ci error++; 676f08c3bdfSopenharmony_ci continue; 677f08c3bdfSopenharmony_ci } else { 678f08c3bdfSopenharmony_ci if (nb == 0) { 679f08c3bdfSopenharmony_ci if (nchildcompleted >= num_writers && !loop) { 680f08c3bdfSopenharmony_ci tst_resm(TWARN, "The children have " 681f08c3bdfSopenharmony_ci "died prematurely"); 682f08c3bdfSopenharmony_ci break; /* All children have died */ 683f08c3bdfSopenharmony_ci } 684f08c3bdfSopenharmony_ci empty_read++; 685f08c3bdfSopenharmony_ci ++i; 686f08c3bdfSopenharmony_ci count--; 687f08c3bdfSopenharmony_ci continue; 688f08c3bdfSopenharmony_ci } else if (nb < size && size <= PIPE_BUF) { 689f08c3bdfSopenharmony_ci tst_resm(TFAIL, "pass %d: partial read from the" 690f08c3bdfSopenharmony_ci " pipe: read %d bytes, expected %d, " 691f08c3bdfSopenharmony_ci "read count %d", i, nb, size, count); 692f08c3bdfSopenharmony_ci ++error; 693f08c3bdfSopenharmony_ci } else if (nb == size) { 694f08c3bdfSopenharmony_ci check_rw_buf(); 695f08c3bdfSopenharmony_ci if (exit_error && exit_error == error) 696f08c3bdfSopenharmony_ci return; 697f08c3bdfSopenharmony_ci } 698f08c3bdfSopenharmony_ci 699f08c3bdfSopenharmony_ci if (verbose || (num_rpt && !(count % num_rpt))) { 700f08c3bdfSopenharmony_ci current_time = time(0); 701f08c3bdfSopenharmony_ci diff_time = current_time - start_time; 702f08c3bdfSopenharmony_ci tst_resm(TFAIL, 703f08c3bdfSopenharmony_ci "(%d) rd# %d, sz= %d, %s %s " 704f08c3bdfSopenharmony_ci "empty_reads= %d, err= %d\n", 705f08c3bdfSopenharmony_ci (int)diff_time, count, size, 706f08c3bdfSopenharmony_ci pipe_type, blk_type, 707f08c3bdfSopenharmony_ci empty_read, error); 708f08c3bdfSopenharmony_ci fflush(stdout); 709f08c3bdfSopenharmony_ci } 710f08c3bdfSopenharmony_ci } 711f08c3bdfSopenharmony_ci } 712f08c3bdfSopenharmony_ci 713f08c3bdfSopenharmony_ci SAFE_CLOSE(cleanup, read_fd); 714f08c3bdfSopenharmony_ci} 715f08c3bdfSopenharmony_ci 716f08c3bdfSopenharmony_cistatic void usage(void) 717f08c3bdfSopenharmony_ci{ 718f08c3bdfSopenharmony_ci fprintf(stderr, "Usage: %s [-bEv][-c #writers][-D pname][-h]" 719f08c3bdfSopenharmony_ci "[-e exit_num][-f fmt][-l][-i #writes][-n #writes][-p num_rpt]" 720f08c3bdfSopenharmony_ci "\n\t[-s size][-W max_wait][-w max_wait][-u]\n", TCID); 721f08c3bdfSopenharmony_ci fflush(stderr); 722f08c3bdfSopenharmony_ci} 723f08c3bdfSopenharmony_ci 724f08c3bdfSopenharmony_cistatic void help(void) 725f08c3bdfSopenharmony_ci{ 726f08c3bdfSopenharmony_ci usage(); 727f08c3bdfSopenharmony_ci 728f08c3bdfSopenharmony_ci printf(" -b - blocking reads and writes. default non-block\n\ 729f08c3bdfSopenharmony_ci -c #writers - number of writers (childern)\n\ 730f08c3bdfSopenharmony_ci -D pname - name of fifo (def tpipe<pid>)\n\ 731f08c3bdfSopenharmony_ci -h - print this help message\n\ 732f08c3bdfSopenharmony_ci -e exit_num - exit on error exit_num, 0 is ignore errors, 1 is default.\n\ 733f08c3bdfSopenharmony_ci -E - print cmd line examples and exit\n\ 734f08c3bdfSopenharmony_ci -f format - define format of bad buffer: h(hex), o(octal)\n\ 735f08c3bdfSopenharmony_ci d(decimal), a(ascii), n (none). hex is default\n\ 736f08c3bdfSopenharmony_ci option size can be added to control output\n\ 737f08c3bdfSopenharmony_ci -i #writes - number write per child, zero means forever.\n\ 738f08c3bdfSopenharmony_ci -I io_type - Specifies io type: s - sync, p - polled async, a - async (def s)\n\ 739f08c3bdfSopenharmony_ci l - listio sync, L - listio async, r - random\n\ 740f08c3bdfSopenharmony_ci -l - loop forever (implied by -n 0).\n\ 741f08c3bdfSopenharmony_ci -n #writes - same as -i (for compatability).\n\ 742f08c3bdfSopenharmony_ci -p num_rpt - number of reads before a report\n\ 743f08c3bdfSopenharmony_ci -q - quiet mode, no PASS results are printed\n\ 744f08c3bdfSopenharmony_ci -s size - size of read and write (def 327)\n\ 745f08c3bdfSopenharmony_ci if size >= 4096, i/o will be in 4096 chuncks\n\ 746f08c3bdfSopenharmony_ci -w max_wait - max time (seconds) for sleep between writes.\n\ 747f08c3bdfSopenharmony_ci max_wait is interpreted as a double with ms accuracy.\n\ 748f08c3bdfSopenharmony_ci -W max_wait - max time (seconds) for sleep between reads\n\ 749f08c3bdfSopenharmony_ci max_wait is interpreted as a double with ms accuracy.\n\ 750f08c3bdfSopenharmony_ci -u - un-named pipe instead of named pipe\n\ 751f08c3bdfSopenharmony_ci -v - verbose mode, all writes/reads resutlts printed\n"); 752f08c3bdfSopenharmony_ci 753f08c3bdfSopenharmony_ci fflush(stdout); 754f08c3bdfSopenharmony_ci} 755f08c3bdfSopenharmony_ci 756f08c3bdfSopenharmony_cistatic void prt_buf(char **addr, char *buf, int length, int format) 757f08c3bdfSopenharmony_ci{ 758f08c3bdfSopenharmony_ci int i; 759f08c3bdfSopenharmony_ci int num_words = length / NBPW; /* given length in bytes, get length in words */ 760f08c3bdfSopenharmony_ci int width; /* number of columns */ 761f08c3bdfSopenharmony_ci int extra_words = 0; /* odd or even number of words */ 762f08c3bdfSopenharmony_ci char *a = buf; 763f08c3bdfSopenharmony_ci char b[NBPW]; 764f08c3bdfSopenharmony_ci char c[NBPW * 2]; 765f08c3bdfSopenharmony_ci char *p; 766f08c3bdfSopenharmony_ci long *word; 767f08c3bdfSopenharmony_ci 768f08c3bdfSopenharmony_ci if (format == NO_OUT) /* if no output wanted, return */ 769f08c3bdfSopenharmony_ci return; 770f08c3bdfSopenharmony_ci 771f08c3bdfSopenharmony_ci if (length % NBPW) 772f08c3bdfSopenharmony_ci ++num_words; /* is length in full words? */ 773f08c3bdfSopenharmony_ci if (format == ASCII) { 774f08c3bdfSopenharmony_ci width = 3; 775f08c3bdfSopenharmony_ci } else { 776f08c3bdfSopenharmony_ci width = 2; 777f08c3bdfSopenharmony_ci /* do we have an odd number of words? */ 778f08c3bdfSopenharmony_ci extra_words = num_words % width; 779f08c3bdfSopenharmony_ci } 780f08c3bdfSopenharmony_ci for (i = 0; i < num_words; ++i, a += NBPW, addr++) { 781f08c3bdfSopenharmony_ci word = (long *)a; 782f08c3bdfSopenharmony_ci if (!(i % width)) { 783f08c3bdfSopenharmony_ci if (i > 0 && format != ASCII) { 784f08c3bdfSopenharmony_ci /* 785f08c3bdfSopenharmony_ci * print the ascii equivalent of the data 786f08c3bdfSopenharmony_ci * before beginning the next line of output. 787f08c3bdfSopenharmony_ci */ 788f08c3bdfSopenharmony_ci memset(c, 0x00, width * NBPW); 789f08c3bdfSopenharmony_ci /* 790f08c3bdfSopenharmony_ci * get the last 2 words printed 791f08c3bdfSopenharmony_ci */ 792f08c3bdfSopenharmony_ci memcpy(c, a - (width * NBPW), width * NBPW); 793f08c3bdfSopenharmony_ci for (p = c; (p - c) < (int)(width*NBPW); ++p) { 794f08c3bdfSopenharmony_ci if (*p < '!' || *p > '~') 795f08c3bdfSopenharmony_ci *p = '.'; 796f08c3bdfSopenharmony_ci } 797f08c3bdfSopenharmony_ci printf("\t%16.16s", c); 798f08c3bdfSopenharmony_ci } 799f08c3bdfSopenharmony_ci printf("\n%p: ", addr); 800f08c3bdfSopenharmony_ci /***printf("\n%7o (%d): ",addr,i);***/ 801f08c3bdfSopenharmony_ci } 802f08c3bdfSopenharmony_ci 803f08c3bdfSopenharmony_ci switch (format) { 804f08c3bdfSopenharmony_ci case HEX: 805f08c3bdfSopenharmony_ci printf("%16.16lx ", *word); 806f08c3bdfSopenharmony_ci break; 807f08c3bdfSopenharmony_ci case DECIMAL: 808f08c3bdfSopenharmony_ci printf("%10.10ld ", *word); 809f08c3bdfSopenharmony_ci break; 810f08c3bdfSopenharmony_ci case ASCII: 811f08c3bdfSopenharmony_ci memcpy(b, a, NBPW); 812f08c3bdfSopenharmony_ci for (p = b; (p - b) < (int)NBPW; ++p) { 813f08c3bdfSopenharmony_ci if (*p < '!' || *p > '~') 814f08c3bdfSopenharmony_ci *p = '.'; 815f08c3bdfSopenharmony_ci } 816f08c3bdfSopenharmony_ci printf("%8.8s ", b); 817f08c3bdfSopenharmony_ci break; 818f08c3bdfSopenharmony_ci default: 819f08c3bdfSopenharmony_ci printf("%22.22lo ", *word); 820f08c3bdfSopenharmony_ci break; 821f08c3bdfSopenharmony_ci } 822f08c3bdfSopenharmony_ci } 823f08c3bdfSopenharmony_ci if (format != ASCII) { 824f08c3bdfSopenharmony_ci /* 825f08c3bdfSopenharmony_ci * print the ascii equivalent of the last words in the buffer 826f08c3bdfSopenharmony_ci * before returning. 827f08c3bdfSopenharmony_ci */ 828f08c3bdfSopenharmony_ci memset(c, 0x00, width * NBPW); 829f08c3bdfSopenharmony_ci if (extra_words) 830f08c3bdfSopenharmony_ci width = extra_words; /* odd number of words */ 831f08c3bdfSopenharmony_ci memcpy(c, a - (width * NBPW), width * NBPW); 832f08c3bdfSopenharmony_ci for (p = c; (p - c) < (int)(width * NBPW); ++p) { 833f08c3bdfSopenharmony_ci if (*p < '!' || *p > '~') 834f08c3bdfSopenharmony_ci *p = '.'; 835f08c3bdfSopenharmony_ci } 836f08c3bdfSopenharmony_ci if (width == 2) 837f08c3bdfSopenharmony_ci printf("\t%16.16s", c); 838f08c3bdfSopenharmony_ci else 839f08c3bdfSopenharmony_ci printf("\t\t%16.8s", c); 840f08c3bdfSopenharmony_ci } 841f08c3bdfSopenharmony_ci printf("\n"); 842f08c3bdfSopenharmony_ci fflush(stdout); 843f08c3bdfSopenharmony_ci} 844f08c3bdfSopenharmony_ci 845f08c3bdfSopenharmony_cistatic void prt_examples(void) 846f08c3bdfSopenharmony_ci{ 847f08c3bdfSopenharmony_ci printf("%s -c 5 -i 0 -s 4090 -b\n", TCID); 848f08c3bdfSopenharmony_ci printf("%s -c 5 -i 0 -s 4090 -b -u \n", TCID); 849f08c3bdfSopenharmony_ci printf("%s -c 5 -i 0 -s 4090 -b -W 3 -w 3 \n", TCID); 850f08c3bdfSopenharmony_ci} 851f08c3bdfSopenharmony_ci 852f08c3bdfSopenharmony_cistatic void sig_child(int sig) 853f08c3bdfSopenharmony_ci{ 854f08c3bdfSopenharmony_ci int status; 855f08c3bdfSopenharmony_ci 856f08c3bdfSopenharmony_ci nchildcompleted++; 857f08c3bdfSopenharmony_ci#if DEBUG 858f08c3bdfSopenharmony_ci #define STR "parent: received SIGCHLD\n" 859f08c3bdfSopenharmony_ci write(STDOUT_FILENO, str, strlen(STR)); 860f08c3bdfSopenharmony_ci#endif 861f08c3bdfSopenharmony_ci waitpid(-1, &status, WNOHANG); 862f08c3bdfSopenharmony_ci} 863