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
get_pagesize_order(void)65 static int get_pagesize_order(void)
66 {
67 int i, pagesize, size = 0;
68 pagesize = sysconf(_SC_PAGESIZE);
69 for (i = 0; size != pagesize; i++)
70 size = 1 << i;
71 return (i - 1);
72 }
73
main(int argc,char ** argv)74 int main(int argc, char **argv)
75 {
76 int i;
77 char *pm1, *pm2, *pm3, *pm4;
78 void *memptr;
79 long laddr;
80 int iteration_count;
81 int size; /* Size to memory to be valloced */
82 int pagesize_order = get_pagesize_order();
83 int memsize = MEMSIZE; /* Size of memory to allocate */
84 extern char *optarg; /* getopt() function global variables */
85 extern int optopt; /* stores bad option passed to the program */
86 int ch;
87
88 optarg = NULL;
89 opterr = 0;
90
91 while ((ch = getopt(argc, argv, "m:")) != -1) {
92 switch (ch) {
93 case 'm':
94 if (optarg)
95 memsize = atoi(optarg) * 1024 * 1024;
96 else
97 fprintf(stderr, "%s: option -%c requires "
98 "an argument\n", argv[0], optopt);
99 break;
100 default:
101 usage(argv[0]);
102 exit(1);
103 }
104 }
105
106 /* check out calloc/free */
107 if ((pm2 = pm1 = calloc(memsize, 1)) == NULL) {
108
109 tst_brkm(TFAIL, NULL, "calloc - alloc of %dMB failed",
110 memsize / 1024 / 1024);
111 }
112
113 for (i = 0; i < memsize; i++)
114 if (*pm2++ != 0) {
115 tst_brkm(TFAIL, NULL,
116 "calloc returned non zero memory");
117 }
118
119 pm2 = pm1;
120 for (i = 0; i < memsize; i++)
121 *pm2++ = 'X';
122 pm2 = pm1;
123 for (i = 0; i < memsize; i++)
124 if (*pm2++ != 'X') {
125 tst_brkm(TFAIL, NULL,
126 "could not write/verify memory ");
127 }
128
129 free(pm1);
130
131 tst_resm(TPASS, "calloc - calloc of %uMB of memory succeeded",
132 memsize / 1024 / 1024);
133
134 /*--------------------------------------------------------------------*/
135
136 /* check out malloc/free */
137 if ((pm2 = pm1 = malloc(memsize)) == NULL) {
138 tst_brkm(TFAIL, NULL, "malloc did not alloc memory ");
139 }
140
141 for (i = 0; i < memsize; i++)
142 *pm2++ = 'X';
143 pm2 = pm1;
144 for (i = 0; i < memsize; i++)
145 if (*pm2++ != 'X') {
146 tst_brkm(TFAIL, NULL,
147 "could not write/verify memory ");
148 }
149
150 free(pm1);
151
152 tst_resm(TPASS, "malloc - malloc of %uMB of memory succeeded",
153 memsize / 1024 / 1024);
154
155 /*--------------------------------------------------------------------*/
156
157 /* check out realloc */
158
159 pm4 = pm3 = malloc(10);
160 for (i = 0; i < 10; i++)
161 *pm4++ = 'X';
162
163 /* realloc with reduced size */
164 pm4 = realloc(pm3, 5);
165 pm3 = pm4;
166 /* verify contents did not change */
167 for (i = 0; i < 5; i++) {
168 if (*pm4++ != 'X') {
169 tst_brkm(TFAIL, NULL,
170 "realloc changed memory contents");
171 }
172 }
173
174 tst_resm(TPASS, "realloc - realloc of 5 bytes succeeded");
175
176 /* realloc with increased size after fragmenting memory */
177 pm4 = realloc(pm3, 15);
178 pm3 = pm4;
179 /* verify contents did not change */
180 for (i = 0; i < 5; i++) {
181 if (*pm3++ != 'X') {
182 tst_brkm(TFAIL, NULL,
183 "realloc changed memory contents");
184 }
185 }
186
187 tst_resm(TPASS, "realloc - realloc of 15 bytes succeeded");
188 free(pm4);
189
190 /*--------------------------------------------------------------------*/
191 /*
192 * Check out for valloc failures
193 */
194
195 /*
196 * Setup to catch the memory fault, otherwise the core might
197 * be dumped on failures.
198 */
199 if ((signal(SIGSEGV, on_mem_fault)) == SIG_ERR) {
200 tst_brkm(TFAIL, NULL,
201 "Could not get signal handler for SIGSEGV");
202 }
203
204 srand(1); /* Ensure Determinism */
205
206 for (iteration_count = 15000; iteration_count > 0; iteration_count--) {
207 /*
208 * size is a fraction of 100000 and is determined by rand().
209 */
210 size = (int)((rand() / (float)RAND_MAX) * 100000) + 1;
211 memptr = valloc(size);
212
213 /*
214 * Check to see if valloc returns unaligned data.
215 * This can be done by copying the memory address into
216 * a variable and the by diving and multipying the address
217 * by the pagesize order and checking.
218 */
219 laddr = (long)memptr;
220 if (((laddr >> pagesize_order) << pagesize_order) != laddr) {
221 tst_brkm(TFAIL, NULL,
222 "Valloc returned unaligned data");
223 }
224
225 free(memptr);
226 }
227 tst_resm(TPASS, "valloc - valloc of rand() size of memory succeeded "
228 "for 15000 iteration");
229
230 tst_exit();
231 }
232
233 /*
234 * void
235 * on_mem_fault(int sig)
236 *
237 * on_mem_fault() is a signal handler used by the valloc test-case
238 * (block 3). This function will catch the signal, indicate a failure,
239 * write to the log file (a failure message) and exit the test.
240 */
on_mem_fault(int sig)241 void on_mem_fault(int sig)
242 {
243 tst_brkm(TFAIL, NULL, "\tTest failed on receipt of a SIGSEGV signal");
244 }
245