summaryrefslogtreecommitdiff
path: root/src/libs/uio/memdebug.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/uio/memdebug.c')
-rw-r--r--src/libs/uio/memdebug.c293
1 files changed, 293 insertions, 0 deletions
diff --git a/src/libs/uio/memdebug.c b/src/libs/uio/memdebug.c
new file mode 100644
index 0000000..b6bd1b6
--- /dev/null
+++ b/src/libs/uio/memdebug.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2003 Serge van den Boom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * Nota bene: later versions of the GNU General Public License do not apply
+ * to this program.
+ *
+ * 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
+ *
+ */
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "memdebug.h"
+#include "hashtable.h"
+#include "mem.h"
+#include "uioutils.h"
+#include "types.h"
+#include "uioport.h"
+
+// I'm intentionally not including the .h files. It would only make things
+// messy, because the second arguments would be other pointers, which
+// would require typecasts of the functions in uio_MemDebug_logTypeInfo.
+extern void uio_DirHandle_print(FILE *out, const void *);
+extern void uio_printMountInfo(FILE *out, const void *);
+extern void uio_printMountTreeItem(FILE *out, const void *);
+extern void uio_printPathComp(FILE *out, const void *);
+
+// Must be in the same order as in uio_MemDebug_LogTypes
+// Change the third field to have debug info printed for specific actions.
+// See memdebug.h file the possible values.
+const uio_MemDebug_LogTypeInfo uio_MemDebug_logTypeInfo[] = {
+ { "uio_DirHandle", uio_DirHandle_print, 0 },
+ { "uio_FileSystemInfo", NULL, 0 },
+ { "uio_GPDir", NULL, 0 },
+ { "uio_GPFile", NULL, 0 },
+ { "uio_GPRoot", NULL, 0 },
+ { "uio_Handle", NULL, 0 },
+ { "uio_MountHandle", NULL, 0 },
+ { "uio_MountInfo", uio_printMountInfo, 0 },
+ { "uio_MountTree", NULL, 0 },
+ { "uio_MountTreeItem", uio_printMountTreeItem, 0 },
+ { "uio_PathComp", uio_printPathComp, 0 },
+ { "uio_PFileHandle", NULL, 0 },
+ { "uio_PDirHandle", NULL, 0 },
+ { "uio_PRoot", NULL, 0 },
+ { "uio_Repository", NULL, 0 },
+ { "uio_Stream", NULL, 0 },
+ { "stdio_GPDirData", NULL, 0 },
+#ifdef HAVE_ZIP
+ { "zip_GPFileData", NULL, 0 },
+ { "zip_GPDirData", NULL, 0 },
+#endif
+};
+
+HashTable_HashTable **uio_MemDebug_logs;
+
+
+static uio_uint32 uio_MemDebug_pointerHash(const void *ptr);
+static uio_bool uio_MemDebug_pointerCompare(const void *ptr1, const void *ptr2);
+static void *uio_MemDebug_pointerCopy(const void *ptr);
+static void uio_MemDebug_pointerFree(void *ptr);
+
+static inline uio_MemDebug_PointerInfo *uio_MemDebug_PointerInfo_new(int ref);
+static inline void uio_MemDebug_PointerInfo_delete(
+ uio_MemDebug_PointerInfo *pointerInfo);
+static inline uio_MemDebug_PointerInfo *uio_MemDebug_PointerInfo_alloc(void);
+static inline void uio_MemDebug_PointerInfo_free(
+ uio_MemDebug_PointerInfo *pointerInfo);
+
+void
+uio_MemDebug_init(void) {
+ int i;
+
+ assert((int) uio_MemDebug_numLogTypes ==
+ (sizeof uio_MemDebug_logTypeInfo /
+ sizeof uio_MemDebug_logTypeInfo[0]));
+ uio_MemDebug_logs = uio_malloc(uio_MemDebug_numLogTypes *
+ sizeof (HashTable_HashTable *));
+
+ for (i = 0; i < uio_MemDebug_numLogTypes; i++) {
+ uio_MemDebug_logs[i] = HashTable_newHashTable(
+ uio_MemDebug_pointerHash,
+ uio_MemDebug_pointerCompare,
+ uio_MemDebug_pointerCopy,
+ uio_MemDebug_pointerFree,
+ 4, 0.85, 0.90);
+ }
+}
+
+void
+uio_MemDebug_unInit(void) {
+ int i;
+
+ for (i = 0; i < uio_MemDebug_numLogTypes; i++)
+ HashTable_deleteHashTable(uio_MemDebug_logs[i]);
+
+ uio_free(uio_MemDebug_logs);
+}
+
+static uio_uint32
+uio_MemDebug_pointerHash(const void *ptr) {
+ uio_uintptr ptrInt;
+
+ ptrInt = (uio_uintptr) ptr;
+ return (uio_uint32) (ptrInt ^ (ptrInt >> 10) ^ (ptrInt >> 20));
+}
+
+static uio_bool
+uio_MemDebug_pointerCompare(const void *ptr1, const void *ptr2) {
+ return ptr1 == ptr2;
+}
+
+static void *
+uio_MemDebug_pointerCopy(const void *ptr) {
+ return unconst(ptr);
+}
+
+static void
+uio_MemDebug_pointerFree(void *ptr) {
+ (void) ptr;
+}
+
+void
+uio_MemDebug_logAllocation(uio_MemDebug_LogType type, void *ptr) {
+ uio_MemDebug_PointerInfo *pointerInfo;
+
+ if (ptr == NULL) {
+ fprintf(stderr, "Fatal: Allocated pointer is (%s *) NULL.\n",
+ uio_MemDebug_logTypeInfo[(int) type].name);
+ abort();
+ }
+ if (uio_MemDebug_logTypeInfo[(int) type].flags & uio_MemDebug_PRINT_ALLOC) {
+ fprintf(stderr, "Alloc ");
+ uio_MemDebug_printPointer(stderr, type, ptr);
+ fprintf(stderr, "\n");
+ }
+ pointerInfo = uio_MemDebug_PointerInfo_new(1);
+ HashTable_add(uio_MemDebug_logs[type], ptr, (void *) pointerInfo);
+}
+
+void
+uio_MemDebug_logDeallocation(uio_MemDebug_LogType type, void *ptr) {
+ uio_MemDebug_PointerInfo *pointerInfo;
+
+ if (ptr == NULL) {
+ fprintf(stderr, "Fatal: Attempt to free (%s *) NULL pointer.\n",
+ uio_MemDebug_logTypeInfo[(int) type].name);
+ abort();
+ }
+ if (uio_MemDebug_logTypeInfo[(int) type].flags & uio_MemDebug_PRINT_FREE) {
+ fprintf(stderr, "Free ");
+ uio_MemDebug_printPointer(stderr, type, ptr);
+ fprintf(stderr, "\n");
+ }
+ pointerInfo = HashTable_find(uio_MemDebug_logs[type], ptr);
+ if (pointerInfo == NULL) {
+ fprintf(stderr, "Fatal: Attempt to free unallocated pointer "
+ "(%s *) %p.\n",
+ uio_MemDebug_logTypeInfo[(int) type].name, ptr);
+ abort();
+ }
+#if 0
+ if (pointerInfo->ref != 0) {
+ fprintf(stderr, "Fatal: Attempt to free pointer with references "
+ "left (%s *) %p.\n",
+ uio_MemDebug_logTypeInfo[(int) type].name, ptr);
+ abort();
+ }
+#endif
+ uio_MemDebug_PointerInfo_free(pointerInfo);
+ HashTable_remove(uio_MemDebug_logs[type], ptr);
+}
+
+void
+uio_MemDebug_logRef(uio_MemDebug_LogType type, void *ptr) {
+ uio_MemDebug_PointerInfo *pointerInfo;
+
+ if (ptr == NULL) {
+ fprintf(stderr, "Fatal: Attempt to increment reference to a "
+ "(%s *) NULL pointer.\n",
+ uio_MemDebug_logTypeInfo[(int) type].name);
+ abort();
+ }
+ pointerInfo = HashTable_find(uio_MemDebug_logs[type], ptr);
+ if (pointerInfo == NULL) {
+ fprintf(stderr, "Fatal: Attempt to increment reference to "
+ "unallocated pointer (%s *) %p.\n",
+ uio_MemDebug_logTypeInfo[(int) type].name, ptr);
+ abort();
+ }
+ pointerInfo->pointerRef++;
+ if (uio_MemDebug_logTypeInfo[(int) type].flags & uio_MemDebug_PRINT_REF) {
+ fprintf(stderr, "Ref++ to %d, ", pointerInfo->pointerRef);
+ uio_MemDebug_printPointer(stderr, type, ptr);
+ fprintf(stderr, "\n");
+ }
+}
+
+void
+uio_MemDebug_logUnref(uio_MemDebug_LogType type, void *ptr) {
+ uio_MemDebug_PointerInfo *pointerInfo;
+
+ if (ptr == NULL) {
+ fprintf(stderr, "Fatal: Attempt to decrement reference to a "
+ "(%s *) NULL pointer.\n",
+ uio_MemDebug_logTypeInfo[(int) type].name);
+ abort();
+ }
+ pointerInfo = HashTable_find(uio_MemDebug_logs[type], ptr);
+ if (pointerInfo == NULL) {
+ fprintf(stderr, "Fatal: Attempt to decrement reference to "
+ "unallocated pointer (%s *) %p.\n",
+ uio_MemDebug_logTypeInfo[(int) type].name, ptr);
+ abort();
+ }
+ if (pointerInfo->pointerRef == 0) {
+ fprintf(stderr, "Fatal: Attempt to decrement reference below 0 for "
+ "pointer (%s *) %p.\n",
+ uio_MemDebug_logTypeInfo[(int) type].name, ptr);
+ abort();
+ }
+ pointerInfo->pointerRef--;
+ if (uio_MemDebug_logTypeInfo[(int) type].flags & uio_MemDebug_PRINT_UNREF) {
+ fprintf(stderr, "Ref-- to %d, ", pointerInfo->pointerRef);
+ uio_MemDebug_printPointer(stderr, type, ptr);
+ fprintf(stderr, "\n");
+ }
+}
+
+void
+uio_MemDebug_printPointer(FILE *out, uio_MemDebug_LogType type, void *ptr) {
+ fprintf(out, "(%s *) %p", uio_MemDebug_logTypeInfo[(int) type].name, ptr);
+ if (uio_MemDebug_logTypeInfo[(int) type].printFunction != NULL) {
+ fprintf(out, ": ");
+ uio_MemDebug_logTypeInfo[(int) type].printFunction(out, ptr);
+ }
+}
+
+void
+uio_MemDebug_printPointersType(FILE *out, uio_MemDebug_LogType type) {
+ HashTable_Iterator *iterator;
+
+ for (iterator = HashTable_getIterator(uio_MemDebug_logs[type]);
+ !HashTable_iteratorDone(iterator);
+ iterator = HashTable_iteratorNext(iterator)) {
+ uio_MemDebug_printPointer(out, type, HashTable_iteratorKey(iterator));
+ fprintf(out, "\n");
+ }
+ HashTable_freeIterator(iterator);
+}
+
+void
+uio_MemDebug_printPointers(FILE *out) {
+ int i;
+
+ for (i = 0; i < uio_MemDebug_numLogTypes; i++)
+ uio_MemDebug_printPointersType(out, i);
+}
+
+static inline uio_MemDebug_PointerInfo *
+uio_MemDebug_PointerInfo_new(int ref) {
+ uio_MemDebug_PointerInfo *result;
+ result = uio_MemDebug_PointerInfo_alloc();
+ result->pointerRef = ref;
+ return result;
+}
+
+static inline void
+uio_MemDebug_PointerInfo_delete(uio_MemDebug_PointerInfo *pointerInfo) {
+ uio_MemDebug_PointerInfo_free(pointerInfo);
+}
+
+static inline uio_MemDebug_PointerInfo *
+uio_MemDebug_PointerInfo_alloc(void) {
+ return uio_malloc(sizeof (uio_MemDebug_PointerInfo));
+}
+
+static inline void
+uio_MemDebug_PointerInfo_free(uio_MemDebug_PointerInfo *pointerInfo) {
+ uio_free(pointerInfo);
+}
+