1 /*
2  *
3  *   Copyright (c) International Business Machines  Corp., 2002
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 /* 06/30/2001	Port to Linux	nsharoff@us.ibm.com */
21 /* 11/01/2002	Port to LTP  	robbiew@us.ibm.com */
22 
23 			   /* page01.c */
24 /*======================================================================
25 	=================== TESTPLAN SEGMENT ===================
26 CALLS:	malloc(3)
27 
28 	Run with KILL flag
29 
30 >KEYS:  < paging behavior
31 >WHAT:  < Does the system balk at heavy demands on it's paging facilities?
32 >HOW:   < Create a number of process, each of which requests a large
33 	< chunk of memory to be assigned to an array.  Write to each
34 	< element in that array, and verify that what was written/stored
35 	< is what was expected.
36 >BUGS:  <
37 ======================================================================*/
38 
39 #include <sys/types.h>
40 #include <sys/wait.h>
41 #include <errno.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 
45 int bd_arg(char *);
46 
47 /** LTP Port **/
48 #include "test.h"
49 
50 void blenter(void);
51 void setup(void);
52 void anyfail(void);
53 void ok_exit(void);
54 void forkfail(void);
55 void terror(char *);
56 int instress(void);
57 
58 #define FAILED 0
59 #define PASSED 1
60 
61 int local_flag = PASSED;
62 int block_number;
63 FILE *temp;
64 
65 char *TCID = "page01";		/* Test program identifier.    */
66 int TST_TOTAL = 1;		/* Total number of test cases. */
67 /**************/
68 
main(argc,argv)69 int main(argc, argv)
70 int argc;
71 char *argv[];
72 {
73 	int nchild;
74 	int memory_size;
75 	int error_count, i, j, pid, status;
76 	int *number_pointer;
77 	int *memory_pointer;
78 	int child, count;
79 
80 	setup();
81 
82 	if (argc < 2) {
83 		memory_size = 256 * 1024;
84 		nchild = 50;
85 	} else if (argc == 3) {
86 		if (sscanf(argv[1], "%d", &memory_size) != 1)
87 			bd_arg(argv[1]);
88 		if (sscanf(argv[2], "%d", &nchild) != 1)
89 			bd_arg(argv[2]);
90 	} else {
91 		printf("page01 [memory size (words)]  [nchild]\n");
92 		tst_resm(TCONF, "\tBad arg count.\n");
93 		exit(1);
94 	}
95 
96 	blenter();
97 
98 	error_count = 0;
99 
100 	/****************************************/
101 	/*                                      */
102 	/*      attempt to fork a number of     */
103 	/*      identical processes             */
104 	/*                                      */
105 	/****************************************/
106 
107 	for (i = 1; i <= nchild; i++) {
108 		if ((pid = fork()) == -1) {
109 			terror("Fork failed (may be OK if under stress)");
110 			if (instress())
111 				ok_exit();
112 			forkfail();
113 		} else if (pid == 0) {
114 			/********************************/
115 			/*                              */
116 			/*   allocate memory  of size   */
117 			/*    "memory_size"             */
118 			/*                              */
119 			/********************************/
120 
121 			memory_pointer = malloc(memory_size * sizeof(int));
122 			if (memory_pointer == 0) {
123 				tst_resm(TBROK,
124 					 "Cannot allocate memory - malloc failed.\n");
125 				if (i < 2) {
126 					tst_resm(TBROK,
127 						 "This should not happen for first two children.\n");
128 					tst_brkm(TFAIL, NULL,
129 						 "Child %d - fail.\n",
130 						 i);
131 				} else {
132 					tst_resm(TCONF,
133 						 "This is ok for all but first two children.\n");
134 					tst_brkm(TCONF, NULL,
135 						 "Child %d - ok.\n", i);
136 				}
137 			}
138 			number_pointer = memory_pointer;
139 
140 			/********************************/
141 			/*                              */
142 			/*         write to it          */
143 			/*                              */
144 			/********************************/
145 
146 			for (j = 1; j <= memory_size; j++)
147 				*(number_pointer++) = j;
148 			sleep(1);
149 
150 			/********************************/
151 			/*                              */
152 			/*      and read from it to     */
153 			/*  check that what was written */
154 			/*       is still there         */
155 			/*                              */
156 			/********************************/
157 
158 			number_pointer = memory_pointer;
159 			for (j = 1; j <= memory_size; j++) {
160 				if (*(number_pointer++) != j)
161 					error_count++;
162 			}
163 			exit(error_count);
164 		}
165 	}
166 
167 	/****************************************/
168 	/*                                      */
169 	/*      wait for the child processes    */
170 	/*      to teminate and report the #    */
171 	/*      of deviations recognized        */
172 	/*                                      */
173 	/****************************************/
174 
175 	count = 0;
176 	while ((child = wait(&status)) > 0) {
177 #ifdef DEBUG
178 		tst_resm(TINFO, "Test {%d} exited status %d\n", child, status);
179 #endif
180 		if (status)
181 			local_flag = FAILED;
182 		count++;
183 	}
184 
185 	if (count != nchild) {
186 		tst_resm(TWARN, "Wrong number of children waited on.\n");
187 		tst_resm(TWARN, "Count = %d, expected = %d.\n", count, nchild);
188 	}
189 
190 	anyfail();
191 	/** NOT REACHED **/
192 	tst_exit();
193 }
194 
bd_arg(str)195 int bd_arg(str)
196 char *str;
197 {
198 	tst_resm(TCONF, "\tCannot parse %s as a number.\n", str);
199 	exit(1);
200 }
201 
202 /** LTP Port **/
203 /*
204  * setup
205  *
206  * Do set up - here its a dummy function
207  */
setup()208 void setup()
209 {
210 	tst_tmpdir();
211 	temp = stderr;
212 }
213 
214 /*
215  * Function: blenter()
216  *
217  * Description: Print message on entering a new block
218  */
blenter()219 void blenter()
220 {
221 	local_flag = PASSED;
222 	return;
223 }
224 
225 /*
226  *
227  * Function: anyfail()
228  *
229  * Description: Exit a test.
230  */
anyfail()231 void anyfail()
232 {
233 	(local_flag == FAILED) ? tst_resm(TFAIL, "Test failed")
234 	    : tst_resm(TPASS, "Test passed");
235 	tst_rmdir();
236 	tst_exit();
237 }
238 
239 /*
240  * ok_exit
241  *
242  * Calling block passed the test
243  */
ok_exit()244 void ok_exit()
245 {
246 	local_flag = PASSED;
247 	return;
248 }
249 
250 /*
251  * forkfail()
252  *
253  * exit on failure
254  */
forkfail()255 void forkfail()
256 {
257 	tst_brkm(TBROK, tst_rmdir, "Reason: %s\n", strerror(errno));
258 }
259 
260 /*
261  * Function: terror
262  *
263  * Description: prints error message this may not be because some part of the
264  *              test case failed, for example fork() failed. We will log this
265  *              failure as TBROK instead of TFAIL.
266  */
terror(char * message)267 void terror(char *message)
268 {
269 	tst_resm(TBROK, "Reason: %s:%s\n", message, strerror(errno));
270 	return;
271 }
272 
273 /*
274  * instress
275  *
276  * Assume that we are always running under stress, so this function will
277  * return > 0 value always.
278  */
instress()279 int instress()
280 {
281 	tst_resm(TINFO, "System resource may be too low, fork() malloc()"
282 		 " etc are likely to fail.\n");
283 	return 1;
284 }
285