annotate src/fftw-3.3.5/kernel/alloc.c @ 77:4edcd14160a5 pa_catalina

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