annotate src/fftw-3.3.5/kernel/alloc.c @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +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 }