blob: 42e7b1782d4fee80e30346e1880918ad8434a17d [file] [log] [blame]
njn3e884182003-04-15 13:03:23 +00001
2/*--------------------------------------------------------------------*/
3/*--- A separately chained hash table. vg_hashtable.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
9
njn0e1b5142003-04-15 14:58:06 +000010 Copyright (C) 2000-2003 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
31#include "vg_include.h"
32
33/*--------------------------------------------------------------------*/
34/*--- Declarations ---*/
35/*--------------------------------------------------------------------*/
36
37/* Holds malloc'd but not freed blocks. Static, so zero-inited by default. */
38
39#define VG_N_CHAINS 997
40
41#define VG_CHAIN_NO(aa) (((UInt)(aa)) % VG_N_CHAINS)
42
43/*--------------------------------------------------------------------*/
44/*--- Functions ---*/
45/*--------------------------------------------------------------------*/
46
47VgHashTable VG_(HT_construct)(void)
48{
49 /* VG_(malloc) initialises to zero */
50 return VG_(malloc)(VG_N_CHAINS * sizeof(VgHashNode*));
51}
52
53Int VG_(HT_count_nodes) ( VgHashTable table )
54{
55 VgHashNode* node;
56 UInt chain;
57 Int n = 0;
58
59 for (chain = 0; chain < VG_N_CHAINS; chain++)
60 for (node = table[chain]; node != NULL; node = node->next)
61 n++;
62 return n;
63}
64
65/* Puts a new, heap allocated VgHashNode, into the malloclist. */
66void VG_(HT_add_node) ( VgHashTable table, VgHashNode* node )
67{
68 UInt chain = VG_CHAIN_NO(node->key);
69 node->next = table[chain];
70 table[chain] = node;
71}
72
73/* Looks up a VgHashNode in the table. Also returns the address of
74 the previous node's `next' pointer which allows it to be removed from the
75 list later without having to look it up again. */
76VgHashNode* VG_(HT_get_node) ( VgHashTable table, UInt key,
77 /*OUT*/VgHashNode*** next_ptr )
78{
79 VgHashNode *prev, *curr;
80 Int chain;
81
82 chain = VG_CHAIN_NO(key);
83
84 prev = NULL;
85 curr = table[chain];
86 while (True) {
87 if (curr == NULL)
88 break;
89 if (key == curr->key)
90 break;
91 prev = curr;
92 curr = curr->next;
93 }
94
95 if (NULL == prev)
96 *next_ptr = & table[chain];
97 else
98 *next_ptr = & prev->next;
99
100 return curr;
101}
102
103static
104void sort_hash_array ( VgHashNode** shadows, UInt n_shadows )
105{
106 Int incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
107 9841, 29524, 88573, 265720,
108 797161, 2391484 };
109 Int lo = 0;
110 Int hi = n_shadows-1;
111 Int i, j, h, bigN, hp;
112 VgHashNode* v;
113
114 bigN = hi - lo + 1; if (bigN < 2) return;
115 hp = 0; while (hp < 14 && incs[hp] < bigN) hp++; hp--;
njn8372b7f2003-05-14 12:42:14 +0000116 vg_assert(0 <= hp && hp < 14);
njn3e884182003-04-15 13:03:23 +0000117
118 for (; hp >= 0; hp--) {
119 h = incs[hp];
120 i = lo + h;
121 while (1) {
122 if (i > hi) break;
123 v = shadows[i];
124 j = i;
125 while (shadows[j-h]->key > v->key) {
126 shadows[j] = shadows[j-h];
127 j = j - h;
128 if (j <= (lo + h - 1)) break;
129 }
130 shadows[j] = v;
131 i++;
132 }
133 }
134}
135
136/* Allocates a suitably-sized array, copies all the malloc'd block
137 shadows into it, sorts it by the `key' field, then returns both the array
138 and the size of it. This is used by the memory-leak detector.
139*/
140VgHashNode** VG_(HT_to_sorted_array) ( VgHashTable table,
141 /*OUT*/ UInt* n_shadows )
142{
143 UInt i, j;
144 VgHashNode** arr;
145 VgHashNode* node;
146
147 *n_shadows = 0;
148 for (i = 0; i < VG_N_CHAINS; i++) {
149 for (node = table[i]; node != NULL; node = node->next) {
150 (*n_shadows)++;
151 }
152 }
153 if (*n_shadows == 0)
154 return NULL;
155
156 arr = VG_(malloc)( *n_shadows * sizeof(VgHashNode*) );
157
158 j = 0;
159 for (i = 0; i < VG_N_CHAINS; i++) {
160 for (node = table[i]; node != NULL; node = node->next) {
161 arr[j++] = node;
162 }
163 }
njn8372b7f2003-05-14 12:42:14 +0000164 vg_assert(j == *n_shadows);
njn3e884182003-04-15 13:03:23 +0000165
166 sort_hash_array(arr, *n_shadows);
167
168 /* Sanity check; assert that the blocks are now in order */
169 for (i = 0; i < *n_shadows-1; i++) {
njn8372b7f2003-05-14 12:42:14 +0000170 vg_assert( arr[i]->key < arr[i+1]->key );
njn3e884182003-04-15 13:03:23 +0000171 }
172
173 return arr;
174}
175
176/* Return the first VgHashNode satisfying the predicate p. */
177VgHashNode* VG_(HT_first_match) ( VgHashTable table, Bool (*p) ( VgHashNode* ))
178{
179 UInt i;
180 VgHashNode* node;
181
182 for (i = 0; i < VG_N_CHAINS; i++)
183 for (node = table[i]; node != NULL; node = node->next)
184 if ( p(node) )
185 return node;
186
187 return NULL;
188}
189
190void VG_(HT_apply_to_all_nodes)( VgHashTable table, void (*f)(VgHashNode*) )
191{
192 UInt i;
193 VgHashNode* node;
194
195 for (i = 0; i < VG_N_CHAINS; i++) {
196 for (node = table[i]; node != NULL; node = node->next) {
197 f(node);
198 }
199 }
200}
201
202void VG_(HT_destruct)(VgHashTable table)
203{
204 UInt i;
205 VgHashNode* node;
206
207 for (i = 0; i < VG_N_CHAINS; i++) {
208 for (node = table[i]; node != NULL; node = node->next) {
209 VG_(free)(node);
210 }
211 }
212 VG_(free)(table);
213}
214
215/*--------------------------------------------------------------------*/
216/*--- end vg_hashtable.c ---*/
217/*--------------------------------------------------------------------*/