Home | History | Annotate | Download | only in mem
      1 /*
      2  *
      3  *   Copyright (c) International Business Machines  Corp., 2002
      4  *   Copyright (c) 2012 Cyril Hrubis <chrubis (at) suse.cz>
      5  *
      6  *   This program is free software;  you can redistribute it and/or modify
      7  *   it under the terms of the GNU General Public License as published by
      8  *   the Free Software Foundation; either version 2 of the License, or
      9  *   (at your option) any later version.
     10  *
     11  *   This program is distributed in the hope that it will be useful,
     12  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
     13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
     14  *   the GNU General Public License for more details.
     15  *
     16  *   You should have received a copy of the GNU General Public License
     17  *   along with this program;  if not, write to the Free Software
     18  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     19  */
     20 
     21 /* IBM Corporation */
     22 /* 06/30/2001	Port to Linux	nsharoff (at) us.ibm.com */
     23 /* 10/30/2002	Port to LTP	dbarrera (at) us.ibm.com */
     24 
     25 /*======================================================================
     26 /	=================== TESTPLAN SEGMENT ===================
     27 >KEYS:	< calloc, malloc, free, realloc, valloc
     28 >WHAT:	< check that memory can be allocated and freed. check for zeroed
     29    	< memory.
     30 >HOW:	< Allocate a big chunk of memory, verify it is available (zeroed
     31 	< in the case of calloc).
     32 	< Write into it and verify, free memory and verify free was
     33 	< successful.
     34 	< In the case of valloc, allocate memory and free it (do this for
     35 	< several iterations). Check if valloc returns unaligned pointers.
     36 	< If valloc causes a SIGSEGV, that means a failure has occured.
     37 >BUGS:	<
     38 ======================================================================*/
     39 
     40 #include <stdio.h>
     41 #include <signal.h>
     42 #include <stdlib.h>
     43 #include "test.h"
     44 #include <unistd.h>
     45 #include <errno.h>
     46 #include <time.h>
     47 #include <string.h>
     48 #include <sys/types.h>
     49 #include <sys/user.h>
     50 
     51 #define MEMSIZE	8192*8192
     52 
     53 void on_mem_fault(int sig);
     54 
     55 char *TCID = "mem02";
     56 int TST_TOTAL = 1;
     57 
     58 static void usage(char *progname)
     59 {
     60 	fprintf(stderr, "usage: %s -m memsize\n", progname);
     61 	fprintf(stderr, "\t-m specify the size of memory to allocate, in MB\n");
     62 	exit(1);
     63 }
     64 
     65 int main(int argc, char **argv)
     66 {
     67 	int i;
     68 	char *pm1, *pm2, *pm3, *pm4;
     69 	long pm6;
     70 	void *memptr;
     71 	long laddr;
     72 	int iteration_count;
     73 	int size;		/* Size to memory to be valloced */
     74 	int pagesize = 12;	/* 2^12 = 4096, PAGESIZE      */
     75 	int memsize = MEMSIZE;	/* Size of memory to allocate */
     76 	extern char *optarg;	/* getopt() function global variables */
     77 	extern int optopt;	/* stores bad option passed to the program */
     78 	int ch;
     79 
     80 	optarg = NULL;
     81 	opterr = 0;
     82 
     83 	while ((ch = getopt(argc, argv, "m:")) != -1) {
     84 		switch (ch) {
     85 		case 'm':
     86 			if (optarg)
     87 				memsize = atoi(optarg) * 1024 * 1024;
     88 			else
     89 				fprintf(stderr, "%s: option -%c requires "
     90 					"an argument\n", argv[0], optopt);
     91 			break;
     92 		default:
     93 			usage(argv[0]);
     94 			exit(1);
     95 		}
     96 	}
     97 
     98 	/* check out calloc/free */
     99 	if ((pm2 = pm1 = calloc(memsize, 1)) == NULL) {
    100 
    101 		tst_brkm(TFAIL, NULL, "calloc - alloc of %dMB failed",
    102 			 memsize / 1024 / 1024);
    103 	}
    104 
    105 	for (i = 0; i < memsize; i++)
    106 		if (*pm2++ != 0) {
    107 			tst_brkm(TFAIL, NULL,
    108 				 "calloc returned non zero memory");
    109 		}
    110 
    111 	pm2 = pm1;
    112 	for (i = 0; i < memsize; i++)
    113 		*pm2++ = 'X';
    114 	pm2 = pm1;
    115 	for (i = 0; i < memsize; i++)
    116 		if (*pm2++ != 'X') {
    117 			tst_brkm(TFAIL, NULL,
    118 				 "could not write/verify memory ");
    119 		}
    120 
    121 	free(pm1);
    122 
    123 	tst_resm(TPASS, "calloc - calloc of %uMB of memory succeeded",
    124 		 memsize / 1024 / 1024);
    125 
    126 /*--------------------------------------------------------------------*/
    127 
    128 	/* check out malloc/free */
    129 	if ((pm2 = pm1 = malloc(memsize)) == NULL) {
    130 		tst_brkm(TFAIL, NULL, "malloc did not alloc memory ");
    131 	}
    132 
    133 	for (i = 0; i < memsize; i++)
    134 		*pm2++ = 'X';
    135 	pm2 = pm1;
    136 	for (i = 0; i < memsize; i++)
    137 		if (*pm2++ != 'X') {
    138 			tst_brkm(TFAIL, NULL,
    139 				 "could not write/verify memory ");
    140 		}
    141 
    142 	free(pm1);
    143 
    144 	tst_resm(TPASS, "malloc - malloc of %uMB of memory succeeded",
    145 		 memsize / 1024 / 1024);
    146 
    147 /*--------------------------------------------------------------------*/
    148 
    149 	/* check out realloc */
    150 
    151 	pm4 = pm3 = malloc(10);
    152 	for (i = 0; i < 10; i++)
    153 		*pm4++ = 'X';
    154 
    155 	/* realloc with reduced size */
    156 	pm4 = realloc(pm3, 5);
    157 	pm6 = (long)pm4;
    158 	pm3 = pm4;
    159 	/* verify contents did not change */
    160 	for (i = 0; i < 5; i++) {
    161 		if (*pm4++ != 'X') {
    162 			tst_brkm(TFAIL, NULL,
    163 				 "realloc changed memory contents");
    164 		}
    165 	}
    166 
    167 	tst_resm(TPASS, "realloc - realloc of 5 bytes succeeded");
    168 
    169 	/* realloc with increased size after fragmenting memory */
    170 	pm4 = realloc(pm3, 15);
    171 	pm6 = (long)pm3;
    172 	pm3 = pm4;
    173 	/* verify contents did not change */
    174 	for (i = 0; i < 5; i++) {
    175 		if (*pm3++ != 'X') {
    176 			tst_brkm(TFAIL, NULL,
    177 				 "realloc changed memory contents");
    178 		}
    179 	}
    180 
    181 	tst_resm(TPASS, "realloc - realloc of 15 bytes succeeded");
    182 	free(pm4);
    183 
    184 /*--------------------------------------------------------------------*/
    185 	/*
    186 	 * Check out for valloc failures
    187 	 */
    188 
    189 	/*
    190 	 * Setup to catch the memory fault, otherwise the core might
    191 	 * be dumped on failures.
    192 	 */
    193 	if ((signal(SIGSEGV, on_mem_fault)) == SIG_ERR) {
    194 		tst_brkm(TFAIL, NULL,
    195 			 "Could not get signal handler for SIGSEGV");
    196 	}
    197 
    198 	srand(1);		/* Ensure Determinism         */
    199 
    200 	for (iteration_count = 15000; iteration_count > 0; iteration_count--) {
    201 		/*
    202 		 * size is a fraction of 100000 and is determined by rand().
    203 		 */
    204 		size = (int)((rand() / (float)RAND_MAX) * 100000) + 1;
    205 		memptr = valloc(size);
    206 
    207 		/*
    208 		 * Check to see if valloc returns unaligned data.
    209 		 * This can be done by copying the memory address into
    210 		 * a variable and the by diving and multipying the address
    211 		 * by the pagesize and checking.
    212 		 */
    213 		laddr = (long)memptr;
    214 		if (((laddr >> pagesize) << pagesize) != laddr) {
    215 			tst_brkm(TFAIL, NULL,
    216 				 "Valloc returned unaligned data");
    217 		}
    218 
    219 		free(memptr);
    220 	}
    221 
    222 	tst_exit();
    223 }
    224 
    225 /*
    226  * void
    227  * on_mem_fault(int sig)
    228  *
    229  *	on_mem_fault() is a signal handler used by the valloc test-case
    230  *	(block 3). This function will catch the signal, indicate a failure,
    231  *	write to the log file (a failure message) and exit the test.
    232  */
    233 void on_mem_fault(int sig)
    234 {
    235 	tst_brkm(TFAIL, NULL, "\tTest failed on receipt of a SIGSEGV signal");
    236 }
    237