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
53 void on_mem_fault(int sig);
54
55 char *TCID = "mem02";
56 int TST_TOTAL = 1;
57
usage(char * progname)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
main(int argc,char ** argv)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 */
on_mem_fault(int sig)233 void on_mem_fault(int sig)
234 {
235 tst_brkm(TFAIL, NULL, "\tTest failed on receipt of a SIGSEGV signal");
236 }
237