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