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 (at) us.ibm.com */ 21 /* 11/01/2002 Port to LTP robbiew (at) 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 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 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 */ 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 */ 219 void blenter() 220 { 221 local_flag = PASSED; 222 return; 223 } 224 225 /* 226 * 227 * Function: anyfail() 228 * 229 * Description: Exit a test. 230 */ 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 */ 244 void ok_exit() 245 { 246 local_flag = PASSED; 247 return; 248 } 249 250 /* 251 * forkfail() 252 * 253 * exit on failure 254 */ 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 */ 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 */ 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