1/* 2 * 3 * Copyright (c) International Business Machines Corp., 2002 4 * Copyright (c) 2012 Cyril Hrubis <chrubis@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@us.ibm.com */ 23/* 10/30/2002 Port to LTP dbarrera@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 53void on_mem_fault(int sig); 54 55char *TCID = "mem02"; 56int TST_TOTAL = 1; 57 58static 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 65int 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 */ 233void on_mem_fault(int sig) 234{ 235 tst_brkm(TFAIL, NULL, "\tTest failed on receipt of a SIGSEGV signal"); 236} 237