blob: c5312c5d756ace7cf2a471a84f34b83bafe84ac3 [file] [log] [blame]
njn3e884182003-04-15 13:03:23 +00001
2/*--------------------------------------------------------------------*/
njn81c00df2005-05-14 21:28:43 +00003/*--- A separately chained hash table. m_hashtable.c ---*/
njn3e884182003-04-15 13:03:23 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
njn3e884182003-04-15 13:03:23 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 Julian Seward
njn3e884182003-04-15 13:03:23 +000011 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
nethercotef1e5e152004-09-01 23:58:16 +000031#include "core.h"
njn81c00df2005-05-14 21:28:43 +000032#include "pub_core_hashtable.h"
njn132bfcc2005-06-04 19:16:06 +000033#include "pub_core_libcassert.h"
njnaf1d7df2005-06-11 01:31:52 +000034#include "pub_core_mallocfree.h"
njn3e884182003-04-15 13:03:23 +000035
36/*--------------------------------------------------------------------*/
37/*--- Declarations ---*/
38/*--------------------------------------------------------------------*/
39
40/* Holds malloc'd but not freed blocks. Static, so zero-inited by default. */
41
sewardjb326a1a2005-05-17 02:20:35 +000042#define VG_N_CHAINS 80021 /*4999*/ /* a prime number */
njn3e884182003-04-15 13:03:23 +000043
nethercote50397c22004-11-04 18:03:06 +000044#define VG_CHAIN_NO(aa) (((UWord)(aa)) % VG_N_CHAINS)
njn3e884182003-04-15 13:03:23 +000045
46/*--------------------------------------------------------------------*/
47/*--- Functions ---*/
48/*--------------------------------------------------------------------*/
49
50VgHashTable VG_(HT_construct)(void)
51{
njnce46c2a2003-07-21 10:52:07 +000052 /* Initialises to zero, ie. all entries NULL */
njn84d669f2003-07-21 11:42:27 +000053 return VG_(calloc)(VG_N_CHAINS, sizeof(VgHashNode*));
njn3e884182003-04-15 13:03:23 +000054}
55
56Int VG_(HT_count_nodes) ( VgHashTable table )
57{
58 VgHashNode* node;
59 UInt chain;
60 Int n = 0;
61
62 for (chain = 0; chain < VG_N_CHAINS; chain++)
63 for (node = table[chain]; node != NULL; node = node->next)
64 n++;
65 return n;
66}
67
68/* Puts a new, heap allocated VgHashNode, into the malloclist. */
69void VG_(HT_add_node) ( VgHashTable table, VgHashNode* node )
70{
71 UInt chain = VG_CHAIN_NO(node->key);
72 node->next = table[chain];
73 table[chain] = node;
74}
75
76/* Looks up a VgHashNode in the table. Also returns the address of
njn02bc4b82005-05-15 17:28:26 +000077 the previous node's 'next' pointer which allows it to be removed from the
njn3e884182003-04-15 13:03:23 +000078 list later without having to look it up again. */
nethercote3d6b6112004-11-04 16:39:43 +000079VgHashNode* VG_(HT_get_node) ( VgHashTable table, UWord key,
njn3e884182003-04-15 13:03:23 +000080 /*OUT*/VgHashNode*** next_ptr )
81{
82 VgHashNode *prev, *curr;
83 Int chain;
84
85 chain = VG_CHAIN_NO(key);
86
87 prev = NULL;
88 curr = table[chain];
89 while (True) {
90 if (curr == NULL)
91 break;
92 if (key == curr->key)
93 break;
94 prev = curr;
95 curr = curr->next;
96 }
97
98 if (NULL == prev)
99 *next_ptr = & table[chain];
100 else
101 *next_ptr = & prev->next;
102
103 return curr;
104}
105
njn3e884182003-04-15 13:03:23 +0000106/* Allocates a suitably-sized array, copies all the malloc'd block
njn06072ec2003-09-30 15:35:13 +0000107 shadows into it, then returns both the array and the size of it. This is
108 used by the memory-leak detector.
njn3e884182003-04-15 13:03:23 +0000109*/
njn06072ec2003-09-30 15:35:13 +0000110VgHashNode** VG_(HT_to_array) ( VgHashTable table, /*OUT*/ UInt* n_shadows )
njn3e884182003-04-15 13:03:23 +0000111{
112 UInt i, j;
113 VgHashNode** arr;
114 VgHashNode* node;
115
116 *n_shadows = 0;
117 for (i = 0; i < VG_N_CHAINS; i++) {
118 for (node = table[i]; node != NULL; node = node->next) {
119 (*n_shadows)++;
120 }
121 }
122 if (*n_shadows == 0)
123 return NULL;
124
125 arr = VG_(malloc)( *n_shadows * sizeof(VgHashNode*) );
126
127 j = 0;
128 for (i = 0; i < VG_N_CHAINS; i++) {
129 for (node = table[i]; node != NULL; node = node->next) {
130 arr[j++] = node;
131 }
132 }
njn8372b7f2003-05-14 12:42:14 +0000133 vg_assert(j == *n_shadows);
njn3e884182003-04-15 13:03:23 +0000134
njn3e884182003-04-15 13:03:23 +0000135 return arr;
136}
137
138/* Return the first VgHashNode satisfying the predicate p. */
thughes4ad52d02004-06-27 17:37:21 +0000139VgHashNode* VG_(HT_first_match) ( VgHashTable table,
140 Bool (*p) ( VgHashNode*, void* ),
141 void* d )
njn3e884182003-04-15 13:03:23 +0000142{
143 UInt i;
144 VgHashNode* node;
145
146 for (i = 0; i < VG_N_CHAINS; i++)
147 for (node = table[i]; node != NULL; node = node->next)
thughes4ad52d02004-06-27 17:37:21 +0000148 if ( p(node, d) )
njn3e884182003-04-15 13:03:23 +0000149 return node;
150
151 return NULL;
152}
153
thughes4ad52d02004-06-27 17:37:21 +0000154void VG_(HT_apply_to_all_nodes)( VgHashTable table,
155 void (*f)(VgHashNode*, void*),
156 void* d )
njn3e884182003-04-15 13:03:23 +0000157{
158 UInt i;
159 VgHashNode* node;
160
161 for (i = 0; i < VG_N_CHAINS; i++) {
162 for (node = table[i]; node != NULL; node = node->next) {
thughes4ad52d02004-06-27 17:37:21 +0000163 f(node, d);
njn3e884182003-04-15 13:03:23 +0000164 }
165 }
166}
167
168void VG_(HT_destruct)(VgHashTable table)
169{
170 UInt i;
171 VgHashNode* node;
172
173 for (i = 0; i < VG_N_CHAINS; i++) {
174 for (node = table[i]; node != NULL; node = node->next) {
175 VG_(free)(node);
176 }
177 }
178 VG_(free)(table);
179}
180
181/*--------------------------------------------------------------------*/
njn81c00df2005-05-14 21:28:43 +0000182/*--- end ---*/
njn3e884182003-04-15 13:03:23 +0000183/*--------------------------------------------------------------------*/