blob: 32d882f4ab1bcaa484e2662cfd7c292189d8c01e [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
plars865695b2001-08-27 22:15:12 +000018 */
19
20/*
21 * NAME
22 * pipe11.c
23 *
24 * DESCRIPTION
25 * Check if many children can read what is written to a pipe by the
26 * parent.
27 *
28 * ALGORITHM
29 * 1. Open a pipe and write to it
30 * 2. Fork a large number of children
31 * 3. Have the children read the pipe and check how many characters
32 * each got
33 *
34 * USAGE: <for command-line>
35 * pipe11 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
36 * where, -c n : Run n copies concurrently.
37 * -f : Turn off functionality Testing.
38 * -i n : Execute test n times.
39 * -I x : Execute test for x seconds.
40 * -P x : Pause for x seconds between iterations.
41 * -t : Turn on syscall timing.
42 *
43 * HISTORY
44 * 07/2001 Ported by Wayne Boyer
45 *
46 * RESTRICTIONS
47 * None
48 */
plars74948ad2002-11-14 16:16:14 +000049#include <sys/types.h>
50#include <sys/wait.h>
plars865695b2001-08-27 22:15:12 +000051#include <errno.h>
52#include <stdio.h>
53#include <limits.h>
54#include "test.h"
plars865695b2001-08-27 22:15:12 +000055
56char *TCID = "pipe11";
57int TST_TOTAL = 1;
plars865695b2001-08-27 22:15:12 +000058
robbiewd34d5812005-07-11 22:28:09 +000059void do_child(void);
60void do_child_uclinux(void);
plars865695b2001-08-27 22:15:12 +000061void setup(void);
62void cleanup(void);
63
64#define NUMCHILD 50
65#define NCPERCHILD 50
subrata_modak56207ce2009-03-23 13:35:39 +000066char rawchars[] =
67 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
plars865695b2001-08-27 22:15:12 +000068int kidid;
69int numchild; /* no of children to fork */
70int ncperchild; /* no of chars child should read */
71int szcharbuf; /* size of char buf */
72int pipewrcnt; /* chars written to pipe */
73char *wrbuf, *rdbuf;
robbiewd34d5812005-07-11 22:28:09 +000074int fd[2]; /* fds for pipe read/write */
plars865695b2001-08-27 22:15:12 +000075
robbiewa728d282003-09-08 21:36:41 +000076ssize_t safe_read(int fd, void *buf, size_t count)
77{
78 ssize_t n;
79
80 do {
81 n = read(fd, buf, count);
82 } while (n < 0 && errno == EINTR);
83
84 return n;
85}
86
plars74948ad2002-11-14 16:16:14 +000087int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +000088{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020089 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020090 const char *msg;
plars865695b2001-08-27 22:15:12 +000091
plars865695b2001-08-27 22:15:12 +000092 int i;
plars74948ad2002-11-14 16:16:14 +000093 int fork_ret, status;
subrata_modak56207ce2009-03-23 13:35:39 +000094 int written; /* no of chars read and written */
plars865695b2001-08-27 22:15:12 +000095
Garrett Cooper45e285d2010-11-22 12:19:25 -080096 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) {
Garrett Cooper60fa8012010-11-22 13:50:58 -080097 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Wanlong Gao354ebb42012-12-07 10:10:04 +080098 }
robbiewd34d5812005-07-11 22:28:09 +000099#ifdef UCLINUX
100 maybe_run_child(&do_child_uclinux, "ddddd", &fd[0], &fd[1], &kidid,
101 &ncperchild, &szcharbuf);
102#endif
103
plars865695b2001-08-27 22:15:12 +0000104 setup();
105
106 for (lc = 0; TEST_LOOPING(lc); lc++) {
107
Caspar Zhangd59a6592013-03-07 14:59:12 +0800108 /* reset tst_count in case we are looping */
109 tst_count = 0;
plars865695b2001-08-27 22:15:12 +0000110
111 TEST(pipe(fd));
112
113 if (TEST_RETURN != 0) {
114 tst_resm(TFAIL, "pipe creation failed");
115 continue;
116 }
117
plars865695b2001-08-27 22:15:12 +0000118 written = write(fd[1], wrbuf, szcharbuf);
119 if (written != szcharbuf) {
120 tst_brkm(TBROK, cleanup, "write to pipe failed");
121 }
122
Wanlong Gao354ebb42012-12-07 10:10:04 +0800123refork:
plars865695b2001-08-27 22:15:12 +0000124 ++kidid;
robbiewd34d5812005-07-11 22:28:09 +0000125 fork_ret = FORK_OR_VFORK();
plars865695b2001-08-27 22:15:12 +0000126
127 if (fork_ret < 0) {
128 tst_brkm(TBROK, cleanup, "fork() failed");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800129 }
plars865695b2001-08-27 22:15:12 +0000130
131 if ((fork_ret != 0) && (fork_ret != -1) && (kidid < numchild)) {
132 goto refork;
133 }
134
subrata_modak56207ce2009-03-23 13:35:39 +0000135 if (fork_ret == 0) { /* child */
robbiewd34d5812005-07-11 22:28:09 +0000136#ifdef UCLINUX
137 if (self_exec(av[0], "ddddd", fd[0], fd[1], kidid,
138 ncperchild, szcharbuf) < 0) {
139 tst_brkm(TBROK, cleanup, "self_exec failed");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800140 }
robbiewd34d5812005-07-11 22:28:09 +0000141#else
142 do_child();
143#endif
plars865695b2001-08-27 22:15:12 +0000144 }
145
146 /* parent */
147 sleep(5);
148 tst_resm(TINFO, "There are %d children to wait for", kidid);
149 for (i = 1; i <= kidid; ++i) {
150 wait(&status);
151 if (status == 0) {
152 tst_resm(TPASS, "child %d exitted successfully",
153 i);
154 } else {
155 tst_resm(TFAIL, "child %d exitted with bad "
156 "status", i);
157 }
158 }
159 }
160 cleanup();
161
Garrett Cooper53740502010-12-16 00:04:01 -0800162 tst_exit();
plars865695b2001-08-27 22:15:12 +0000163}
164
165/*
robbiewd34d5812005-07-11 22:28:09 +0000166 * do_child()
167 */
Mike Frysingerc57fba52014-04-09 18:56:30 -0400168void do_child(void)
robbiewd34d5812005-07-11 22:28:09 +0000169{
170 int nread;
171
172 if (close(fd[1])) {
173 tst_resm(TINFO, "child %d " "could not close pipe", kidid);
174 exit(0);
175 }
176 nread = safe_read(fd[0], rdbuf, ncperchild);
177 if (nread == ncperchild) {
178 tst_resm(TINFO, "child %d " "got %d chars", kidid, nread);
179 exit(0);
180 } else {
181 tst_resm(TFAIL, "child %d did not receive expected no of "
182 "characters, got %d characters", kidid, nread);
183 exit(1);
184 }
185}
186
subrata_modak4bb656a2009-02-26 12:02:09 +0000187/*
robbiewd34d5812005-07-11 22:28:09 +0000188 * do_child_uclinux() - as above, but mallocs rdbuf first
189 */
Mike Frysingerc57fba52014-04-09 18:56:30 -0400190void do_child_uclinux(void)
robbiewd34d5812005-07-11 22:28:09 +0000191{
Cyril Hrubis4e2bab82014-09-24 16:34:35 +0200192 if ((rdbuf = malloc(szcharbuf)) == NULL) {
robbiewd34d5812005-07-11 22:28:09 +0000193 tst_brkm(TBROK, cleanup, "malloc of rdbuf failed");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800194 }
robbiewd34d5812005-07-11 22:28:09 +0000195
196 do_child();
197}
198
robbiewd34d5812005-07-11 22:28:09 +0000199/*
plars865695b2001-08-27 22:15:12 +0000200 * setup() - performs all ONE TIME setup for this test.
201 */
Mike Frysingerc57fba52014-04-09 18:56:30 -0400202void setup(void)
plars865695b2001-08-27 22:15:12 +0000203{
204 int i, j;
205
plars865695b2001-08-27 22:15:12 +0000206 tst_sig(FORK, DEF_HANDLER, cleanup);
207
plars865695b2001-08-27 22:15:12 +0000208 TEST_PAUSE;
209
210 numchild = NUMCHILD;
211 ncperchild = NCPERCHILD;
212
213 kidid = 0;
214
215 /* allocate read and write buffers */
216 szcharbuf = numchild * ncperchild;
217
218 /* make sure pipe write doesn't block */
219 if (szcharbuf == PIPE_BUF) {
220 /* adjust number of characters per child */
221 ncperchild = szcharbuf / numchild;
222 }
223
Cyril Hrubis4e2bab82014-09-24 16:34:35 +0200224 if ((wrbuf = malloc(szcharbuf)) == NULL) {
plars865695b2001-08-27 22:15:12 +0000225 tst_brkm(TBROK, cleanup, "malloc failed");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800226 }
plars865695b2001-08-27 22:15:12 +0000227
Cyril Hrubis4e2bab82014-09-24 16:34:35 +0200228 if ((rdbuf = malloc(szcharbuf)) == NULL) {
plars865695b2001-08-27 22:15:12 +0000229 tst_brkm(TBROK, cleanup, "malloc of rdbuf failed");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800230 }
plars865695b2001-08-27 22:15:12 +0000231
232 /* initialize wrbuf */
233 j = 0;
subrata_modak56207ce2009-03-23 13:35:39 +0000234 for (i = 0; i < szcharbuf;) {
plars865695b2001-08-27 22:15:12 +0000235 wrbuf[i++] = rawchars[j++];
236 if (j >= sizeof(rawchars)) {
237 j = 0;
238 }
239 }
240}
241
242/*
243 * cleanup() - performs all ONE TIME cleanup for this test at
244 * completion or premature exit.
245 */
Mike Frysingerc57fba52014-04-09 18:56:30 -0400246void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000247{
plars865695b2001-08-27 22:15:12 +0000248
Chris Dearmanec6edca2012-10-17 19:54:01 -0700249}