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