summaryrefslogtreecommitdiff
path: root/src/fftw/malloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fftw/malloc.c')
-rw-r--r--src/fftw/malloc.c240
1 files changed, 240 insertions, 0 deletions
diff --git a/src/fftw/malloc.c b/src/fftw/malloc.c
new file mode 100644
index 0000000..7ae22e4
--- /dev/null
+++ b/src/fftw/malloc.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 1997-1999, 2003 Massachusetts Institute of Technology
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*
+ * malloc.c -- memory allocation related functions
+ */
+
+/* $Id: malloc.c,v 1.1 2008/10/17 06:13:18 scuri Exp $ */
+#include "fftw-int.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+fftw_malloc_type_function fftw_malloc_hook = 0;
+fftw_free_type_function fftw_free_hook = 0;
+fftw_die_type_function fftw_die_hook = 0;
+
+/**********************************************************
+ * DEBUGGING CODE
+ **********************************************************/
+#ifdef FFTW_DEBUG
+static int fftw_malloc_cnt = 0;
+
+/*
+ * debugging malloc/free. Initialize every malloced and freed area to
+ * random values, just to make sure we are not using uninitialized
+ * pointers. Also check for writes past the ends of allocated blocks,
+ * and a couple of other things.
+ *
+ * This code is a quick and dirty hack -- use at your own risk.
+ */
+
+static int fftw_malloc_total = 0, fftw_malloc_max = 0, fftw_malloc_cnt_max = 0;
+
+#define MAGIC 0xABadCafe
+#define PAD_FACTOR 2
+#define TWOINTS (2 * sizeof(int))
+
+#define VERBOSE_ALLOCATION 0
+
+#if VERBOSE_ALLOCATION
+#define WHEN_VERBOSE(a) a
+#else
+#define WHEN_VERBOSE(a)
+#endif
+
+void *fftw_malloc(size_t n)
+{
+ char *p;
+ int i;
+
+ fftw_malloc_total += n;
+
+ if (fftw_malloc_total > fftw_malloc_max)
+ fftw_malloc_max = fftw_malloc_total;
+
+ p = (char *) malloc(PAD_FACTOR * n + TWOINTS);
+ if (!p)
+ fftw_die("fftw_malloc: out of memory\n");
+
+ /* store the size in a known position */
+ ((int *) p)[0] = n;
+ ((int *) p)[1] = MAGIC;
+ for (i = 0; i < PAD_FACTOR * n; ++i)
+ p[i + TWOINTS] = (char) (i ^ 0xDEADBEEF);
+
+ ++fftw_malloc_cnt;
+
+ if (fftw_malloc_cnt > fftw_malloc_cnt_max)
+ fftw_malloc_cnt_max = fftw_malloc_cnt;
+
+ /* skip the size we stored previously */
+ return (void *) (p + TWOINTS);
+}
+
+void fftw_free(void *p)
+{
+ char *q;
+
+ if (!p)
+ return;
+
+ q = ((char *) p) - TWOINTS;
+ if (!q)
+ fftw_die("fftw_free: tried to free NULL+TWOINTS pointer!\n");
+
+ {
+ int n = ((int *) q)[0];
+ int magic = ((int *) q)[1];
+ int i;
+
+ WHEN_VERBOSE( {
+ printf("FFTW_FREE %d\n", n);
+ fflush(stdout);
+ })
+
+ *((int *) q) = 0; /* set to zero to detect duplicate free's */
+
+ if (magic != MAGIC)
+ fftw_die("Wrong magic in fftw_free()!\n");
+ ((int *) q)[1] = ~MAGIC;
+
+ if (n < 0)
+ fftw_die("Tried to free block with corrupt size descriptor!\n");
+
+ fftw_malloc_total -= n;
+
+ if (fftw_malloc_total < 0)
+ fftw_die("fftw_malloc_total went negative!\n");
+
+ /* check for writing past end of array: */
+ for (i = n; i < PAD_FACTOR * n; ++i)
+ if (q[i + TWOINTS] != (char) (i ^ 0xDEADBEEF)) {
+ fflush(stdout);
+ fprintf(stderr, "Byte %d past end of array has changed!\n",
+ i - n + 1);
+ fftw_die("Array bounds overwritten!\n");
+ }
+ for (i = 0; i < PAD_FACTOR * n; ++i)
+ q[i + TWOINTS] = (char) (i ^ 0xBEEFDEAD);
+
+ --fftw_malloc_cnt;
+
+ if (fftw_malloc_cnt < 0)
+ fftw_die("fftw_malloc_cnt went negative!\n");
+
+ if (fftw_malloc_cnt == 0 && fftw_malloc_total > 0 ||
+ fftw_malloc_cnt > 0 && fftw_malloc_total == 0)
+ fftw_die("fftw_malloc_cnt/total not zero at the same time!\n");
+
+ free(q);
+ }
+}
+
+#else
+/**********************************************************
+ * NON DEBUGGING CODE
+ **********************************************************/
+/* production version, no hacks */
+
+void *fftw_malloc(size_t n)
+{
+ void *p;
+
+ if (fftw_malloc_hook)
+ return fftw_malloc_hook(n);
+
+ if (n == 0)
+ n = 1;
+
+ p = malloc(n);
+
+ if (!p)
+ fftw_die("fftw_malloc: out of memory\n");
+
+ return p;
+}
+
+void fftw_free(void *p)
+{
+ if (p) {
+ if (fftw_free_hook) {
+ fftw_free_hook(p);
+ return;
+ }
+ free(p);
+ }
+}
+
+#endif
+
+/* die when fatal errors occur */
+void fftw_die(const char *s)
+{
+ if (fftw_die_hook)
+ fftw_die_hook(s);
+
+ fflush(stdout);
+ fprintf(stderr, "fftw: %s", s);
+ exit(EXIT_FAILURE);
+}
+
+/* check for memory leaks when debugging */
+void fftw_check_memory_leaks(void)
+{
+ extern int fftw_node_cnt, fftw_plan_cnt, fftw_twiddle_size;
+
+#ifdef FFTW_DEBUG
+ if (fftw_malloc_cnt || fftw_malloc_total ||
+ fftw_node_cnt || fftw_plan_cnt || fftw_twiddle_size) {
+ fflush(stdout);
+ fprintf(stderr,
+ "MEMORY LEAK!!!\n"
+ "fftw_malloc = %d"
+ " node=%d plan=%d twiddle=%d\n"
+ "fftw_malloc_total = %d\n",
+ fftw_malloc_cnt,
+ fftw_node_cnt, fftw_plan_cnt, fftw_twiddle_size,
+ fftw_malloc_total);
+ exit(EXIT_FAILURE);
+ }
+#else
+ if (fftw_node_cnt || fftw_plan_cnt || fftw_twiddle_size) {
+ fflush(stdout);
+ fprintf(stderr,
+ "MEMORY LEAK!!!\n"
+ " node=%d plan=%d twiddle=%d\n",
+ fftw_node_cnt, fftw_plan_cnt, fftw_twiddle_size);
+ exit(EXIT_FAILURE);
+ }
+#endif
+}
+
+void fftw_print_max_memory_usage(void)
+{
+#ifdef FFTW_DEBUG
+ printf("\nMaximum number of blocks allocated = %d\n"
+ "Maximum number of bytes allocated = %0.3f kB\n",
+ fftw_malloc_cnt_max, fftw_malloc_max / 1024.0);
+#endif
+}