Home | History | Annotate | Download | only in page
      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