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 /* 11/05/2002 Port to LTP robbiew@us.ibm.com */
21 /* 06/30/2001 Port to Linux nsharoff@us.ibm.com */
22
23 /* page02.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 Writes start in middle of array and proceede to ends.
37 >BUGS: <
38 ======================================================================*/
39
40 #include <stdio.h>
41 #include <signal.h>
42 #include <errno.h>
43
44 #ifdef LINUX
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <stdlib.h>
48 #include <sys/wait.h>
49 #endif
50
51 /** LTP Port **/
52 #include "test.h"
53
54 #define FAILED 0
55 #define PASSED 1
56
57 int local_flag = PASSED;
58 int block_number;
59
60 char *TCID = "page02"; /* Test program identifier. */
61 int TST_TOTAL = 1; /* Total number of test cases. */
62 /**************/
63
64 int bd_arg(char *);
65 int chld_flag;
66 int parent_pid;
67
main(argc,argv)68 int main(argc, argv)
69 int argc;
70 char *argv[];
71 {
72 int nchild;
73 int memory_size, half_memory_size;
74 int error_count, i, j, pid, status;
75 int *memory_pointer;
76 int *up_pointer, *down_pointer;
77 int child, count;
78 int chld();
79
80 parent_pid = getpid();
81 tst_tmpdir();
82
83 if (signal(SIGUSR1, (void (*)())chld) == SIG_ERR) {
84 tst_resm(TBROK, "signal failed");
85 exit(1);
86 }
87
88 if (argc < 2) {
89 memory_size = 128 * 1024;
90 nchild = 5;
91 } else if (argc == 3) {
92 if (sscanf(argv[1], "%d", &memory_size) != 1)
93 bd_arg(argv[1]);
94 if (sscanf(argv[2], "%d", &nchild) != 1)
95 bd_arg(argv[2]);
96 } else {
97 printf("page02 [memory size (words)] [nchild]\n");
98 tst_resm(TCONF, "\tBad arg count.\n");
99 exit(1);
100 }
101 half_memory_size = memory_size / 2;
102
103 error_count = 0;
104
105 /****************************************/
106 /* */
107 /* attempt to fork a number of */
108 /* identical processes */
109 /* */
110 /****************************************/
111
112 for (i = 1; i <= nchild; i++) {
113 chld_flag = 0;
114 if ((pid = fork()) == -1) {
115 tst_resm(TBROK,
116 "Fork failed (may be OK if under stress)");
117 tst_resm(TINFO, "System resource may be too low.\n");
118 local_flag = PASSED;
119 tst_brkm(TBROK, tst_rmdir, "Reason: %s\n",
120 strerror(errno));
121 } else if (pid == 0) {
122 /********************************/
123 /* */
124 /* allocate memory of size */
125 /* "memory_size" */
126 /* */
127 /********************************/
128
129 memory_pointer = malloc(memory_size * sizeof(int));
130 if (memory_pointer == 0) {
131 tst_resm(TBROK, "\tCannot malloc memory.\n");
132 if (i < 2) {
133 tst_resm(TBROK,
134 "\tThis should not happen to first two children.\n");
135 tst_resm(TBROK, "\tChild %d - fail.\n",
136 i);
137 } else {
138 tst_resm(TBROK,
139 "\tThis is ok for all but first two children.\n");
140 tst_resm(TBROK, "\tChild %d - ok.\n",
141 i);
142 kill(parent_pid, SIGUSR1);
143 _exit(0);
144 }
145 tst_resm(TBROK, "malloc fail");
146 tst_resm(TFAIL,
147 "\t\nImpossible to allocate memory of size %d in process %d\n",
148 memory_size, i);
149 kill(parent_pid, SIGUSR1);
150 tst_exit();
151 }
152 kill(parent_pid, SIGUSR1);
153
154 down_pointer = up_pointer = memory_pointer +
155 (memory_size / 2);
156
157 /********************************/
158 /* */
159 /* write to it */
160 /* */
161 /********************************/
162
163 for (j = 1; j <= half_memory_size; j++) {
164 *(up_pointer++) = j;
165 *(down_pointer--) = j;
166 }
167 sleep(1);
168
169 /********************************/
170 /* */
171 /* and read from it to */
172 /* check that what was written */
173 /* is still there */
174 /* */
175 /********************************/
176
177 down_pointer = up_pointer = memory_pointer +
178 (memory_size / 2);
179
180 for (j = 1; j <= half_memory_size; j++) {
181 if (*(up_pointer++) != j)
182 error_count++;
183 if (*(down_pointer--) != j)
184 error_count++;
185 }
186 exit(error_count);
187 }
188 while (!chld_flag)
189 sleep(1);
190 }
191
192 /****************************************/
193 /* */
194 /* wait for the child processes */
195 /* to teminate and report the # */
196 /* of deviations recognized */
197 /* */
198 /****************************************/
199
200 count = 0;
201 while ((child = wait(&status)) > 0) {
202 #ifdef DEBUG
203 tst_resm(TINFO, "\tTest {%d} exited status %d\n", child,
204 status);
205 #endif
206 if (status)
207 local_flag = FAILED;
208 count++;
209 }
210
211 if (count != nchild) {
212 tst_resm(TFAIL, "\tWrong number of children waited on.\n");
213 tst_resm(TFAIL, "\tCount = %d, expected = %d.\n",
214 count, nchild);
215 }
216
217 (local_flag == FAILED) ? tst_resm(TFAIL, "Test failed")
218 : tst_resm(TPASS, "Test passed");
219 tst_rmdir();
220 tst_exit();
221
222 }
223
bd_arg(str)224 int bd_arg(str)
225 char *str;
226 {
227 tst_brkm(TCONF, NULL, "\tCannot parse %s as a number.\n", str);
228 }
229
chld()230 int chld()
231 {
232 if (signal(SIGUSR1, (void (*)())chld) == SIG_ERR) {
233 tst_brkm(TBROK, NULL, "signal failed");
234 }
235 chld_flag++;
236 return 0;
237 }
238