2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 10:10:06 +00:00

consolidate fibonacci hashing in one place

Fibonacci hashing was implemented in four separate places (rbt.c,
rbtdb.c, resolver.c, zone.c). This commit combines them into a single
implementation. The hash_32() function is now replaced with
isc_hash_bits32().
This commit is contained in:
Evan Hunt 2022-03-16 13:23:02 -07:00
parent f768c138b4
commit e9ef3defa4
6 changed files with 90 additions and 118 deletions

View File

@ -466,7 +466,6 @@ dns_name_hash(const dns_name_t *name, bool case_sensitive) {
length = 16; length = 16;
} }
/* High bits are more random. */
return (isc_hash32(name->ndata, length, case_sensitive)); return (isc_hash32(name->ndata, length, case_sensitive));
} }
@ -481,7 +480,6 @@ dns_name_fullhash(const dns_name_t *name, bool case_sensitive) {
return (0); return (0);
} }
/* High bits are more random. */
return (isc_hash32(name->ndata, name->length, case_sensitive)); return (isc_hash32(name->ndata, name->length, case_sensitive));
} }

View File

@ -19,6 +19,7 @@
#include <isc/crc64.h> #include <isc/crc64.h>
#include <isc/file.h> #include <isc/file.h>
#include <isc/hash.h>
#include <isc/hex.h> #include <isc/hex.h>
#include <isc/mem.h> #include <isc/mem.h>
#include <isc/once.h> #include <isc/once.h>
@ -60,24 +61,8 @@
#define CHAIN_MAGIC ISC_MAGIC('0', '-', '0', '-') #define CHAIN_MAGIC ISC_MAGIC('0', '-', '0', '-')
#define VALID_CHAIN(chain) ISC_MAGIC_VALID(chain, CHAIN_MAGIC) #define VALID_CHAIN(chain) ISC_MAGIC_VALID(chain, CHAIN_MAGIC)
#define RBT_HASH_NO_BITS 0
#define RBT_HASH_MIN_BITS 4
#define RBT_HASH_MAX_BITS 32
#define RBT_HASH_OVERCOMMIT 3
#define RBT_HASH_NEXTTABLE(hindex) ((hindex == 0) ? 1 : 0) #define RBT_HASH_NEXTTABLE(hindex) ((hindex == 0) ? 1 : 0)
#define GOLDEN_RATIO_32 0x61C88647
#define HASHSIZE(bits) (UINT64_C(1) << (bits))
static uint32_t
hash_32(uint32_t val, unsigned int bits) {
REQUIRE(bits <= RBT_HASH_MAX_BITS);
/* High bits are more random. */
return (val * GOLDEN_RATIO_32 >> (32 - bits));
}
struct dns_rbt { struct dns_rbt {
unsigned int magic; unsigned int magic;
isc_mem_t *mctx; isc_mem_t *mctx;
@ -322,7 +307,7 @@ dns_rbt_create(isc_mem_t *mctx, dns_rbtdeleter_t deleter, void *deleter_arg,
isc_mem_attach(mctx, &rbt->mctx); isc_mem_attach(mctx, &rbt->mctx);
hashtable_new(rbt, 0, RBT_HASH_MIN_BITS); hashtable_new(rbt, 0, ISC_HASH_MIN_BITS);
rbt->magic = RBT_MAGIC; rbt->magic = RBT_MAGIC;
@ -932,7 +917,7 @@ dns_rbt_findnode(dns_rbt_t *rbt, const dns_name_t *name, dns_name_t *foundname,
* by the computed hash value. * by the computed hash value.
*/ */
hash = hash_32(hashval, rbt->hashbits[hindex]); hash = isc_hash_bits32(hashval, rbt->hashbits[hindex]);
for (hnode = rbt->hashtable[hindex][hash]; for (hnode = rbt->hashtable[hindex][hash];
hnode != NULL; hnode = HASHNEXT(hnode)) hnode != NULL; hnode = HASHNEXT(hnode))
@ -1616,7 +1601,7 @@ hash_add_node(dns_rbt_t *rbt, dns_rbtnode_t *node, const dns_name_t *name) {
HASHVAL(node) = dns_name_fullhash(name, false); HASHVAL(node) = dns_name_fullhash(name, false);
hash = hash_32(HASHVAL(node), rbt->hashbits[rbt->hindex]); hash = isc_hash_bits32(HASHVAL(node), rbt->hashbits[rbt->hindex]);
HASHNEXT(node) = rbt->hashtable[rbt->hindex][hash]; HASHNEXT(node) = rbt->hashtable[rbt->hindex][hash];
rbt->hashtable[rbt->hindex][hash] = node; rbt->hashtable[rbt->hindex][hash] = node;
@ -1629,24 +1614,25 @@ static void
hashtable_new(dns_rbt_t *rbt, uint8_t index, uint8_t bits) { hashtable_new(dns_rbt_t *rbt, uint8_t index, uint8_t bits) {
size_t size; size_t size;
REQUIRE(rbt->hashbits[index] == RBT_HASH_NO_BITS); REQUIRE(rbt->hashbits[index] == 0U);
REQUIRE(rbt->hashtable[index] == NULL); REQUIRE(rbt->hashtable[index] == NULL);
REQUIRE(bits >= RBT_HASH_MIN_BITS); REQUIRE(bits >= ISC_HASH_MIN_BITS);
REQUIRE(bits < RBT_HASH_MAX_BITS); REQUIRE(bits < ISC_HASH_MAX_BITS);
rbt->hashbits[index] = bits; rbt->hashbits[index] = bits;
size = HASHSIZE(rbt->hashbits[index]) * sizeof(dns_rbtnode_t *); size = ISC_HASHSIZE(rbt->hashbits[index]) * sizeof(dns_rbtnode_t *);
rbt->hashtable[index] = isc_mem_get(rbt->mctx, size); rbt->hashtable[index] = isc_mem_get(rbt->mctx, size);
memset(rbt->hashtable[index], 0, size); memset(rbt->hashtable[index], 0, size);
} }
static void static void
hashtable_free(dns_rbt_t *rbt, uint8_t index) { hashtable_free(dns_rbt_t *rbt, uint8_t index) {
size_t size = HASHSIZE(rbt->hashbits[index]) * sizeof(dns_rbtnode_t *); size_t size = ISC_HASHSIZE(rbt->hashbits[index]) *
sizeof(dns_rbtnode_t *);
isc_mem_put(rbt->mctx, rbt->hashtable[index], size); isc_mem_put(rbt->mctx, rbt->hashtable[index], size);
rbt->hashbits[index] = RBT_HASH_NO_BITS; rbt->hashbits[index] = 0U;
rbt->hashtable[index] = NULL; rbt->hashtable[index] = NULL;
} }
@ -1654,7 +1640,8 @@ static uint32_t
rehash_bits(dns_rbt_t *rbt, size_t newcount) { rehash_bits(dns_rbt_t *rbt, size_t newcount) {
uint32_t newbits = rbt->hashbits[rbt->hindex]; uint32_t newbits = rbt->hashbits[rbt->hindex];
while (newcount >= HASHSIZE(newbits) && newbits < RBT_HASH_MAX_BITS) { while (newcount >= ISC_HASHSIZE(newbits) && newbits < ISC_HASH_MAX_BITS)
{
newbits += 1; newbits += 1;
} }
@ -1670,12 +1657,12 @@ hashtable_rehash(dns_rbt_t *rbt, uint32_t newbits) {
uint32_t oldbits = rbt->hashbits[oldindex]; uint32_t oldbits = rbt->hashbits[oldindex];
uint8_t newindex = RBT_HASH_NEXTTABLE(oldindex); uint8_t newindex = RBT_HASH_NEXTTABLE(oldindex);
REQUIRE(rbt->hashbits[oldindex] >= RBT_HASH_MIN_BITS); REQUIRE(rbt->hashbits[oldindex] >= ISC_HASH_MIN_BITS);
REQUIRE(rbt->hashbits[oldindex] <= RBT_HASH_MAX_BITS); REQUIRE(rbt->hashbits[oldindex] <= ISC_HASH_MAX_BITS);
REQUIRE(rbt->hashtable[oldindex] != NULL); REQUIRE(rbt->hashtable[oldindex] != NULL);
REQUIRE(newbits <= RBT_HASH_MAX_BITS); REQUIRE(newbits <= ISC_HASH_MAX_BITS);
REQUIRE(rbt->hashbits[newindex] == RBT_HASH_NO_BITS); REQUIRE(rbt->hashbits[newindex] == 0U);
REQUIRE(rbt->hashtable[newindex] == NULL); REQUIRE(rbt->hashtable[newindex] == NULL);
REQUIRE(newbits > oldbits); REQUIRE(newbits > oldbits);
@ -1691,7 +1678,7 @@ static void
hashtable_rehash_one(dns_rbt_t *rbt) { hashtable_rehash_one(dns_rbt_t *rbt) {
dns_rbtnode_t **newtable = rbt->hashtable[rbt->hindex]; dns_rbtnode_t **newtable = rbt->hashtable[rbt->hindex];
uint32_t oldsize = uint32_t oldsize =
HASHSIZE(rbt->hashbits[RBT_HASH_NEXTTABLE(rbt->hindex)]); ISC_HASHSIZE(rbt->hashbits[RBT_HASH_NEXTTABLE(rbt->hindex)]);
dns_rbtnode_t **oldtable = dns_rbtnode_t **oldtable =
rbt->hashtable[RBT_HASH_NEXTTABLE(rbt->hindex)]; rbt->hashtable[RBT_HASH_NEXTTABLE(rbt->hindex)];
dns_rbtnode_t *node = NULL; dns_rbtnode_t *node = NULL;
@ -1711,8 +1698,8 @@ hashtable_rehash_one(dns_rbt_t *rbt) {
/* Move the first non-empty node from old hashtable to new hashtable */ /* Move the first non-empty node from old hashtable to new hashtable */
for (node = oldtable[rbt->hiter]; node != NULL; node = nextnode) { for (node = oldtable[rbt->hiter]; node != NULL; node = nextnode) {
uint32_t hash = hash_32(HASHVAL(node), uint32_t hash = isc_hash_bits32(HASHVAL(node),
rbt->hashbits[rbt->hindex]); rbt->hashbits[rbt->hindex]);
nextnode = HASHNEXT(node); nextnode = HASHNEXT(node);
HASHNEXT(node) = newtable[hash]; HASHNEXT(node) = newtable[hash];
newtable[hash] = node; newtable[hash] = node;
@ -1728,7 +1715,7 @@ maybe_rehash(dns_rbt_t *rbt, size_t newcount) {
uint32_t newbits = rehash_bits(rbt, newcount); uint32_t newbits = rehash_bits(rbt, newcount);
if (rbt->hashbits[rbt->hindex] < newbits && if (rbt->hashbits[rbt->hindex] < newbits &&
newbits <= RBT_HASH_MAX_BITS) { newbits <= ISC_HASH_MAX_BITS) {
hashtable_rehash(rbt, newbits); hashtable_rehash(rbt, newbits);
} }
} }
@ -1740,8 +1727,8 @@ rehashing_in_progress(dns_rbt_t *rbt) {
static bool static bool
hashtable_is_overcommited(dns_rbt_t *rbt) { hashtable_is_overcommited(dns_rbt_t *rbt) {
return (rbt->nodecount >= return (rbt->nodecount >= (ISC_HASHSIZE(rbt->hashbits[rbt->hindex]) *
(HASHSIZE(rbt->hashbits[rbt->hindex]) * RBT_HASH_OVERCOMMIT)); ISC_HASH_OVERCOMMIT));
} }
/* /*
@ -1781,7 +1768,7 @@ unhash_node(dns_rbt_t *rbt, dns_rbtnode_t *dnode) {
* c) other table: the node hasn't been moved yet. * c) other table: the node hasn't been moved yet.
*/ */
nexttable: nexttable:
hash = hash_32(HASHVAL(dnode), rbt->hashbits[hindex]); hash = isc_hash_bits32(HASHVAL(dnode), rbt->hashbits[hindex]);
hnode = rbt->hashtable[hindex][hash]; hnode = rbt->hashtable[hindex][hash];

View File

@ -309,20 +309,7 @@ typedef ISC_LIST(dns_rbtnode_t) rbtnodelist_t;
(((header)->rdh_ttl > (now)) || \ (((header)->rdh_ttl > (now)) || \
((header)->rdh_ttl == (now) && ZEROTTL(header))) ((header)->rdh_ttl == (now) && ZEROTTL(header)))
#define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */ #define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */
#define RBTDB_GLUE_TABLE_INIT_BITS 2U
#define RBTDB_GLUE_TABLE_MAX_BITS 32U
#define RBTDB_GLUE_TABLE_OVERCOMMIT 3
#define GOLDEN_RATIO_32 0x61C88647
#define HASHSIZE(bits) (UINT64_C(1) << (bits))
static uint32_t
hash_32(uint32_t val, unsigned int bits) {
REQUIRE(bits <= RBTDB_GLUE_TABLE_MAX_BITS);
/* High bits are more random. */
return (val * GOLDEN_RATIO_32 >> (32 - bits));
}
/*% /*%
* Number of buckets for cache DB entries (locks, LRU lists, TTL heaps). * Number of buckets for cache DB entries (locks, LRU lists, TTL heaps).
@ -1252,10 +1239,10 @@ allocate_version(isc_mem_t *mctx, rbtdb_serial_t serial,
isc_refcount_init(&version->references, references); isc_refcount_init(&version->references, references);
isc_rwlock_init(&version->glue_rwlock, 0, 0); isc_rwlock_init(&version->glue_rwlock, 0, 0);
version->glue_table_bits = RBTDB_GLUE_TABLE_INIT_BITS; version->glue_table_bits = ISC_HASH_MIN_BITS;
version->glue_table_nodecount = 0U; version->glue_table_nodecount = 0U;
size = HASHSIZE(version->glue_table_bits) * size = ISC_HASHSIZE(version->glue_table_bits) *
sizeof(version->glue_table[0]); sizeof(version->glue_table[0]);
version->glue_table = isc_mem_get(mctx, size); version->glue_table = isc_mem_get(mctx, size);
memset(version->glue_table, 0, size); memset(version->glue_table, 0, size);
@ -9494,7 +9481,7 @@ free_gluetable(rbtdb_version_t *version) {
rbtdb = version->rbtdb; rbtdb = version->rbtdb;
for (i = 0; i < HASHSIZE(version->glue_table_bits); i++) { for (i = 0; i < ISC_HASHSIZE(version->glue_table_bits); i++) {
rbtdb_glue_table_node_t *cur, *cur_next; rbtdb_glue_table_node_t *cur, *cur_next;
cur = version->glue_table[i]; cur = version->glue_table[i];
@ -9510,7 +9497,7 @@ free_gluetable(rbtdb_version_t *version) {
version->glue_table[i] = NULL; version->glue_table[i] = NULL;
} }
size = HASHSIZE(version->glue_table_bits) * size = ISC_HASHSIZE(version->glue_table_bits) *
sizeof(*version->glue_table); sizeof(*version->glue_table);
isc_mem_put(rbtdb->common.mctx, version->glue_table, size); isc_mem_put(rbtdb->common.mctx, version->glue_table, size);
@ -9522,8 +9509,8 @@ rehash_bits(rbtdb_version_t *version, size_t newcount) {
uint32_t oldbits = version->glue_table_bits; uint32_t oldbits = version->glue_table_bits;
uint32_t newbits = oldbits; uint32_t newbits = oldbits;
while (newcount >= HASHSIZE(newbits) && while (newcount >= ISC_HASHSIZE(newbits) &&
newbits <= RBTDB_GLUE_TABLE_MAX_BITS) { newbits <= ISC_HASH_MAX_BITS) {
newbits += 1; newbits += 1;
} }
@ -9540,11 +9527,11 @@ rehash_gluetable(rbtdb_version_t *version) {
rbtdb_glue_table_node_t **oldtable; rbtdb_glue_table_node_t **oldtable;
oldbits = version->glue_table_bits; oldbits = version->glue_table_bits;
oldcount = HASHSIZE(oldbits); oldcount = ISC_HASHSIZE(oldbits);
oldtable = version->glue_table; oldtable = version->glue_table;
newbits = rehash_bits(version, version->glue_table_nodecount); newbits = rehash_bits(version, version->glue_table_nodecount);
newsize = HASHSIZE(newbits) * sizeof(version->glue_table[0]); newsize = ISC_HASHSIZE(newbits) * sizeof(version->glue_table[0]);
version->glue_table = isc_mem_get(version->rbtdb->common.mctx, newsize); version->glue_table = isc_mem_get(version->rbtdb->common.mctx, newsize);
version->glue_table_bits = newbits; version->glue_table_bits = newbits;
@ -9557,7 +9544,7 @@ rehash_gluetable(rbtdb_version_t *version) {
gluenode = nextgluenode) { gluenode = nextgluenode) {
uint32_t hash = isc_hash32( uint32_t hash = isc_hash32(
&gluenode->node, sizeof(gluenode->node), true); &gluenode->node, sizeof(gluenode->node), true);
uint32_t idx = hash_32(hash, newbits); uint32_t idx = isc_hash_bits32(hash, newbits);
nextgluenode = gluenode->next; nextgluenode = gluenode->next;
gluenode->next = version->glue_table[idx]; gluenode->next = version->glue_table[idx];
version->glue_table[idx] = gluenode; version->glue_table[idx] = gluenode;
@ -9577,8 +9564,8 @@ rehash_gluetable(rbtdb_version_t *version) {
static void static void
maybe_rehash_gluetable(rbtdb_version_t *version) { maybe_rehash_gluetable(rbtdb_version_t *version) {
size_t overcommit = HASHSIZE(version->glue_table_bits) * size_t overcommit = ISC_HASHSIZE(version->glue_table_bits) *
RBTDB_GLUE_TABLE_OVERCOMMIT; ISC_HASH_OVERCOMMIT;
if (version->glue_table_nodecount < overcommit) { if (version->glue_table_nodecount < overcommit) {
return; return;
} }
@ -9740,7 +9727,7 @@ restart:
*/ */
RWLOCK(&rbtversion->glue_rwlock, isc_rwlocktype_read); RWLOCK(&rbtversion->glue_rwlock, isc_rwlocktype_read);
idx = hash_32(hash, rbtversion->glue_table_bits); idx = isc_hash_bits32(hash, rbtversion->glue_table_bits);
for (cur = rbtversion->glue_table[idx]; cur != NULL; cur = cur->next) { for (cur = rbtversion->glue_table[idx]; cur != NULL; cur = cur->next) {
if (cur->node == node) { if (cur->node == node) {
@ -9901,7 +9888,7 @@ no_glue:
RWLOCK(&rbtversion->glue_rwlock, isc_rwlocktype_write); RWLOCK(&rbtversion->glue_rwlock, isc_rwlocktype_write);
maybe_rehash_gluetable(rbtversion); maybe_rehash_gluetable(rbtversion);
idx = hash_32(hash, rbtversion->glue_table_bits); idx = isc_hash_bits32(hash, rbtversion->glue_table_bits);
(void)dns_rdataset_additionaldata(rdataset, dns_rootname, (void)dns_rdataset_additionaldata(rdataset, dns_rootname,
glue_nsdname_cb, &ctx); glue_nsdname_cb, &ctx);

View File

@ -19,6 +19,7 @@
#include <isc/atomic.h> #include <isc/atomic.h>
#include <isc/counter.h> #include <isc/counter.h>
#include <isc/hash.h>
#include <isc/log.h> #include <isc/log.h>
#include <isc/print.h> #include <isc/print.h>
#include <isc/random.h> #include <isc/random.h>
@ -211,22 +212,8 @@
#endif /* ifndef RES_DOMAIN_HASH_BITS */ #endif /* ifndef RES_DOMAIN_HASH_BITS */
#define RES_NOBUCKET 0xffffffff #define RES_NOBUCKET 0xffffffff
#define GOLDEN_RATIO_32 0x61C88647
#define HASHSIZE(bits) (UINT64_C(1) << (bits))
#define RES_DOMAIN_MAX_BITS 32
#define RES_DOMAIN_OVERCOMMIT 3
#define RES_DOMAIN_NEXTTABLE(hindex) ((hindex == 0) ? 1 : 0) #define RES_DOMAIN_NEXTTABLE(hindex) ((hindex == 0) ? 1 : 0)
static uint32_t
hash_32(uint32_t val, unsigned int bits) {
REQUIRE(bits <= RES_DOMAIN_MAX_BITS);
/* High bits are more random. */
return (val * GOLDEN_RATIO_32 >> (32 - bits));
}
/*% /*%
* Maximum EDNS0 input packet size. * Maximum EDNS0 input packet size.
*/ */
@ -1578,7 +1565,7 @@ fcount_incr(fetchctx_t *fctx, bool force) {
INSIST(fctx->dbucketnum == RES_NOBUCKET); INSIST(fctx->dbucketnum == RES_NOBUCKET);
hashval = dns_name_fullhash(fctx->domain, false); hashval = dns_name_fullhash(fctx->domain, false);
dbucketnum = hash_32(hashval, fctx->res->dhashbits); dbucketnum = isc_hash_bits32(hashval, fctx->res->dhashbits);
dbucket = &fctx->res->dbuckets[dbucketnum]; dbucket = &fctx->res->dbuckets[dbucketnum];
@ -10108,12 +10095,12 @@ destroy(dns_resolver_t *res) {
} }
isc_mem_put(res->mctx, res->buckets, isc_mem_put(res->mctx, res->buckets,
res->nbuckets * sizeof(fctxbucket_t)); res->nbuckets * sizeof(fctxbucket_t));
for (i = 0; i < HASHSIZE(res->dhashbits); i++) { for (i = 0; i < ISC_HASHSIZE(res->dhashbits); i++) {
INSIST(ISC_LIST_EMPTY(res->dbuckets[i].list)); INSIST(ISC_LIST_EMPTY(res->dbuckets[i].list));
isc_mutex_destroy(&res->dbuckets[i].lock); isc_mutex_destroy(&res->dbuckets[i].lock);
} }
isc_mem_put(res->mctx, res->dbuckets, isc_mem_put(res->mctx, res->dbuckets,
HASHSIZE(res->dhashbits) * sizeof(zonebucket_t)); ISC_HASHSIZE(res->dhashbits) * sizeof(zonebucket_t));
if (res->dispatches4 != NULL) { if (res->dispatches4 != NULL) {
dns_dispatchset_destroy(&res->dispatches4); dns_dispatchset_destroy(&res->dispatches4);
} }
@ -10285,9 +10272,9 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr,
} }
res->dbuckets = isc_mem_get(view->mctx, res->dbuckets = isc_mem_get(view->mctx,
HASHSIZE(res->dhashbits) * ISC_HASHSIZE(res->dhashbits) *
sizeof(res->dbuckets[0])); sizeof(res->dbuckets[0]));
for (size_t i = 0; i < HASHSIZE(res->dhashbits); i++) { for (size_t i = 0; i < ISC_HASHSIZE(res->dhashbits); i++) {
res->dbuckets[i] = (zonebucket_t){ .list = { 0 } }; res->dbuckets[i] = (zonebucket_t){ .list = { 0 } };
ISC_LIST_INIT(res->dbuckets[i].list); ISC_LIST_INIT(res->dbuckets[i].list);
isc_mutex_init(&res->dbuckets[i].lock); isc_mutex_init(&res->dbuckets[i].lock);
@ -10333,11 +10320,11 @@ cleanup_primelock:
dns_dispatchset_destroy(&res->dispatches4); dns_dispatchset_destroy(&res->dispatches4);
} }
for (size_t i = 0; i < HASHSIZE(res->dhashbits); i++) { for (size_t i = 0; i < ISC_HASHSIZE(res->dhashbits); i++) {
isc_mutex_destroy(&res->dbuckets[i].lock); isc_mutex_destroy(&res->dbuckets[i].lock);
} }
isc_mem_put(view->mctx, res->dbuckets, isc_mem_put(view->mctx, res->dbuckets,
HASHSIZE(res->dhashbits) * sizeof(zonebucket_t)); ISC_HASHSIZE(res->dhashbits) * sizeof(zonebucket_t));
cleanup_buckets: cleanup_buckets:
for (size_t i = 0; i < ntasks; i++) { for (size_t i = 0; i < ntasks; i++) {
@ -11518,7 +11505,7 @@ dns_resolver_dumpfetches(dns_resolver_t *resolver, isc_statsformat_t format,
REQUIRE(fp != NULL); REQUIRE(fp != NULL);
REQUIRE(format == isc_statsformat_file); REQUIRE(format == isc_statsformat_file);
for (size_t i = 0; i < HASHSIZE(resolver->dhashbits); i++) { for (size_t i = 0; i < ISC_HASHSIZE(resolver->dhashbits); i++) {
fctxcount_t *fc; fctxcount_t *fc;
LOCK(&resolver->dbuckets[i].lock); LOCK(&resolver->dbuckets[i].lock);
for (fc = ISC_LIST_HEAD(resolver->dbuckets[i].list); fc != NULL; for (fc = ISC_LIST_HEAD(resolver->dbuckets[i].list); fc != NULL;

View File

@ -19,6 +19,7 @@
#include <isc/atomic.h> #include <isc/atomic.h>
#include <isc/file.h> #include <isc/file.h>
#include <isc/hash.h>
#include <isc/hex.h> #include <isc/hex.h>
#include <isc/md.h> #include <isc/md.h>
#include <isc/mutex.h> #include <isc/mutex.h>
@ -18504,26 +18505,10 @@ dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
*** Zone manager. *** Zone manager.
***/ ***/
#define KEYMGMT_OVERCOMMIT 3
#define KEYMGMT_BITS_MIN 2U
#define KEYMGMT_BITS_MAX 32U
/*
* WMM: Static hash functions copied from lib/dns/rbtdb.c. Should be moved to
* lib/isc/hash.c when we refactor the hash table code.
*/
#define GOLDEN_RATIO_32 0x61C88647
#define HASHSIZE(bits) (UINT64_C(1) << (bits))
static uint32_t
hash_index(uint32_t val, uint32_t bits) {
return (val * GOLDEN_RATIO_32 >> (32 - bits));
}
static uint32_t static uint32_t
hash_bits_grow(uint32_t bits, uint32_t count) { hash_bits_grow(uint32_t bits, uint32_t count) {
uint32_t newbits = bits; uint32_t newbits = bits;
while (count >= HASHSIZE(newbits) && newbits < KEYMGMT_BITS_MAX) { while (count >= ISC_HASHSIZE(newbits) && newbits < ISC_HASH_MAX_BITS) {
newbits++; newbits++;
} }
return (newbits); return (newbits);
@ -18532,7 +18517,7 @@ hash_bits_grow(uint32_t bits, uint32_t count) {
static uint32_t static uint32_t
hash_bits_shrink(uint32_t bits, uint32_t count) { hash_bits_shrink(uint32_t bits, uint32_t count) {
uint32_t newbits = bits; uint32_t newbits = bits;
while (count <= HASHSIZE(newbits) && newbits > KEYMGMT_BITS_MIN) { while (count <= ISC_HASHSIZE(newbits) && newbits > ISC_HASH_MIN_BITS) {
newbits--; newbits--;
} }
return (newbits); return (newbits);
@ -18544,12 +18529,12 @@ zonemgr_keymgmt_init(dns_zonemgr_t *zmgr) {
uint32_t size; uint32_t size;
*mgmt = (dns_keymgmt_t){ *mgmt = (dns_keymgmt_t){
.bits = KEYMGMT_BITS_MIN, .bits = ISC_HASH_MIN_BITS,
}; };
isc_mem_attach(zmgr->mctx, &mgmt->mctx); isc_mem_attach(zmgr->mctx, &mgmt->mctx);
isc_rwlock_init(&mgmt->lock, 0, 0); isc_rwlock_init(&mgmt->lock, 0, 0);
size = HASHSIZE(mgmt->bits); size = ISC_HASHSIZE(mgmt->bits);
mgmt->table = isc_mem_get(mgmt->mctx, sizeof(*mgmt->table) * size); mgmt->table = isc_mem_get(mgmt->mctx, sizeof(*mgmt->table) * size);
memset(mgmt->table, 0, size * sizeof(mgmt->table[0])); memset(mgmt->table, 0, size * sizeof(mgmt->table[0]));
@ -18568,7 +18553,7 @@ zonemgr_keymgmt_destroy(dns_zonemgr_t *zmgr) {
REQUIRE(DNS_KEYMGMT_VALID(mgmt)); REQUIRE(DNS_KEYMGMT_VALID(mgmt));
RWLOCK(&mgmt->lock, isc_rwlocktype_write); RWLOCK(&mgmt->lock, isc_rwlocktype_write);
size = HASHSIZE(mgmt->bits); size = ISC_HASHSIZE(mgmt->bits);
for (unsigned int i = 0; for (unsigned int i = 0;
atomic_load_relaxed(&mgmt->count) > 0 && i < size; i++) { atomic_load_relaxed(&mgmt->count) > 0 && i < size; i++) {
for (curr = mgmt->table[i]; curr != NULL; curr = next) { for (curr = mgmt->table[i]; curr != NULL; curr = next) {
@ -18601,10 +18586,10 @@ zonemgr_keymgmt_resize(dns_zonemgr_t *zmgr) {
bits = mgmt->bits; bits = mgmt->bits;
RWUNLOCK(&mgmt->lock, isc_rwlocktype_read); RWUNLOCK(&mgmt->lock, isc_rwlocktype_read);
size = HASHSIZE(bits); size = ISC_HASHSIZE(bits);
INSIST(size > 0); INSIST(size > 0);
if (count >= (size * KEYMGMT_OVERCOMMIT)) { if (count >= (size * ISC_HASH_OVERCOMMIT)) {
grow = true; grow = true;
} else if (count < (size / 2)) { } else if (count < (size / 2)) {
grow = false; grow = false;
@ -18627,7 +18612,7 @@ zonemgr_keymgmt_resize(dns_zonemgr_t *zmgr) {
return; return;
} }
newsize = HASHSIZE(newbits); newsize = ISC_HASHSIZE(newbits);
INSIST(newsize > 0); INSIST(newsize > 0);
RWLOCK(&mgmt->lock, isc_rwlocktype_write); RWLOCK(&mgmt->lock, isc_rwlocktype_write);
@ -18638,7 +18623,7 @@ zonemgr_keymgmt_resize(dns_zonemgr_t *zmgr) {
for (unsigned int i = 0; i < size; i++) { for (unsigned int i = 0; i < size; i++) {
dns_keyfileio_t *kfio, *next; dns_keyfileio_t *kfio, *next;
for (kfio = mgmt->table[i]; kfio != NULL; kfio = next) { for (kfio = mgmt->table[i]; kfio != NULL; kfio = next) {
uint32_t hash = hash_index(kfio->hashval, newbits); uint32_t hash = isc_hash_bits32(kfio->hashval, newbits);
next = kfio->next; next = kfio->next;
kfio->next = newtable[hash]; kfio->next = newtable[hash];
newtable[hash] = kfio; newtable[hash] = kfio;
@ -18665,7 +18650,7 @@ zonemgr_keymgmt_add(dns_zonemgr_t *zmgr, dns_zone_t *zone,
RWLOCK(&mgmt->lock, isc_rwlocktype_write); RWLOCK(&mgmt->lock, isc_rwlocktype_write);
hashval = dns_name_hash(&zone->origin, false); hashval = dns_name_hash(&zone->origin, false);
hash = hash_index(hashval, mgmt->bits); hash = isc_hash_bits32(hashval, mgmt->bits);
for (kfio = mgmt->table[hash]; kfio != NULL; kfio = next) { for (kfio = mgmt->table[hash]; kfio != NULL; kfio = next) {
next = kfio->next; next = kfio->next;
@ -18718,7 +18703,7 @@ zonemgr_keymgmt_delete(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
RWLOCK(&mgmt->lock, isc_rwlocktype_write); RWLOCK(&mgmt->lock, isc_rwlocktype_write);
hashval = dns_name_hash(&zone->origin, false); hashval = dns_name_hash(&zone->origin, false);
hash = hash_index(hashval, mgmt->bits); hash = isc_hash_bits32(hashval, mgmt->bits);
prev = NULL; prev = NULL;
for (kfio = mgmt->table[hash]; kfio != NULL; kfio = next) { for (kfio = mgmt->table[hash]; kfio != NULL; kfio = next) {
@ -18776,7 +18761,7 @@ zonemgr_keymgmt_find(dns_zonemgr_t *zmgr, dns_zone_t *zone,
} }
hashval = dns_name_hash(&zone->origin, false); hashval = dns_name_hash(&zone->origin, false);
hash = hash_index(hashval, mgmt->bits); hash = isc_hash_bits32(hashval, mgmt->bits);
for (kfio = mgmt->table[hash]; kfio != NULL; kfio = next) { for (kfio = mgmt->table[hash]; kfio != NULL; kfio = next) {
next = kfio->next; next = kfio->next;

View File

@ -16,8 +16,14 @@
#include <inttypes.h> #include <inttypes.h>
#include <stdbool.h> #include <stdbool.h>
#include "isc/lang.h" #include <isc/assertions.h>
#include "isc/types.h" #include <isc/lang.h>
#include <isc/types.h>
#define ISC_HASHSIZE(bits) (UINT64_C(1) << (bits))
#define ISC_HASH_OVERCOMMIT 3
#define ISC_HASH_MIN_BITS 2U
#define ISC_HASH_MAX_BITS 32U
/*** /***
*** Functions *** Functions
@ -60,4 +66,26 @@ isc_hash64(const void *data, const size_t length, const bool case_sensitive);
* \li 32 or 64-bit hash value * \li 32 or 64-bit hash value
*/ */
/*!
* \brief Return a hash value of a specified number of bits
*
* This function uses Fibonacci Hashing to convert a 32 bit hash value
* 'val' into a smaller hash value of up to 'bits' bits. This results
* in better hash table distribution than the use of modulo.
*
* Requires:
* \li 'bits' is less than 32.
*
* Returns:
* \li a hash value of length 'bits'.
*/
#define ISC_HASH_GOLDENRATIO_32 0x61C88647
#define isc_hash_bits32(val, bits) \
({ \
REQUIRE(bits <= 32U); \
uint32_t __v = (val & 0xffff); \
__v = ((__v * ISC_HASH_GOLDENRATIO_32) >> (32 - bits)); \
__v; \
})
ISC_LANG_ENDDECLS ISC_LANG_ENDDECLS