1 /* table.c - bookkeeping functions for allocated memory */
3 /* Copyright (C) 2001 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 it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License along
18 with Bash; see the file COPYING. If not, write to the Free Software
19 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
29 extern int malloc_register;
31 #ifdef MALLOC_REGISTER
33 #define FIND_ALLOC 0x01 /* allocate new entry or find existing */
34 #define FIND_EXIST 0x02 /* find existing entry */
36 static int table_count = 0;
37 static mr_table_t mem_table[REG_TABLE_SIZE];
40 * NOTE: taken from dmalloc (http://dmalloc.com) and modified.
46 unsigned int a, b, c, len;
49 /* set up the internal state */
50 a = 0x9e3779b9; /* the golden ratio; an arbitrary value */
51 x = (unsigned long)key; /* truncation is OK */
53 c = x >> 3; /* XXX - was >> 4 */
64 return (mt_hash ((unsigned char *)mem) % REG_TABLE_SIZE);
67 #define which_bucket(mem) (mt_hash ((unsigned char *)(mem)) % REG_TABLE_SIZE);
71 find_entry (mem, flags)
76 register mr_table_t *tp;
77 mr_table_t *endp, *lastp;
79 bucket = which_bucket (mem); /* get initial hash */
80 tp = endp = mem_table + bucket;
81 lastp = mem_table + REG_TABLE_SIZE;
87 if (tp->mem == 0 && (flags & FIND_ALLOC))
95 if (tp == lastp) /* wrap around */
98 if (tp == endp && (flags & FIND_EXIST))
99 return ((mr_table_t *)NULL);
101 if (tp == endp && (flags & FIND_ALLOC))
105 /* oops. table is full. replace an existing free entry. */
108 if (tp->flags & MT_FREE)
110 memset(tp, 0, sizeof (mr_table_t));
117 /* wow. entirely full. return NULL. */
118 return ((mr_table_t *)NULL);
125 return (find_entry (mem, FIND_EXIST));
129 mregister_describe_mem (mem, fp)
135 entry = find_entry (mem, FIND_EXIST);
138 fprintf (fp, "malloc: %p: %s: last %s from %s:%d\n",
140 (entry->flags & MT_ALLOC) ? "allocated" : "free",
141 (entry->flags & MT_ALLOC) ? "allocated" : "freed",
142 entry->file ? entry->file : "unknown",
147 mregister_alloc (tag, mem, size, file, line)
156 tentry = find_entry (mem, FIND_ALLOC);
160 /* oops. table is full. punt. */
161 fprintf (stderr, "register_alloc: alloc table is full?\n");
165 if (tentry->flags & MT_ALLOC)
167 /* oops. bad bookkeeping. ignore for now */
168 fprintf (stderr, "register_alloc: %p already in table as allocated?\n", mem);
174 tentry->flags = MT_ALLOC;
181 mregister_free (mem, size, file, line)
189 tentry = find_entry (mem, FIND_EXIST);
192 /* oops. not found. */
193 fprintf (stderr, "register_free: %p not in allocation table?\n", mem);
196 if (tentry->flags & MT_FREE)
198 /* oops. bad bookkeeping. ignore for now */
199 fprintf (stderr, "register_free: %p already in table as free?\n", mem);
202 tentry->flags = MT_FREE;
203 tentry->func = "free";
209 /* If we ever add more flags, this will require changes. */
216 else if (x & MT_ALLOC)
219 return "undetermined?";
223 _register_dump_table(fp)
229 for (i = 0; i < REG_TABLE_SIZE; i++)
231 entry = mem_table[i];
233 fprintf (fp, "[%d] %p:%d:%s:%s:%s:%d:%d:%d\n", i,
234 entry.mem, entry.size,
235 _entry_flags(entry.flags),
236 entry.func ? entry.func : "unknown",
237 entry.file ? entry.file : "unknown",
239 entry.nalloc, entry.nfree);
244 mregister_dump_table()
246 _register_dump_table (stderr);
250 mregister_table_init ()
252 memset (mem_table, 0, sizeof(mr_table_t) * REG_TABLE_SIZE);
256 #endif /* MALLOC_REGISTER */
259 malloc_set_register(n)
264 old = malloc_register;