1 /* Copyright (C) 2000-2010 Red Hat, Inc. 2 This file is part of elfutils. 3 Written by Ulrich Drepper <drepper (at) redhat.com>, 2000. 4 5 This file is free software; you can redistribute it and/or modify 6 it under the terms of either 7 8 * the GNU Lesser General Public License as published by the Free 9 Software Foundation; either version 3 of the License, or (at 10 your option) any later version 11 12 or 13 14 * the GNU General Public License as published by the Free 15 Software Foundation; either version 2 of the License, or (at 16 your option) any later version 17 18 or both in parallel, as here. 19 20 elfutils is distributed in the hope that it will be useful, but 21 WITHOUT ANY WARRANTY; without even the implied warranty of 22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 General Public License for more details. 24 25 You should have received copies of the GNU General Public License and 26 the GNU Lesser General Public License along with this program. If 27 not, see <http://www.gnu.org/licenses/>. */ 28 29 #include <assert.h> 30 #include <stdlib.h> 31 #include <system.h> 32 33 /* Before including this file the following macros must be defined: 34 35 NAME name of the hash table structure. 36 TYPE data type of the hash table entries 37 COMPARE comparison function taking two pointers to TYPE objects 38 39 The following macros if present select features: 40 41 ITERATE iterating over the table entries is possible 42 REVERSE iterate in reverse order of insert 43 */ 44 45 46 static size_t 47 lookup (NAME *htab, HASHTYPE hval, TYPE val __attribute__ ((unused))) 48 { 49 /* First hash function: simply take the modul but prevent zero. Small values 50 can skip the division, which helps performance when this is common. */ 51 size_t idx = 1 + (hval < htab->size ? hval : hval % htab->size); 52 53 if (htab->table[idx].hashval != 0) 54 { 55 HASHTYPE hash; 56 57 if (htab->table[idx].hashval == hval 58 && COMPARE (htab->table[idx].data, val) == 0) 59 return idx; 60 61 /* Second hash function as suggested in [Knuth]. */ 62 hash = 1 + hval % (htab->size - 2); 63 64 do 65 { 66 if (idx <= hash) 67 idx = htab->size + idx - hash; 68 else 69 idx -= hash; 70 71 /* If entry is found use it. */ 72 if (htab->table[idx].hashval == hval 73 && COMPARE (htab->table[idx].data, val) == 0) 74 return idx; 75 } 76 while (htab->table[idx].hashval); 77 } 78 return idx; 79 } 80 81 82 static void 83 insert_entry_2 (NAME *htab, HASHTYPE hval, size_t idx, TYPE data) 84 { 85 #ifdef ITERATE 86 if (htab->table[idx].hashval == 0) 87 { 88 # ifdef REVERSE 89 htab->table[idx].next = htab->first; 90 htab->first = &htab->table[idx]; 91 # else 92 /* Add the new value to the list. */ 93 if (htab->first == NULL) 94 htab->first = htab->table[idx].next = &htab->table[idx]; 95 else 96 { 97 htab->table[idx].next = htab->first->next; 98 htab->first = htab->first->next = &htab->table[idx]; 99 } 100 # endif 101 } 102 #endif 103 104 htab->table[idx].hashval = hval; 105 htab->table[idx].data = data; 106 107 ++htab->filled; 108 if (100 * htab->filled > 90 * htab->size) 109 { 110 /* Table is filled more than 90%. Resize the table. */ 111 #ifdef ITERATE 112 __typeof__ (htab->first) first; 113 # ifndef REVERSE 114 __typeof__ (htab->first) runp; 115 # endif 116 #else 117 size_t old_size = htab->size; 118 #endif 119 #define _TABLE(name) \ 120 name##_ent *table = htab->table 121 #define TABLE(name) _TABLE (name) 122 TABLE(NAME); 123 124 htab->size = next_prime (htab->size * 2); 125 htab->filled = 0; 126 #ifdef ITERATE 127 first = htab->first; 128 htab->first = NULL; 129 #endif 130 htab->table = calloc ((1 + htab->size), sizeof (htab->table[0])); 131 if (htab->table == NULL) 132 { 133 /* We cannot enlarge the table. Live with what we got. This 134 might lead to an infinite loop at some point, though. */ 135 htab->table = table; 136 return; 137 } 138 139 /* Add the old entries to the new table. When iteration is 140 supported we maintain the order. */ 141 #ifdef ITERATE 142 # ifdef REVERSE 143 while (first != NULL) 144 { 145 insert_entry_2 (htab, first->hashval, 146 lookup (htab, first->hashval, first->data), 147 first->data); 148 149 first = first->next; 150 } 151 # else 152 assert (first != NULL); 153 runp = first = first->next; 154 do 155 insert_entry_2 (htab, runp->hashval, 156 lookup (htab, runp->hashval, runp->data), runp->data); 157 while ((runp = runp->next) != first); 158 # endif 159 #else 160 for (idx = 1; idx <= old_size; ++idx) 161 if (table[idx].hashval != 0) 162 insert_entry_2 (htab, table[idx].hashval, 163 lookup (htab, table[idx].hashval, table[idx].data), 164 table[idx].data); 165 #endif 166 167 free (table); 168 } 169 } 170 171 172 int 173 #define INIT(name) _INIT (name) 174 #define _INIT(name) \ 175 name##_init 176 INIT(NAME) (NAME *htab, size_t init_size) 177 { 178 /* We need the size to be a prime. */ 179 init_size = next_prime (init_size); 180 181 /* Initialize the data structure. */ 182 htab->size = init_size; 183 htab->filled = 0; 184 #ifdef ITERATE 185 htab->first = NULL; 186 #endif 187 htab->table = (void *) calloc ((init_size + 1), sizeof (htab->table[0])); 188 if (htab->table == NULL) 189 return -1; 190 191 return 0; 192 } 193 194 195 int 196 #define FREE(name) _FREE (name) 197 #define _FREE(name) \ 198 name##_free 199 FREE(NAME) (NAME *htab) 200 { 201 free (htab->table); 202 return 0; 203 } 204 205 206 int 207 #define INSERT(name) _INSERT (name) 208 #define _INSERT(name) \ 209 name##_insert 210 INSERT(NAME) (NAME *htab, HASHTYPE hval, TYPE data) 211 { 212 size_t idx; 213 214 /* Make the hash value nonzero. */ 215 hval = hval ?: 1; 216 217 idx = lookup (htab, hval, data); 218 219 if (htab->table[idx].hashval != 0) 220 /* We don't want to overwrite the old value. */ 221 return -1; 222 223 /* An empty bucket has been found. */ 224 insert_entry_2 (htab, hval, idx, data); 225 return 0; 226 } 227 228 229 #ifdef OVERWRITE 230 int 231 #define INSERT(name) _INSERT (name) 232 #define _INSERT(name) \ 233 name##_overwrite 234 INSERT(NAME) (NAME *htab, HASHTYPE hval, TYPE data) 235 { 236 size_t idx; 237 238 /* Make the hash value nonzero. */ 239 hval = hval ?: 1; 240 241 idx = lookup (htab, hval, data); 242 243 /* The correct bucket has been found. */ 244 insert_entry_2 (htab, hval, idx, data); 245 return 0; 246 } 247 #endif 248 249 250 TYPE 251 #define FIND(name) _FIND (name) 252 #define _FIND(name) \ 253 name##_find 254 FIND(NAME) (NAME *htab, HASHTYPE hval, TYPE val) 255 { 256 size_t idx; 257 258 /* Make the hash value nonzero. */ 259 hval = hval ?: 1; 260 261 idx = lookup (htab, hval, val); 262 263 if (htab->table[idx].hashval == 0) 264 return NULL; 265 266 return htab->table[idx].data; 267 } 268 269 270 #ifdef ITERATE 271 # define ITERATEFCT(name) _ITERATEFCT (name) 272 # define _ITERATEFCT(name) \ 273 name##_iterate 274 TYPE 275 ITERATEFCT(NAME) (NAME *htab, void **ptr) 276 { 277 void *p = *ptr; 278 279 # define TYPENAME(name) _TYPENAME (name) 280 # define _TYPENAME(name) name##_ent 281 282 # ifdef REVERSE 283 if (p == NULL) 284 p = htab->first; 285 else 286 p = ((TYPENAME(NAME) *) p)->next; 287 288 if (p == NULL) 289 { 290 *ptr = NULL; 291 return NULL; 292 } 293 # else 294 if (p == NULL) 295 { 296 if (htab->first == NULL) 297 return NULL; 298 p = htab->first->next; 299 } 300 else 301 { 302 if (p == htab->first) 303 return NULL; 304 305 p = ((TYPENAME(NAME) *) p)->next; 306 } 307 # endif 308 309 /* Prepare the next element. If possible this will pull the data 310 into the cache, for reading. */ 311 __builtin_prefetch (((TYPENAME(NAME) *) p)->next, 0, 2); 312 313 return ((TYPENAME(NAME) *) (*ptr = p))->data; 314 } 315 #endif 316