Mercurial > hg > sv-dependency-builds
comparison src/fftw-3.3.3/kernel/alloc.c @ 10:37bf6b4a2645
Add FFTW3
author | Chris Cannam |
---|---|
date | Wed, 20 Mar 2013 15:35:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
9:c0fb53affa76 | 10:37bf6b4a2645 |
---|---|
1 /* | |
2 * Copyright (c) 2003, 2007-11 Matteo Frigo | |
3 * Copyright (c) 2003, 2007-11 Massachusetts Institute of Technology | |
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 the | |
13 * 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 | |
21 #include "ifftw.h" | |
22 | |
23 /********************************************************** | |
24 * DEBUGGING CODE | |
25 **********************************************************/ | |
26 #if defined(FFTW_DEBUG_MALLOC) | |
27 | |
28 #include <stdio.h> | |
29 | |
30 /* | |
31 debugging malloc/free. | |
32 | |
33 1) Initialize every malloced and freed area to random values, just | |
34 to make sure we are not using uninitialized pointers. | |
35 | |
36 2) check for blocks freed twice. | |
37 | |
38 3) Check for writes past the ends of allocated blocks | |
39 | |
40 4) destroy contents of freed blocks in order to detect incorrect reuse. | |
41 | |
42 5) keep track of who allocates what and report memory leaks | |
43 | |
44 This code is a quick and dirty hack. May be nonportable. | |
45 Use at your own risk. | |
46 | |
47 */ | |
48 | |
49 #define MAGIC ((size_t)0xABadCafe) | |
50 #define PAD_FACTOR 2 | |
51 #define SZ_HEADER (4 * sizeof(size_t)) | |
52 #define HASHSZ 1031 | |
53 | |
54 static unsigned int hashaddr(void *p) | |
55 { | |
56 return ((unsigned long)p) % HASHSZ; | |
57 } | |
58 | |
59 struct mstat { | |
60 int siz; | |
61 int maxsiz; | |
62 int cnt; | |
63 int maxcnt; | |
64 }; | |
65 | |
66 static struct mstat mstat[MALLOC_WHAT_LAST]; | |
67 | |
68 struct minfo { | |
69 const char *file; | |
70 int line; | |
71 size_t n; | |
72 void *p; | |
73 struct minfo *next; | |
74 }; | |
75 | |
76 static struct minfo *minfo[HASHSZ] = {0}; | |
77 | |
78 #if defined(HAVE_THREADS) || defined(HAVE_OPENMP) | |
79 int X(in_thread) = 0; | |
80 #endif | |
81 | |
82 void *X(malloc_debug)(size_t n, enum malloc_tag what, | |
83 const char *file, int line) | |
84 { | |
85 char *p; | |
86 size_t i; | |
87 struct minfo *info; | |
88 struct mstat *stat = mstat + what; | |
89 struct mstat *estat = mstat + EVERYTHING; | |
90 | |
91 if (n == 0) | |
92 n = 1; | |
93 | |
94 if (!IN_THREAD) { | |
95 stat->siz += n; | |
96 if (stat->siz > stat->maxsiz) | |
97 stat->maxsiz = stat->siz; | |
98 estat->siz += n; | |
99 if (estat->siz > estat->maxsiz) | |
100 estat->maxsiz = estat->siz; | |
101 } | |
102 | |
103 p = (char *) X(kernel_malloc)(PAD_FACTOR * n + SZ_HEADER); | |
104 A(p); | |
105 | |
106 /* store the sz in a known position */ | |
107 ((size_t *) p)[0] = n; | |
108 ((size_t *) p)[1] = MAGIC; | |
109 ((size_t *) p)[2] = what; | |
110 | |
111 /* fill with junk */ | |
112 for (i = 0; i < PAD_FACTOR * n; i++) | |
113 p[i + SZ_HEADER] = (char) (i ^ 0xEF); | |
114 | |
115 if (!IN_THREAD) { | |
116 ++stat->cnt; | |
117 ++estat->cnt; | |
118 | |
119 if (stat->cnt > stat->maxcnt) | |
120 stat->maxcnt = stat->cnt; | |
121 if (estat->cnt > estat->maxcnt) | |
122 estat->maxcnt = estat->cnt; | |
123 } | |
124 | |
125 /* skip the info we stored previously */ | |
126 p = p + SZ_HEADER; | |
127 | |
128 if (!IN_THREAD) { | |
129 unsigned int h = hashaddr(p); | |
130 /* record allocation in allocation list */ | |
131 info = (struct minfo *) malloc(sizeof(struct minfo)); | |
132 info->n = n; | |
133 info->file = file; | |
134 info->line = line; | |
135 info->p = p; | |
136 info->next = minfo[h]; | |
137 minfo[h] = info; | |
138 } | |
139 | |
140 return (void *) p; | |
141 } | |
142 | |
143 void X(ifree)(void *p) | |
144 { | |
145 char *q; | |
146 | |
147 A(p); | |
148 | |
149 q = ((char *) p) - SZ_HEADER; | |
150 A(q); | |
151 | |
152 { | |
153 size_t n = ((size_t *) q)[0]; | |
154 size_t magic = ((size_t *) q)[1]; | |
155 int what = ((size_t *) q)[2]; | |
156 size_t i; | |
157 struct mstat *stat = mstat + what; | |
158 struct mstat *estat = mstat + EVERYTHING; | |
159 | |
160 /* set to zero to detect duplicate free's */ | |
161 ((size_t *) q)[0] = 0; | |
162 | |
163 A(magic == MAGIC); | |
164 ((size_t *) q)[1] = ~MAGIC; | |
165 | |
166 if (!IN_THREAD) { | |
167 stat->siz -= n; | |
168 A(stat->siz >= 0); | |
169 estat->siz -= n; | |
170 A(estat->siz >= 0); | |
171 } | |
172 | |
173 /* check for writing past end of array: */ | |
174 for (i = n; i < PAD_FACTOR * n; ++i) | |
175 if (q[i + SZ_HEADER] != (char) (i ^ 0xEF)) { | |
176 A(0 /* array bounds overwritten */ ); | |
177 } | |
178 for (i = 0; i < PAD_FACTOR * n; ++i) | |
179 q[i + SZ_HEADER] = (char) (i ^ 0xAD); | |
180 | |
181 if (!IN_THREAD) { | |
182 --stat->cnt; | |
183 --estat->cnt; | |
184 | |
185 A(stat->cnt >= 0); | |
186 A((stat->cnt == 0 && stat->siz == 0) || | |
187 (stat->cnt > 0 && stat->siz > 0)); | |
188 A(estat->cnt >= 0); | |
189 A((estat->cnt == 0 && estat->siz == 0) || | |
190 (estat->cnt > 0 && estat->siz > 0)); | |
191 } | |
192 | |
193 X(kernel_free)(q); | |
194 } | |
195 | |
196 if (!IN_THREAD) { | |
197 /* delete minfo entry */ | |
198 unsigned int h = hashaddr(p); | |
199 struct minfo **i; | |
200 | |
201 for (i = minfo + h; *i; i = &((*i)->next)) { | |
202 if ((*i)->p == p) { | |
203 struct minfo *i0 = (*i)->next; | |
204 free(*i); | |
205 *i = i0; | |
206 return; | |
207 } | |
208 } | |
209 | |
210 A(0 /* no entry in minfo list */ ); | |
211 } | |
212 } | |
213 | |
214 void X(malloc_print_minfo)(int verbose) | |
215 { | |
216 struct minfo *info; | |
217 int what; | |
218 unsigned int h; | |
219 int leak = 0; | |
220 | |
221 if (verbose > 2) { | |
222 static const char *names[MALLOC_WHAT_LAST] = { | |
223 "EVERYTHING", | |
224 "PLANS", "SOLVERS", "PROBLEMS", "BUFFERS", | |
225 "HASHT", "TENSORS", "PLANNERS", "SLVDSC", "TWIDDLES", | |
226 "STRIDES", "OTHER" | |
227 }; | |
228 | |
229 printf("%12s %8s %8s %10s %10s\n", | |
230 "what", "cnt", "maxcnt", "siz", "maxsiz"); | |
231 | |
232 for (what = 0; what < MALLOC_WHAT_LAST; ++what) { | |
233 struct mstat *stat = mstat + what; | |
234 printf("%12s %8d %8d %10d %10d\n", | |
235 names[what], stat->cnt, stat->maxcnt, | |
236 stat->siz, stat->maxsiz); | |
237 } | |
238 } | |
239 | |
240 for (h = 0; h < HASHSZ; ++h) | |
241 if (minfo[h]) { | |
242 printf("\nUnfreed allocations:\n"); | |
243 break; | |
244 } | |
245 | |
246 for (h = 0; h < HASHSZ; ++h) | |
247 for (info = minfo[h]; info; info = info->next) { | |
248 leak = 1; | |
249 printf("%s:%d: %zd bytes at %p\n", | |
250 info->file, info->line, info->n, info->p); | |
251 } | |
252 | |
253 if (leak) | |
254 abort(); | |
255 } | |
256 | |
257 #else | |
258 /********************************************************** | |
259 * NON DEBUGGING CODE | |
260 **********************************************************/ | |
261 /* production version, no hacks */ | |
262 | |
263 void *X(malloc_plain)(size_t n) | |
264 { | |
265 void *p; | |
266 if (n == 0) | |
267 n = 1; | |
268 p = X(kernel_malloc)(n); | |
269 CK(p); | |
270 | |
271 #ifdef MIN_ALIGNMENT | |
272 A((((uintptr_t)p) % MIN_ALIGNMENT) == 0); | |
273 #endif | |
274 | |
275 return p; | |
276 } | |
277 | |
278 void X(ifree)(void *p) | |
279 { | |
280 X(kernel_free)(p); | |
281 } | |
282 | |
283 #endif | |
284 | |
285 void X(ifree0)(void *p) | |
286 { | |
287 /* common pattern */ | |
288 if (p) X(ifree)(p); | |
289 } |