1 /* table.c - bookkeeping functions for allocated memory */
3 /* Copyright (C) 2001-2003 Free Software Foundation, Inc.
5 This file is part of GNU Bash, the Bourne Again SHell.
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
31 extern int malloc_register;
33 #ifdef MALLOC_REGISTER
35 #define FIND_ALLOC 0x01 /* allocate new entry or find existing */
36 #define FIND_EXIST 0x02 /* find existing entry */
38 static int table_count = 0;
39 static int table_allocated = 0;
40 static mr_table_t mem_table[REG_TABLE_SIZE];
41 static mr_table_t mem_overflow;
44 * NOTE: taken from dmalloc (http://dmalloc.com) and modified.
53 /* set up the internal state */
54 a = 0x9e3779b9; /* the golden ratio; an arbitrary value */
55 x = (unsigned long)key; /* truncation is OK */
57 c = x >> 3; /* XXX - was >> 4 */
68 return (mt_hash ((unsigned char *)mem) & (REG_TABLE_SIZE-1));
71 #define which_bucket(mem) (mt_hash ((unsigned char *)(mem)) & (REG_TABLE_SIZE-1));
75 find_entry (mem, flags)
80 register mr_table_t *tp;
81 mr_table_t *endp, *lastp;
83 if (mem_overflow.mem == mem)
84 return (&mem_overflow);
86 bucket = which_bucket (mem); /* get initial hash */
87 tp = endp = mem_table + bucket;
88 lastp = mem_table + REG_TABLE_SIZE;
94 if (tp->mem == 0 && (flags & FIND_ALLOC))
102 if (tp == lastp) /* wrap around */
105 if (tp == endp && (flags & FIND_EXIST))
106 return ((mr_table_t *)NULL);
108 if (tp == endp && (flags & FIND_ALLOC))
112 /* oops. table is full. replace an existing free entry. */
115 /* If there are no free entries, punt right away without searching. */
116 if (table_allocated == REG_TABLE_SIZE)
119 if (tp->flags & MT_FREE)
121 memset(tp, 0, sizeof (mr_table_t));
131 /* wow. entirely full. return mem_overflow dummy entry. */
133 memset (tp, 0, sizeof (mr_table_t));
141 return (find_entry (mem, FIND_EXIST));
145 mregister_describe_mem (mem, fp)
151 entry = find_entry (mem, FIND_EXIST);
154 fprintf (fp, "malloc: %p: %s: last %s from %s:%d\n",
156 (entry->flags & MT_ALLOC) ? "allocated" : "free",
157 (entry->flags & MT_ALLOC) ? "allocated" : "freed",
158 entry->file ? entry->file : "unknown",
163 mregister_alloc (tag, mem, size, file, line)
172 tentry = find_entry (mem, FIND_ALLOC);
176 /* oops. table is full. punt. */
177 fprintf (stderr, _("register_alloc: alloc table is full with FIND_ALLOC?\n"));
181 if (tentry->flags & MT_ALLOC)
183 /* oops. bad bookkeeping. ignore for now */
184 fprintf (stderr, _("register_alloc: %p already in table as allocated?\n"), mem);
190 tentry->flags = MT_ALLOC;
195 if (tentry != &mem_overflow)
200 mregister_free (mem, size, file, line)
208 tentry = find_entry (mem, FIND_EXIST);
211 /* oops. not found. */
213 fprintf (stderr, "register_free: %p not in allocation table?\n", mem);
217 if (tentry->flags & MT_FREE)
219 /* oops. bad bookkeeping. ignore for now */
220 fprintf (stderr, _("register_free: %p already in table as free?\n"), mem);
223 tentry->flags = MT_FREE;
224 tentry->func = "free";
229 if (tentry != &mem_overflow)
233 /* If we ever add more flags, this will require changes. */
240 else if (x & MT_ALLOC)
243 return "undetermined?";
247 _register_dump_table(fp)
253 for (i = 0; i < REG_TABLE_SIZE; i++)
255 entry = mem_table[i];
257 fprintf (fp, "[%d] %p:%d:%s:%s:%s:%d:%d:%d\n", i,
258 entry.mem, entry.size,
259 _entry_flags(entry.flags),
260 entry.func ? entry.func : "unknown",
261 entry.file ? entry.file : "unknown",
263 entry.nalloc, entry.nfree);
268 mregister_dump_table()
270 _register_dump_table (stderr);
274 mregister_table_init ()
276 memset (mem_table, 0, sizeof(mr_table_t) * REG_TABLE_SIZE);
277 memset (&mem_overflow, 0, sizeof (mr_table_t));
281 #endif /* MALLOC_REGISTER */
284 malloc_set_register(n)
289 old = malloc_register;