2 * The hashcode handling code below is heavily inspired in libiberty's
3 * hashtab code, but with most adaptation points and support for
4 * deleting elements removed.
6 * Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
7 * Contributed by Vladimir Makarov (vmakarov@cygnus.com).
10 #ifndef INLINE_HASHTAB_H
11 # define INLINE_HASHTAB_H 1
13 static __always_inline
unsigned long
14 higher_prime_number(unsigned long n
)
16 /* These are primes that are near, but slightly smaller than, a power of two. */
17 static const unsigned long primes
[] = {
47 ((unsigned long) 2147483647) + ((unsigned long) 2147483644),
49 const unsigned long *low
= &primes
[0];
50 const unsigned long *high
= &primes
[ARRAY_SIZE(primes
)];
53 const unsigned long *mid
= low
+ (high
- low
) / 2;
61 /* If we've run out of primes, abort. */
63 fprintf(stderr
, "Cannot find prime bigger than %lu\n", n
);
76 /* Current size (in entries) of the hash table */
79 /* Current number of elements */
83 static __always_inline
struct funcdesc_ht
*
86 struct funcdesc_ht
*ht
= _dl_malloc(sizeof(*ht
));
92 ent_size
= sizeof(void *) * ht
->size
;
93 ht
->entries
= _dl_malloc(ent_size
);
98 _dl_memset(ht
->entries
, 0, ent_size
);
104 * This is only called from _dl_loadaddr_unmap, so it's safe to call
105 * _dl_free(). See the discussion below.
107 static __always_inline
void
108 htab_delete(struct funcdesc_ht
*htab
)
112 for (i
= htab
->size
- 1; i
>= 0; i
--)
113 if (htab
->entries
[i
])
114 _dl_free(htab
->entries
[i
]);
116 _dl_free(htab
->entries
);
121 * Similar to htab_find_slot, but without several unwanted side effects:
122 * - Does not call htab->eq_f when it finds an existing entry.
123 * - Does not change the count of elements/searches/collisions in the
125 * This function also assumes there are no deleted entries in the table.
126 * HASH is the hash value for the element to be inserted.
128 static __always_inline
void **
129 find_empty_slot_for_expand(struct funcdesc_ht
*htab
, int hash
)
131 size_t size
= htab
->size
;
132 unsigned int index
= hash
% size
;
133 void **slot
= htab
->entries
+ index
;
139 hash2
= 1 + hash
% (size
- 2);
145 slot
= htab
->entries
+ index
;
152 * The following function changes size of memory allocated for the
153 * entries and repeatedly inserts the table elements. The occupancy
154 * of the table after the call will be about 50%. Naturally the hash
155 * table must already exist. Remember also that the place of the
156 * table entries is changed. If memory allocation failures are allowed,
157 * this function will return zero, indicating that the table could not be
158 * expanded. If all goes well, it will return a non-zero value.
160 static __always_inline
int
161 htab_expand(struct funcdesc_ht
*htab
, int (*hash_fn
) (void *))
169 oentries
= htab
->entries
;
170 olimit
= oentries
+ htab
->size
;
173 * Resize only when table after removal of unused elements is either
174 * too full or too empty.
176 if (htab
->n_elements
* 2 > htab
->size
)
177 nsize
= higher_prime_number(htab
->n_elements
* 2);
181 nentries
= _dl_malloc(sizeof(*nentries
) * nsize
);
182 _dl_memset(nentries
, 0, sizeof(*nentries
) * nsize
);
183 if (nentries
== NULL
)
185 htab
->entries
= nentries
;
191 *find_empty_slot_for_expand(htab
, hash_fn(*p
)) = *p
;
193 } while (p
< olimit
);
197 * We can't tell whether this was allocated by the _dl_malloc()
198 * built into ld.so or malloc() in the main executable or libc,
199 * and calling free() for something that wasn't malloc()ed could
200 * do Very Bad Things (TM). Take the conservative approach
201 * here, potentially wasting as much memory as actually used by
202 * the hash table, even if multiple growths occur. That's not
203 * so bad as to require some overengineered solution that would
204 * enable us to keep track of how it was allocated.
212 * This function searches for a hash table slot containing an entry
213 * equal to the given element. To delete an entry, call this with
214 * INSERT = 0, then call htab_clear_slot on the slot returned (possibly
215 * after doing some checks). To insert an entry, call this with
216 * INSERT = 1, then write the value you want into the returned slot.
217 * When inserting an entry, NULL may be returned if memory allocation
220 static __always_inline
void **
221 htab_find_slot(struct funcdesc_ht
*htab
, void *ptr
, int insert
,
222 int (*hash_fn
)(void *), int (*eq_fn
)(void *, void *))
229 if (htab
->size
* 3 <= htab
->n_elements
* 4 &&
230 htab_expand(htab
, hash_fn
) == 0)
238 entry
= &htab
->entries
[index
];
241 else if (eq_fn(*entry
, ptr
))
244 hash2
= 1 + hash
% (size
- 2);
250 entry
= &htab
->entries
[index
];
253 else if (eq_fn(*entry
, ptr
))