source: vendor/bash/3.1-p17/lib/malloc/table.c

Last change on this file was 3231, checked in by bird, 18 years ago

eol style.

  • Property svn:eol-style set to native
File size: 6.0 KB
Line 
1/* table.c - bookkeeping functions for allocated memory */
2
3/* Copyright (C) 2001-2003 Free Software Foundation, Inc.
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
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
10 version.
11
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
15 for more details.
16
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. */
20#ifdef HAVE_CONFIG_H
21# include <config.h>
22#endif
23
24#include <stdio.h>
25
26#include "imalloc.h"
27#include "table.h"
28
29extern int malloc_register;
30
31#ifdef MALLOC_REGISTER
32
33#define FIND_ALLOC 0x01 /* allocate new entry or find existing */
34#define FIND_EXIST 0x02 /* find existing entry */
35
36static int table_count = 0;
37static int table_allocated = 0;
38static mr_table_t mem_table[REG_TABLE_SIZE];
39static mr_table_t mem_overflow;
40
41/*
42 * NOTE: taken from dmalloc (http://dmalloc.com) and modified.
43 */
44static unsigned int
45mt_hash (key)
46 const PTR_T key;
47{
48 unsigned int a, b, c;
49 unsigned long x;
50
51 /* set up the internal state */
52 a = 0x9e3779b9; /* the golden ratio; an arbitrary value */
53 x = (unsigned long)key; /* truncation is OK */
54 b = x >> 8;
55 c = x >> 3; /* XXX - was >> 4 */
56
57 HASH_MIX(a, b, c);
58 return c;
59}
60
61#if 0
62static unsigned int
63which_bucket (mem)
64 PTR_T mem;
65{
66 return (mt_hash ((unsigned char *)mem) & (REG_TABLE_SIZE-1));
67}
68#else
69#define which_bucket(mem) (mt_hash ((unsigned char *)(mem)) & (REG_TABLE_SIZE-1));
70#endif
71
72static mr_table_t *
73find_entry (mem, flags)
74 PTR_T mem;
75 int flags;
76{
77 unsigned int bucket;
78 register mr_table_t *tp;
79 mr_table_t *endp, *lastp;
80
81 if (mem_overflow.mem == mem)
82 return (&mem_overflow);
83
84 bucket = which_bucket (mem); /* get initial hash */
85 tp = endp = mem_table + bucket;
86 lastp = mem_table + REG_TABLE_SIZE;
87
88 while (1)
89 {
90 if (tp->mem == mem)
91 return (tp);
92 if (tp->mem == 0 && (flags & FIND_ALLOC))
93 {
94 table_count++;
95 return (tp);
96 }
97
98 tp++;
99
100 if (tp == lastp) /* wrap around */
101 tp = mem_table;
102
103 if (tp == endp && (flags & FIND_EXIST))
104 return ((mr_table_t *)NULL);
105
106 if (tp == endp && (flags & FIND_ALLOC))
107 break;
108 }
109
110 /* oops. table is full. replace an existing free entry. */
111 do
112 {
113 /* If there are no free entries, punt right away without searching. */
114 if (table_allocated == REG_TABLE_SIZE)
115 break;
116
117 if (tp->flags & MT_FREE)
118 {
119 memset(tp, 0, sizeof (mr_table_t));
120 return (tp);
121 }
122 tp++;
123
124 if (tp == lastp)
125 tp = mem_table;
126 }
127 while (tp != endp);
128
129 /* wow. entirely full. return mem_overflow dummy entry. */
130 tp = &mem_overflow;
131 memset (tp, 0, sizeof (mr_table_t));
132 return tp;
133}
134
135mr_table_t *
136mr_table_entry (mem)
137 PTR_T mem;
138{
139 return (find_entry (mem, FIND_EXIST));
140}
141
142void
143mregister_describe_mem (mem, fp)
144 PTR_T mem;
145 FILE *fp;
146{
147 mr_table_t *entry;
148
149 entry = find_entry (mem, FIND_EXIST);
150 if (entry == 0)
151 return;
152 fprintf (fp, "malloc: %p: %s: last %s from %s:%d\n",
153 mem,
154 (entry->flags & MT_ALLOC) ? "allocated" : "free",
155 (entry->flags & MT_ALLOC) ? "allocated" : "freed",
156 entry->file ? entry->file : "unknown",
157 entry->line);
158}
159
160void
161mregister_alloc (tag, mem, size, file, line)
162 const char *tag;
163 PTR_T mem;
164 size_t size;
165 const char *file;
166 int line;
167{
168 mr_table_t *tentry;
169
170 tentry = find_entry (mem, FIND_ALLOC);
171
172 if (tentry == 0)
173 {
174 /* oops. table is full. punt. */
175 fprintf (stderr, _("register_alloc: alloc table is full with FIND_ALLOC?\n"));
176 return;
177 }
178
179 if (tentry->flags & MT_ALLOC)
180 {
181 /* oops. bad bookkeeping. ignore for now */
182 fprintf (stderr, _("register_alloc: %p already in table as allocated?\n"), mem);
183 }
184
185 tentry->mem = mem;
186 tentry->size = size;
187 tentry->func = tag;
188 tentry->flags = MT_ALLOC;
189 tentry->file = file;
190 tentry->line = line;
191 tentry->nalloc++;
192
193 if (tentry != &mem_overflow)
194 table_allocated++;
195}
196
197void
198mregister_free (mem, size, file, line)
199 PTR_T mem;
200 int size;
201 const char *file;
202 int line;
203{
204 mr_table_t *tentry;
205
206 tentry = find_entry (mem, FIND_EXIST);
207 if (tentry == 0)
208 {
209 /* oops. not found. */
210#if 0
211 fprintf (stderr, "register_free: %p not in allocation table?\n", mem);
212#endif
213 return;
214 }
215 if (tentry->flags & MT_FREE)
216 {
217 /* oops. bad bookkeeping. ignore for now */
218 fprintf (stderr, _("register_free: %p already in table as free?\n"), mem);
219 }
220
221 tentry->flags = MT_FREE;
222 tentry->func = "free";
223 tentry->file = file;
224 tentry->line = line;
225 tentry->nfree++;
226
227 if (tentry != &mem_overflow)
228 table_allocated--;
229}
230
231/* If we ever add more flags, this will require changes. */
232static char *
233_entry_flags(x)
234 int x;
235{
236 if (x & MT_FREE)
237 return "free";
238 else if (x & MT_ALLOC)
239 return "allocated";
240 else
241 return "undetermined?";
242}
243
244static void
245_register_dump_table(fp)
246 FILE *fp;
247{
248 register int i;
249 mr_table_t entry;
250
251 for (i = 0; i < REG_TABLE_SIZE; i++)
252 {
253 entry = mem_table[i];
254 if (entry.mem)
255 fprintf (fp, "[%d] %p:%d:%s:%s:%s:%d:%d:%d\n", i,
256 entry.mem, entry.size,
257 _entry_flags(entry.flags),
258 entry.func ? entry.func : "unknown",
259 entry.file ? entry.file : "unknown",
260 entry.line,
261 entry.nalloc, entry.nfree);
262 }
263}
264
265void
266mregister_dump_table()
267{
268 _register_dump_table (stderr);
269}
270
271void
272mregister_table_init ()
273{
274 memset (mem_table, 0, sizeof(mr_table_t) * REG_TABLE_SIZE);
275 memset (&mem_overflow, 0, sizeof (mr_table_t));
276 table_count = 0;
277}
278
279#endif /* MALLOC_REGISTER */
280
281int
282malloc_set_register(n)
283 int n;
284{
285 int old;
286
287 old = malloc_register;
288 malloc_register = n;
289 return old;
290}
Note: See TracBrowser for help on using the repository browser.