p_debug_mem.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  * 
00026  **************************************************************************/
00027 
00035 #include "pipe/p_config.h" 
00036 
00037 #if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
00038 #include <windows.h>
00039 #include <winddi.h>
00040 #elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
00041 #include <wdm.h>
00042 #else
00043 #include <stdio.h>
00044 #include <stdlib.h>
00045 #endif
00046 
00047 #include "pipe/p_debug.h" 
00048 #include "util/u_double_list.h" 
00049 
00050 
00051 #define DEBUG_MEMORY_MAGIC 0x6e34090aU 
00052 
00053 
00054 #if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) && !defined(WINCE)
00055 #define real_malloc(_size) EngAllocMem(0, _size, 'D3AG')
00056 #define real_free(_ptr) EngFreeMem(_ptr)
00057 #elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
00058 #define real_malloc(_size) ExAllocatePool(0, _size)
00059 #define real_free(_ptr) ExFreePool(_ptr)
00060 #else
00061 #define real_malloc(_size) malloc(_size)
00062 #define real_free(_ptr) free(_ptr)
00063 #endif
00064 
00065 
00066 struct debug_memory_header 
00067 {
00068    struct list_head head;
00069    
00070    unsigned long no;
00071    const char *file;
00072    unsigned line;
00073    const char *function;
00074    size_t size;
00075    unsigned magic;
00076 };
00077 
00078 struct debug_memory_footer
00079 {
00080    unsigned magic;
00081 };
00082 
00083 
00084 static struct list_head list = { &list, &list };
00085 
00086 static unsigned long last_no = 0;
00087 
00088 
00089 static INLINE struct debug_memory_header *
00090 header_from_data(void *data)
00091 {
00092    if(data)
00093       return (struct debug_memory_header *)((char *)data - sizeof(struct debug_memory_header));
00094    else
00095       return NULL;
00096 }
00097 
00098 static INLINE void *
00099 data_from_header(struct debug_memory_header *hdr)
00100 {
00101    if(hdr)
00102       return (void *)((char *)hdr + sizeof(struct debug_memory_header));
00103    else
00104       return NULL;
00105 }
00106 
00107 static INLINE struct debug_memory_footer *
00108 footer_from_header(struct debug_memory_header *hdr)
00109 {
00110    if(hdr)
00111       return (struct debug_memory_footer *)((char *)hdr + sizeof(struct debug_memory_header) + hdr->size);
00112    else
00113       return NULL;
00114 }
00115 
00116 
00117 void *
00118 debug_malloc(const char *file, unsigned line, const char *function,
00119              size_t size) 
00120 {
00121    struct debug_memory_header *hdr;
00122    struct debug_memory_footer *ftr;
00123    
00124    assert(size);
00125    
00126    hdr = real_malloc(sizeof(*hdr) + size + sizeof(*ftr));
00127    if(!hdr) {
00128       debug_printf("%s:%u:%s: out of memory when trying to allocate %lu bytes\n",
00129                    file, line, function,
00130                    (long unsigned)size);
00131       return NULL;
00132    }
00133  
00134    hdr->no = last_no++;
00135    hdr->file = file;
00136    hdr->line = line;
00137    hdr->function = function;
00138    hdr->size = size;
00139    hdr->magic = DEBUG_MEMORY_MAGIC;
00140 
00141    ftr = footer_from_header(hdr);
00142    ftr->magic = DEBUG_MEMORY_MAGIC;
00143    
00144    LIST_ADDTAIL(&hdr->head, &list);
00145    
00146    return data_from_header(hdr);
00147 }
00148 
00149 void
00150 debug_free(const char *file, unsigned line, const char *function,
00151            void *ptr) 
00152 {
00153    struct debug_memory_header *hdr;
00154    struct debug_memory_footer *ftr;
00155    
00156    if(!ptr)
00157       return;
00158    
00159    hdr = header_from_data(ptr);
00160    if(hdr->magic != DEBUG_MEMORY_MAGIC) {
00161       debug_printf("%s:%u:%s: freeing bad or corrupted memory %p\n",
00162                    file, line, function,
00163                    ptr);
00164       debug_assert(0);
00165       return;
00166    }
00167 
00168    ftr = footer_from_header(hdr);
00169    if(ftr->magic != DEBUG_MEMORY_MAGIC) {
00170       debug_printf("%s:%u:%s: buffer overflow %p\n",
00171                    hdr->file, hdr->line, hdr->function,
00172                    ptr);
00173       debug_assert(0);
00174    }
00175 
00176    LIST_DEL(&hdr->head);
00177    hdr->magic = 0;
00178    ftr->magic = 0;
00179    
00180    real_free(hdr);
00181 }
00182 
00183 void *
00184 debug_calloc(const char *file, unsigned line, const char *function,
00185              size_t count, size_t size )
00186 {
00187    void *ptr = debug_malloc( file, line, function, count * size );
00188    if( ptr )
00189       memset( ptr, 0, count * size );
00190    return ptr;
00191 }
00192 
00193 void *
00194 debug_realloc(const char *file, unsigned line, const char *function,
00195               void *old_ptr, size_t old_size, size_t new_size )
00196 {
00197    struct debug_memory_header *old_hdr, *new_hdr;
00198    struct debug_memory_footer *old_ftr, *new_ftr;
00199    void *new_ptr;
00200    
00201    if(!old_ptr)
00202       return debug_malloc( file, line, function, new_size );
00203    
00204    if(!new_size) {
00205       debug_free( file, line, function, old_ptr );
00206       return NULL;
00207    }
00208    
00209    old_hdr = header_from_data(old_ptr);
00210    if(old_hdr->magic != DEBUG_MEMORY_MAGIC) {
00211       debug_printf("%s:%u:%s: reallocating bad or corrupted memory %p\n",
00212                    file, line, function,
00213                    old_ptr);
00214       debug_assert(0);
00215       return NULL;
00216    }
00217    
00218    old_ftr = footer_from_header(old_hdr);
00219    if(old_ftr->magic != DEBUG_MEMORY_MAGIC) {
00220       debug_printf("%s:%u:%s: buffer overflow %p\n",
00221                    old_hdr->file, old_hdr->line, old_hdr->function,
00222                    old_ptr);
00223       debug_assert(0);
00224    }
00225 
00226    /* alloc new */
00227    new_hdr = real_malloc(sizeof(*new_hdr) + new_size + sizeof(*new_ftr));
00228    if(!new_hdr) {
00229       debug_printf("%s:%u:%s: out of memory when trying to allocate %lu bytes\n",
00230                    file, line, function,
00231                    (long unsigned)new_size);
00232       return NULL;
00233    }
00234    new_hdr->no = old_hdr->no;
00235    new_hdr->file = old_hdr->file;
00236    new_hdr->line = old_hdr->line;
00237    new_hdr->function = old_hdr->function;
00238    new_hdr->size = new_size;
00239    new_hdr->magic = DEBUG_MEMORY_MAGIC;
00240    
00241    new_ftr = footer_from_header(new_hdr);
00242    new_ftr->magic = DEBUG_MEMORY_MAGIC;
00243    
00244    LIST_REPLACE(&old_hdr->head, &new_hdr->head);
00245 
00246    /* copy data */
00247    new_ptr = data_from_header(new_hdr);
00248    memcpy( new_ptr, old_ptr, old_size < new_size ? old_size : new_size );
00249 
00250    /* free old */
00251    old_hdr->magic = 0;
00252    old_ftr->magic = 0;
00253    real_free(old_hdr);
00254 
00255    return new_ptr;
00256 }
00257 
00258 unsigned long
00259 debug_memory_begin(void)
00260 {
00261    return last_no;
00262 }
00263 
00264 void 
00265 debug_memory_end(unsigned long start_no)
00266 {
00267    size_t total_size = 0;
00268    struct list_head *entry;
00269 
00270    if(start_no == last_no)
00271       return;
00272 
00273    entry = list.prev;
00274    for (; entry != &list; entry = entry->prev) {
00275       struct debug_memory_header *hdr;
00276       void *ptr;
00277       struct debug_memory_footer *ftr;
00278 
00279       hdr = LIST_ENTRY(struct debug_memory_header, entry, head);
00280       ptr = data_from_header(hdr);
00281       ftr = footer_from_header(hdr);
00282 
00283       if(hdr->magic != DEBUG_MEMORY_MAGIC) {
00284          debug_printf("%s:%u:%s: bad or corrupted memory %p\n",
00285                       hdr->file, hdr->line, hdr->function,
00286                       ptr);
00287          debug_assert(0);
00288       }
00289 
00290       if((start_no <= hdr->no && hdr->no < last_no) ||
00291          (last_no < start_no && (hdr->no < last_no || start_no <= hdr->no))) {
00292          debug_printf("%s:%u:%s: %u bytes at %p not freed\n",
00293                       hdr->file, hdr->line, hdr->function,
00294                       hdr->size, ptr);
00295          total_size += hdr->size;
00296       }
00297 
00298       if(ftr->magic != DEBUG_MEMORY_MAGIC) {
00299          debug_printf("%s:%u:%s: buffer overflow %p\n",
00300                       hdr->file, hdr->line, hdr->function,
00301                       ptr);
00302          debug_assert(0);
00303       }
00304    }
00305 
00306    if(total_size) {
00307       debug_printf("Total of %u KB of system memory apparently leaked\n",
00308                    (total_size + 1023)/1024);
00309    }
00310    else {
00311       debug_printf("No memory leaks detected.\n");
00312    }
00313 }

Generated on Tue Sep 29 06:25:15 2009 for Gallium3D by  doxygen 1.5.4