3 #include "ircd_alloc.h"
12 /* To use this you need to get gc6.0 from:
13 * http://www.hpl.hp.com/personal/Hans_Boehm/gc/
14 * and you need to apply the patch in
15 * doc/debug_memleak_gc.patch to your gc6.0 tree, and reconfigure your ircd using
16 --with-leak-detect=path-to-gc6.0/.lib/
17 * You should only do this for debugging builds as it can slow things down
21 #include "ircd_string.h"
23 void *GC_malloc(size_t size);
24 void GC_free(void *ptr);
25 void GC_set_leak_handler(void (*)(void*, int));
26 void GC_gcollect(void);
27 extern int GC_find_leak;
40 memfrob(void *p, size_t len)
44 const char *pat = "\xde\xad\xbe\xef";
47 for (s = (char*)p, se = s + (len & ~3) - 4;
50 *(uint32_t*)s = *(uint32_t*)pat;
51 for (se = s; se < s; s++)
55 static size_t mdbg_bytes_allocated = 0, mdbg_blocks_allocated = 0;
56 static time_t last_gcollect = 0;
61 dbg_check_gcollect(void)
63 if (CurrentTime - last_gcollect < GC_FREQ)
66 last_gcollect = CurrentTime;
70 dbg_malloc(size_t size, const char *type, const char *file, int line)
72 struct MemHeader *mh = GC_malloc(size + sizeof(*mh));
75 memfrob((void*)(mh + 1), size);
76 mh->magic = 0xA110CA7E;
77 ircd_strncpy(mh->type, type, sizeof(mh->type) - 1)[sizeof(mh->type) - 1] = 0;
78 ircd_strncpy(mh->file, file, sizeof(mh->file) - 1)[sizeof(mh->file) - 1] = 0;
81 mh->since = CurrentTime;
82 mdbg_bytes_allocated += size;
83 mdbg_blocks_allocated++;
85 return (void*)(mh + 1);
89 dbg_malloc_zero(size_t size, const char *type, const char *file, int line)
91 struct MemHeader *mh = GC_malloc(size + sizeof(*mh));
94 memset((void*)(mh + 1), 0, size);
95 mh->magic = 0xA110CA7E;
96 ircd_strncpy(mh->type, type, sizeof(mh->type) - 1)[sizeof(mh->type) - 1] = 0;
97 ircd_strncpy(mh->file, file, sizeof(mh->file) - 1)[sizeof(mh->file) - 1] = 0;
100 mdbg_bytes_allocated += size;
101 mdbg_blocks_allocated++;
102 dbg_check_gcollect();
103 return (void*)(mh + 1);
107 dbg_realloc(void *ptr, size_t size, const char *file, int line)
109 struct MemHeader *mh, *mh2;
111 return dbg_malloc(size, "realloc", file, line);
112 mh = (struct MemHeader*)ptr - 1;
113 assert(mh->magic == 0xA110CA7E);
114 if (mh->length >= size)
116 mh2 = dbg_malloc(size, "realloc", file, line);
119 dbg_free(mh+1, file, line);
122 memcpy(mh2+1, mh+1, mh->length);
123 dbg_free(mh+1, file, line);
124 return (void*)(mh2+1);
128 dbg_free(void *ptr, const char *file, int line)
130 struct MemHeader *mh = (struct MemHeader*)ptr - 1;
131 /* XXX but bison gives us NULLs */
134 assert(mh->magic == 0xA110CA7E);
135 /* XXX can we get boehmgc to check for references to it? */
136 memfrob(mh, mh->length + sizeof(*mh));
137 mdbg_bytes_allocated -= mh->length;
138 mdbg_blocks_allocated--;
140 dbg_check_gcollect();
144 fda_get_byte_count(void)
146 dbg_check_gcollect();
147 return mdbg_bytes_allocated;
151 fda_get_block_count(void)
153 return mdbg_blocks_allocated;
159 dbg_memory_leaked(void *p, int sz)
161 struct MemHeader *mh;
162 /* We have to return because the gc "leaks". */
164 if (mh->magic != 0xA110CA7E)
166 sendto_opmask_butone(NULL, SNO_OLDSNO,
167 "%s leak at %s:%u(%u bytes for %u seconds)",
168 mh->type, mh->file, mh->line, mh->length,
169 CurrentTime - mh->since);
171 "%s leak at %s:%u(%u bytes for %u seconds)",
172 mh->type, mh->file, mh->line, mh->length,
173 CurrentTime - mh->since));
177 mem_dbg_initialise(void)
180 GC_set_leak_handler(dbg_memory_leaked);