1 /**************************************************************************
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
32 * @author José Fonseca <jrfonseca@tungstengraphics.com>
35 #include "pipe/p_config.h"
37 #if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
40 #elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
47 #include "util/u_debug.h"
48 #include "util/u_double_list.h"
51 #define DEBUG_MEMORY_MAGIC 0x6e34090aU
54 #if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) && !defined(WINCE)
55 #define real_malloc(_size) EngAllocMem(0, _size, 'D3AG')
56 #define real_free(_ptr) EngFreeMem(_ptr)
57 #elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
58 #define real_malloc(_size) ExAllocatePool(0, _size)
59 #define real_free(_ptr) ExFreePool(_ptr)
61 #define real_malloc(_size) malloc(_size)
62 #define real_free(_ptr) free(_ptr)
66 struct debug_memory_header
68 struct list_head head;
78 struct debug_memory_footer
84 static struct list_head list = { &list, &list };
86 static unsigned long last_no = 0;
89 static INLINE struct debug_memory_header *
90 header_from_data(void *data)
93 return (struct debug_memory_header *)((char *)data - sizeof(struct debug_memory_header));
99 data_from_header(struct debug_memory_header *hdr)
102 return (void *)((char *)hdr + sizeof(struct debug_memory_header));
107 static INLINE struct debug_memory_footer *
108 footer_from_header(struct debug_memory_header *hdr)
111 return (struct debug_memory_footer *)((char *)hdr + sizeof(struct debug_memory_header) + hdr->size);
118 debug_malloc(const char *file, unsigned line, const char *function,
121 struct debug_memory_header *hdr;
122 struct debug_memory_footer *ftr;
124 hdr = real_malloc(sizeof(*hdr) + size + sizeof(*ftr));
126 debug_printf("%s:%u:%s: out of memory when trying to allocate %lu bytes\n",
127 file, line, function,
128 (long unsigned)size);
135 hdr->function = function;
137 hdr->magic = DEBUG_MEMORY_MAGIC;
139 ftr = footer_from_header(hdr);
140 ftr->magic = DEBUG_MEMORY_MAGIC;
142 LIST_ADDTAIL(&hdr->head, &list);
144 return data_from_header(hdr);
148 debug_free(const char *file, unsigned line, const char *function,
151 struct debug_memory_header *hdr;
152 struct debug_memory_footer *ftr;
157 hdr = header_from_data(ptr);
158 if(hdr->magic != DEBUG_MEMORY_MAGIC) {
159 debug_printf("%s:%u:%s: freeing bad or corrupted memory %p\n",
160 file, line, function,
166 ftr = footer_from_header(hdr);
167 if(ftr->magic != DEBUG_MEMORY_MAGIC) {
168 debug_printf("%s:%u:%s: buffer overflow %p\n",
169 hdr->file, hdr->line, hdr->function,
174 LIST_DEL(&hdr->head);
182 debug_calloc(const char *file, unsigned line, const char *function,
183 size_t count, size_t size )
185 void *ptr = debug_malloc( file, line, function, count * size );
187 memset( ptr, 0, count * size );
192 debug_realloc(const char *file, unsigned line, const char *function,
193 void *old_ptr, size_t old_size, size_t new_size )
195 struct debug_memory_header *old_hdr, *new_hdr;
196 struct debug_memory_footer *old_ftr, *new_ftr;
200 return debug_malloc( file, line, function, new_size );
203 debug_free( file, line, function, old_ptr );
207 old_hdr = header_from_data(old_ptr);
208 if(old_hdr->magic != DEBUG_MEMORY_MAGIC) {
209 debug_printf("%s:%u:%s: reallocating bad or corrupted memory %p\n",
210 file, line, function,
216 old_ftr = footer_from_header(old_hdr);
217 if(old_ftr->magic != DEBUG_MEMORY_MAGIC) {
218 debug_printf("%s:%u:%s: buffer overflow %p\n",
219 old_hdr->file, old_hdr->line, old_hdr->function,
225 new_hdr = real_malloc(sizeof(*new_hdr) + new_size + sizeof(*new_ftr));
227 debug_printf("%s:%u:%s: out of memory when trying to allocate %lu bytes\n",
228 file, line, function,
229 (long unsigned)new_size);
232 new_hdr->no = old_hdr->no;
233 new_hdr->file = old_hdr->file;
234 new_hdr->line = old_hdr->line;
235 new_hdr->function = old_hdr->function;
236 new_hdr->size = new_size;
237 new_hdr->magic = DEBUG_MEMORY_MAGIC;
239 new_ftr = footer_from_header(new_hdr);
240 new_ftr->magic = DEBUG_MEMORY_MAGIC;
242 LIST_REPLACE(&old_hdr->head, &new_hdr->head);
245 new_ptr = data_from_header(new_hdr);
246 memcpy( new_ptr, old_ptr, old_size < new_size ? old_size : new_size );
257 debug_memory_begin(void)
263 debug_memory_end(unsigned long start_no)
265 size_t total_size = 0;
266 struct list_head *entry;
268 if(start_no == last_no)
272 for (; entry != &list; entry = entry->prev) {
273 struct debug_memory_header *hdr;
275 struct debug_memory_footer *ftr;
277 hdr = LIST_ENTRY(struct debug_memory_header, entry, head);
278 ptr = data_from_header(hdr);
279 ftr = footer_from_header(hdr);
281 if(hdr->magic != DEBUG_MEMORY_MAGIC) {
282 debug_printf("%s:%u:%s: bad or corrupted memory %p\n",
283 hdr->file, hdr->line, hdr->function,
288 if((start_no <= hdr->no && hdr->no < last_no) ||
289 (last_no < start_no && (hdr->no < last_no || start_no <= hdr->no))) {
290 debug_printf("%s:%u:%s: %u bytes at %p not freed\n",
291 hdr->file, hdr->line, hdr->function,
293 total_size += hdr->size;
296 if(ftr->magic != DEBUG_MEMORY_MAGIC) {
297 debug_printf("%s:%u:%s: buffer overflow %p\n",
298 hdr->file, hdr->line, hdr->function,
305 debug_printf("Total of %u KB of system memory apparently leaked\n",
306 (total_size + 1023)/1024);
309 debug_printf("No memory leaks detected.\n");