]>
git.ipfire.org Git - thirdparty/bash.git/blob - lib/malloc/table.c
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/>.
32 extern int interrupt_immediately
, running_trap
;
33 extern int signal_is_trapped
__P((int));
36 extern int malloc_register
;
38 #ifdef MALLOC_REGISTER
40 #define FIND_ALLOC 0x01 /* allocate new entry or find existing */
41 #define FIND_EXIST 0x02 /* find existing entry */
43 static int table_count
= 0;
44 static int table_allocated
= 0;
45 static mr_table_t mem_table
[REG_TABLE_SIZE
];
46 static mr_table_t mem_overflow
;
49 * NOTE: taken from dmalloc (http://dmalloc.com) and modified.
58 /* set up the internal state */
59 a
= 0x9e3779b9; /* the golden ratio; an arbitrary value */
60 x
= (unsigned long)key
; /* truncation is OK */
62 c
= x
>> 3; /* XXX - was >> 4 */
73 return (mt_hash ((unsigned char *)mem
) & (REG_TABLE_SIZE
-1));
76 #define which_bucket(mem) (mt_hash ((unsigned char *)(mem)) & (REG_TABLE_SIZE-1));
80 find_entry (mem
, flags
)
85 register mr_table_t
*tp
;
86 mr_table_t
*endp
, *lastp
;
88 if (mem_overflow
.mem
== mem
)
89 return (&mem_overflow
);
91 bucket
= which_bucket (mem
); /* get initial hash */
92 tp
= endp
= mem_table
+ bucket
;
93 lastp
= mem_table
+ REG_TABLE_SIZE
;
99 if (tp
->mem
== 0 && (flags
& FIND_ALLOC
))
107 if (tp
== lastp
) /* wrap around */
110 if (tp
== endp
&& (flags
& FIND_EXIST
))
111 return ((mr_table_t
*)NULL
);
113 if (tp
== endp
&& (flags
& FIND_ALLOC
))
117 /* oops. table is full. replace an existing free entry. */
120 /* If there are no free entries, punt right away without searching. */
121 if (table_allocated
== REG_TABLE_SIZE
)
124 if (tp
->flags
& MT_FREE
)
126 memset(tp
, 0, sizeof (mr_table_t
));
136 /* wow. entirely full. return mem_overflow dummy entry. */
138 memset (tp
, 0, sizeof (mr_table_t
));
146 return (find_entry (mem
, FIND_EXIST
));
150 mregister_describe_mem (mem
, fp
)
156 entry
= find_entry (mem
, FIND_EXIST
);
159 fprintf (fp
, "malloc: %p: %s: last %s from %s:%d\n",
161 (entry
->flags
& MT_ALLOC
) ? "allocated" : "free",
162 (entry
->flags
& MT_ALLOC
) ? "allocated" : "freed",
163 entry
->file
? entry
->file
: "unknown",
168 mregister_alloc (tag
, mem
, size
, file
, line
)
179 /* Block all signals in case we are executed from a signal handler. */
182 if (interrupt_immediately
|| running_trap
|| signal_is_trapped (SIGINT
) || signal_is_trapped (SIGCHLD
))
185 _malloc_block_signals (&set
, &oset
);
189 tentry
= find_entry (mem
, FIND_ALLOC
);
193 /* oops. table is full. punt. */
194 fprintf (stderr
, _("register_alloc: alloc table is full with FIND_ALLOC?\n"));
196 _malloc_unblock_signals (&set
, &oset
);
200 if (tentry
->flags
& MT_ALLOC
)
202 /* oops. bad bookkeeping. ignore for now */
203 fprintf (stderr
, _("register_alloc: %p already in table as allocated?\n"), mem
);
209 tentry
->flags
= MT_ALLOC
;
214 if (tentry
!= &mem_overflow
)
218 _malloc_unblock_signals (&set
, &oset
);
222 mregister_free (mem
, size
, file
, line
)
232 /* Block all signals in case we are executed from a signal handler. */
235 if (interrupt_immediately
|| running_trap
|| signal_is_trapped (SIGINT
) || signal_is_trapped (SIGCHLD
))
238 _malloc_block_signals (&set
, &oset
);
242 tentry
= find_entry (mem
, FIND_EXIST
);
245 /* oops. not found. */
247 fprintf (stderr
, "register_free: %p not in allocation table?\n", mem
);
250 _malloc_unblock_signals (&set
, &oset
);
253 if (tentry
->flags
& MT_FREE
)
255 /* oops. bad bookkeeping. ignore for now */
256 fprintf (stderr
, _("register_free: %p already in table as free?\n"), mem
);
259 tentry
->flags
= MT_FREE
;
260 tentry
->func
= "free";
265 if (tentry
!= &mem_overflow
)
269 _malloc_unblock_signals (&set
, &oset
);
272 /* If we ever add more flags, this will require changes. */
279 else if (x
& MT_ALLOC
)
282 return "undetermined?";
286 _register_dump_table(fp
)
292 for (i
= 0; i
< REG_TABLE_SIZE
; i
++)
294 entry
= mem_table
[i
];
296 fprintf (fp
, "[%d] %p:%d:%s:%s:%s:%d:%d:%d\n", i
,
297 entry
.mem
, entry
.size
,
298 _entry_flags(entry
.flags
),
299 entry
.func
? entry
.func
: "unknown",
300 entry
.file
? entry
.file
: "unknown",
302 entry
.nalloc
, entry
.nfree
);
307 mregister_dump_table()
309 _register_dump_table (stderr
);
313 mregister_table_init ()
315 memset (mem_table
, 0, sizeof(mr_table_t
) * REG_TABLE_SIZE
);
316 memset (&mem_overflow
, 0, sizeof (mr_table_t
));
320 #endif /* MALLOC_REGISTER */
323 malloc_set_register(n
)
328 old
= malloc_register
;