Commit d3104024 authored by Rusty Russell's avatar Rusty Russell

htable: restore perfect bit when resizing.

If the lower bit differs between pointers, we can lose our "perfect"
bit.  Since we're rehashing the entire thing anyway, we can pick
another bit when we double the hash table.
parent 78e983a7
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <ccan/compiler/compiler.h> #include <ccan/compiler/compiler.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <limits.h>
#include <stdbool.h> #include <stdbool.h>
#include <assert.h> #include <assert.h>
...@@ -170,7 +171,16 @@ static COLD_ATTRIBUTE bool double_table(struct htable *ht) ...@@ -170,7 +171,16 @@ static COLD_ATTRIBUTE bool double_table(struct htable *ht)
ht->max *= 2; ht->max *= 2;
ht->max_with_deleted *= 2; ht->max_with_deleted *= 2;
/* FIXME: If we lost our perfect bit, we could reclaim it here! */ /* If we lost our "perfect bit", get it back now. */
if (!ht->perfect_bit && ht->common_mask) {
for (i = 0; i < sizeof(ht->common_mask) * CHAR_BIT; i++) {
if (ht->common_mask & ((size_t)1 << i)) {
ht->perfect_bit = (size_t)1 << i;
break;
}
}
}
for (i = 0; i < oldnum; i++) { for (i = 0; i < oldnum; i++) {
if (entry_is_valid(e = oldtable[i])) { if (entry_is_valid(e = oldtable[i])) {
void *p = get_raw_ptr(ht, e); void *p = get_raw_ptr(ht, e);
......
...@@ -96,13 +96,14 @@ static bool check_mask(struct htable *ht, uint64_t val[], unsigned num) ...@@ -96,13 +96,14 @@ static bool check_mask(struct htable *ht, uint64_t val[], unsigned num)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
unsigned int i; unsigned int i;
uintptr_t perfect_bit;
struct htable *ht; struct htable *ht;
uint64_t val[NUM_VALS]; uint64_t val[NUM_VALS];
uint64_t dne; uint64_t dne;
void *p; void *p;
struct htable_iter iter; struct htable_iter iter;
plan_tests(19); plan_tests(23);
for (i = 0; i < NUM_VALS; i++) for (i = 0; i < NUM_VALS; i++)
val[i] = i; val[i] = i;
dne = i; dne = i;
...@@ -143,6 +144,8 @@ int main(int argc, char *argv[]) ...@@ -143,6 +144,8 @@ int main(int argc, char *argv[])
htable_add(ht, hash(&val[NUM_VALS-1], NULL), &val[NUM_VALS-1]); htable_add(ht, hash(&val[NUM_VALS-1], NULL), &val[NUM_VALS-1]);
ok1(ht->common_mask == 0); ok1(ht->common_mask == 0);
ok1(ht->common_bits == 0); ok1(ht->common_bits == 0);
/* Get rid of bogus pointer before we trip over it! */
htable_del(ht, 0, (void *)~(uintptr_t)&val[NUM_VALS-1]);
/* Add the rest. */ /* Add the rest. */
add_vals(ht, val, NUM_VALS-1); add_vals(ht, val, NUM_VALS-1);
...@@ -151,5 +154,23 @@ int main(int argc, char *argv[]) ...@@ -151,5 +154,23 @@ int main(int argc, char *argv[])
find_vals(ht, val, NUM_VALS); find_vals(ht, val, NUM_VALS);
ok1(!htable_get(ht, hash(&dne, NULL), objcmp, &dne)); ok1(!htable_get(ht, hash(&dne, NULL), objcmp, &dne));
htable_free(ht);
/* Corner cases: wipe out the perfect bit using bogus pointer. */
ht = htable_new(hash, NULL);
htable_add(ht, 0, (void *)((uintptr_t)&val[NUM_VALS-1]));
ok1(ht->perfect_bit);
perfect_bit = ht->perfect_bit;
htable_add(ht, 0, (void *)((uintptr_t)&val[NUM_VALS-1]
| perfect_bit));
ok1(ht->perfect_bit == 0);
htable_del(ht, 0, (void *)((uintptr_t)&val[NUM_VALS-1] | perfect_bit));
/* Enlarging should restore it... */
add_vals(ht, val, NUM_VALS-1);
ok1(ht->perfect_bit != 0);
htable_free(ht);
return exit_status(); return exit_status();
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment