• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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
17  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
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  */
49 #include <sys/types.h>
50 #include <sys/wait.h>
51 #include <errno.h>
52 #include <stdio.h>
53 #include <limits.h>
54 #include "test.h"
55 
56 char *TCID = "pipe11";
57 int TST_TOTAL = 1;
58 
59 void do_child(void);
60 void do_child_uclinux(void);
61 void setup(void);
62 void cleanup(void);
63 
64 #define	NUMCHILD	50
65 #define	NCPERCHILD	50
66 char rawchars[] =
67     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
68 int kidid;
69 int numchild;			/* no of children to fork */
70 int ncperchild;			/* no of chars child should read */
71 int szcharbuf;			/* size of char buf */
72 int pipewrcnt;			/* chars written to pipe */
73 char *wrbuf, *rdbuf;
74 int fd[2];			/* fds for pipe read/write */
75 
do_read(int fd,void * buf,size_t count)76 ssize_t do_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 
main(int ac,char ** av)87 int main(int ac, char **av)
88 {
89 	int lc;
90 
91 	int i;
92 	int fork_ret, status;
93 	int written;		/* no of chars read and written */
94 
95 	tst_parse_opts(ac, av, NULL, NULL);
96 #ifdef UCLINUX
97 	maybe_run_child(&do_child_uclinux, "ddddd", &fd[0], &fd[1], &kidid,
98 			&ncperchild, &szcharbuf);
99 #endif
100 
101 	setup();
102 
103 	for (lc = 0; TEST_LOOPING(lc); lc++) {
104 
105 		/* reset tst_count in case we are looping */
106 		tst_count = 0;
107 
108 		TEST(pipe(fd));
109 
110 		if (TEST_RETURN != 0) {
111 			tst_resm(TFAIL, "pipe creation failed");
112 			continue;
113 		}
114 
115 		written = write(fd[1], wrbuf, szcharbuf);
116 		if (written != szcharbuf) {
117 			tst_brkm(TBROK, cleanup, "write to pipe failed");
118 		}
119 
120 refork:
121 		++kidid;
122 		fork_ret = FORK_OR_VFORK();
123 
124 		if (fork_ret < 0) {
125 			tst_brkm(TBROK, cleanup, "fork() failed");
126 		}
127 
128 		if ((fork_ret != 0) && (fork_ret != -1) && (kidid < numchild)) {
129 			goto refork;
130 		}
131 
132 		if (fork_ret == 0) {	/* child */
133 #ifdef UCLINUX
134 			if (self_exec(av[0], "ddddd", fd[0], fd[1], kidid,
135 				      ncperchild, szcharbuf) < 0) {
136 				tst_brkm(TBROK, cleanup, "self_exec failed");
137 			}
138 #else
139 			do_child();
140 #endif
141 		}
142 
143 		/* parent */
144 		sleep(5);
145 		tst_resm(TINFO, "There are %d children to wait for", kidid);
146 		for (i = 1; i <= kidid; ++i) {
147 			wait(&status);
148 			if (status == 0) {
149 				tst_resm(TPASS, "child %d exitted successfully",
150 					 i);
151 			} else {
152 				tst_resm(TFAIL, "child %d exitted with bad "
153 					 "status", i);
154 			}
155 		}
156 	}
157 	cleanup();
158 
159 	tst_exit();
160 }
161 
162 /*
163  * do_child()
164  */
do_child(void)165 void do_child(void)
166 {
167 	int nread;
168 
169 	if (close(fd[1])) {
170 		tst_resm(TINFO, "child %d " "could not close pipe", kidid);
171 		exit(0);
172 	}
173 	nread = do_read(fd[0], rdbuf, ncperchild);
174 	if (nread == ncperchild) {
175 		tst_resm(TINFO, "child %d " "got %d chars", kidid, nread);
176 		exit(0);
177 	} else {
178 		tst_resm(TFAIL, "child %d did not receive expected no of "
179 			 "characters, got %d characters", kidid, nread);
180 		exit(1);
181 	}
182 }
183 
184 /*
185  * do_child_uclinux() - as above, but mallocs rdbuf first
186  */
do_child_uclinux(void)187 void do_child_uclinux(void)
188 {
189 	if ((rdbuf = malloc(szcharbuf)) == NULL) {
190 		tst_brkm(TBROK, cleanup, "malloc of rdbuf failed");
191 	}
192 
193 	do_child();
194 }
195 
196 /*
197  * setup() - performs all ONE TIME setup for this test.
198  */
setup(void)199 void setup(void)
200 {
201 	int i, j;
202 
203 	tst_sig(FORK, DEF_HANDLER, cleanup);
204 
205 	TEST_PAUSE;
206 
207 	numchild = NUMCHILD;
208 	ncperchild = NCPERCHILD;
209 
210 	kidid = 0;
211 
212 	/* allocate read and write buffers */
213 	szcharbuf = numchild * ncperchild;
214 
215 	/* make sure pipe write doesn't block */
216 	if (szcharbuf == PIPE_BUF) {
217 		/* adjust number of characters per child */
218 		ncperchild = szcharbuf / numchild;
219 	}
220 
221 	if ((wrbuf = malloc(szcharbuf)) == NULL) {
222 		tst_brkm(TBROK, cleanup, "malloc failed");
223 	}
224 
225 	if ((rdbuf = malloc(szcharbuf)) == NULL) {
226 		tst_brkm(TBROK, cleanup, "malloc of rdbuf failed");
227 	}
228 
229 	/* initialize wrbuf */
230 	j = 0;
231 	for (i = 0; i < szcharbuf;) {
232 		wrbuf[i++] = rawchars[j++];
233 		if (j >= sizeof(rawchars)) {
234 			j = 0;
235 		}
236 	}
237 }
238 
239 /*
240  * cleanup() - performs all ONE TIME cleanup for this test at
241  *	       completion or premature exit.
242  */
cleanup(void)243 void cleanup(void)
244 {
245 
246 }
247