gallium: Memory debugging utilities.
authorJosé Fonseca <jrfonseca@tungstengraphics.com>
Sun, 23 Mar 2008 18:38:10 +0000 (18:38 +0000)
committerJosé Fonseca <jrfonseca@tungstengraphics.com>
Sun, 23 Mar 2008 18:38:31 +0000 (18:38 +0000)
There are no known tools for windows kernel memory debugging, so this is a
simple set of malloc etc wrappers.

Enabled by default on win32 debug builds

src/gallium/auxiliary/util/SConscript
src/gallium/auxiliary/util/p_debug_mem.c [new file with mode: 0644]
src/gallium/include/pipe/p_debug.h
src/gallium/include/pipe/p_util.h

index b44f2d5e3987d6f867e7978ec17e795791d2e774..9b3929eb2d35fc430804ecd418bcd08b79b1f73f 100644 (file)
@@ -4,6 +4,7 @@ util = env.ConvenienceLibrary(
        target = 'util',
        source = [
                'p_debug.c',
+               'p_debug_mem.c',
                'p_tile.c',
                'p_util.c',
                'u_blit.c',
diff --git a/src/gallium/auxiliary/util/p_debug_mem.c b/src/gallium/auxiliary/util/p_debug_mem.c
new file mode 100644 (file)
index 0000000..56599da
--- /dev/null
@@ -0,0 +1,172 @@
+/**************************************************************************
+ * 
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+/**
+ * @file
+ * Memory debugging.
+ * 
+ * @author José Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#include <winddi.h>
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#endif
+
+#include "pipe/p_debug.h" 
+#include "util/u_double_list.h" 
+
+
+#define DEBUG_MEMORY_MAGIC 0x6e34090aU 
+
+
+#if defined(WIN32) && !defined(WINCE)
+#define real_malloc(_size) EngAllocMem(0, _size, 'D3AG')
+#define real_free(_ptr) EngFreeMem(_ptr)
+#else
+#define real_malloc(_size) malloc(_size)
+#define real_free(_ptr) free(_ptr)
+#endif
+
+
+struct debug_memory_header 
+{
+   struct list_head head;
+   
+   unsigned long no;
+   const char *file;
+   unsigned line;
+   const char *function;
+   size_t size;
+   unsigned magic;
+};
+
+static struct list_head list = { &list, &list };
+
+static unsigned long start_no = 0;
+static unsigned long end_no = 0;
+
+
+void *
+debug_malloc(const char *file, unsigned line, const char *function,
+             size_t size) 
+{
+   struct debug_memory_header *hdr;
+   
+   hdr = real_malloc(sizeof(*hdr) + size);
+   if(!hdr)
+      return NULL;
+   hdr->no = end_no++;
+   hdr->file = file;
+   hdr->line = line;
+   hdr->function = function;
+   hdr->size = size;
+   hdr->magic = DEBUG_MEMORY_MAGIC;
+
+   LIST_ADDTAIL(&hdr->head, &list);
+   
+   return (void *)((char *)hdr + sizeof(*hdr));
+}
+
+void
+debug_free(const char *file, unsigned line, const char *function,
+           void *ptr) 
+{
+   struct debug_memory_header *hdr;
+   
+   if(!ptr)
+      return;
+   
+   hdr = (struct debug_memory_header *)((char *)ptr - sizeof(*hdr));
+   if(hdr->magic != DEBUG_MEMORY_MAGIC) {
+      debug_printf("%s:%u:%s: freeing bad or corrupted memory %p\n",
+                   file, line, function,
+                   ptr);
+      debug_assert(0);
+      return;
+   }
+
+   LIST_DEL(&hdr->head);
+   hdr->magic = 0;
+   
+   real_free(hdr);
+}
+
+void *
+debug_calloc(const char *file, unsigned line, const char *function,
+             size_t count, size_t size )
+{
+   void *ptr = debug_malloc( file, line, function, count * size );
+   if( ptr )
+      memset( ptr, 0, count * size );
+   return ptr;
+}
+
+void *
+debug_realloc(const char *file, unsigned line, const char *function,
+              void *old_ptr, size_t old_size, size_t new_size )
+{
+   void *new_ptr = NULL;
+
+   if (new_size != 0) {
+      new_ptr = debug_malloc( file, line, function, new_size );
+      
+      if( new_ptr && old_ptr )
+         memcpy( new_ptr, old_ptr, old_size );
+   }
+
+   debug_free( file, line, function, old_ptr );
+   return new_ptr;
+}
+
+void
+debug_memory_reset(void)
+{
+   start_no = end_no;
+}
+
+void 
+debug_memory_report(void)
+{
+   struct list_head *entry;
+
+   entry = list.prev;
+   for (; entry != &list; entry = entry->prev) {
+      struct debug_memory_header *hdr;
+      void *ptr;
+      hdr = LIST_ENTRY(struct debug_memory_header, entry, head);
+      ptr = (void *)((char *)hdr + sizeof(*hdr));
+      if(hdr->no >= start_no)
+        debug_printf("%s:%u:%s: %u byte st %p not freed\n",
+                     hdr->file, hdr->line, hdr->function,
+                     hdr->size, ptr);
+   }
+}
index 14f8056924dc9d84ec56d50e3297a988911d3227..c549513b6f97604fa8117a992f1933dc33cb7db2 100644 (file)
@@ -225,6 +225,29 @@ debug_dump_flags(const struct debug_named_value *names,
                  unsigned long value);
 
 
+void *
+debug_malloc(const char *file, unsigned line, const char *function,
+             size_t size);
+
+void
+debug_free(const char *file, unsigned line, const char *function,
+           void *ptr);
+
+void *
+debug_calloc(const char *file, unsigned line, const char *function,
+             size_t count, size_t size );
+
+void *
+debug_realloc(const char *file, unsigned line, const char *function,
+              void *old_ptr, size_t old_size, size_t new_size );
+
+void 
+debug_memory_reset(void);
+
+void 
+debug_memory_report(void);
+
+
 #ifdef __cplusplus
 }
 #endif
index c2e0f8c6a5d11e6060d69d99d910e4b49882caa5..d3b2fa295071b0f2e8ed24b3be78df2b1b068ee2 100644 (file)
@@ -39,6 +39,22 @@ extern "C" {
 #endif
 
 
+#if defined(WIN32) && defined(DEBUG) /* memory debugging */
+
+#include "p_debug.h"
+
+#define MALLOC( _size ) \
+   debug_malloc( __FILE__, __LINE__, __FUNCTION__, _size )
+#define CALLOC( _count, _size ) \
+   debug_calloc(__FILE__, __LINE__, __FUNCTION__, _count, _size )
+#define FREE( _ptr ) \
+   debug_free( __FILE__, __LINE__, __FUNCTION__,  _ptr )
+#define REALLOC( _ptr, _old_size, _size ) \
+   debug_realloc( __FILE__, __LINE__, __FUNCTION__,  _ptr, _old_size, _size )
+#define GETENV( X ) NULL
+
+#else
+   
 #ifdef WIN32
 
 void * __stdcall
@@ -104,7 +120,7 @@ REALLOC( void *old_ptr, unsigned old_size, unsigned new_size )
 
 #define GETENV( X )  NULL
 
-#else /* WIN32 */
+#else /* !WIN32 */
 
 #define MALLOC( SIZE )  malloc( SIZE )
 
@@ -116,7 +132,8 @@ REALLOC( void *old_ptr, unsigned old_size, unsigned new_size )
 
 #define GETENV( X )  getenv( X )
 
-#endif /* WIN32 */
+#endif /* !WIN32 */
+#endif /* !DEBUG */
 
 #define MALLOC_STRUCT(T)   (struct T *) MALLOC(sizeof(struct T))