diff options
Diffstat (limited to 'freebsd/sys/kern/subr_hash.c')
-rw-r--r-- | freebsd/sys/kern/subr_hash.c | 48 |
1 files changed, 36 insertions, 12 deletions
diff --git a/freebsd/sys/kern/subr_hash.c b/freebsd/sys/kern/subr_hash.c index e526a866..1371a345 100644 --- a/freebsd/sys/kern/subr_hash.c +++ b/freebsd/sys/kern/subr_hash.c @@ -43,6 +43,13 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <sys/malloc.h> +static __inline int +hash_mflags(int flags) +{ + + return ((flags & HASH_NOWAIT) ? M_NOWAIT : M_WAITOK); +} + /* * General routine to allocate a hash table with control of memory flags. */ @@ -63,13 +70,8 @@ hashinit_flags(int elements, struct malloc_type *type, u_long *hashmask, continue; hashsize >>= 1; - if (flags & HASH_NOWAIT) - hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), - type, M_NOWAIT); - else - hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), - type, M_WAITOK); - + hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, + hash_mflags(flags)); if (hashtbl != NULL) { for (i = 0; i < hashsize; i++) LIST_INIT(&hashtbl[i]); @@ -95,26 +97,32 @@ hashdestroy(void *vhashtbl, struct malloc_type *type, u_long hashmask) hashtbl = vhashtbl; for (hp = hashtbl; hp <= &hashtbl[hashmask]; hp++) - KASSERT(LIST_EMPTY(hp), ("%s: hash not empty", __func__)); + KASSERT(LIST_EMPTY(hp), ("%s: hashtbl %p not empty " + "(malloc type %s)", __func__, hashtbl, type->ks_shortdesc)); free(hashtbl, type); } static const int primes[] = { 1, 13, 31, 61, 127, 251, 509, 761, 1021, 1531, 2039, 2557, 3067, 3583, 4093, 4603, 5119, 5623, 6143, 6653, 7159, 7673, 8191, 12281, 16381, 24571, 32749 }; -#define NPRIMES (sizeof(primes) / sizeof(primes[0])) +#define NPRIMES nitems(primes) /* - * General routine to allocate a prime number sized hash table. + * General routine to allocate a prime number sized hash table with control of + * memory flags. */ void * -phashinit(int elements, struct malloc_type *type, u_long *nentries) +phashinit_flags(int elements, struct malloc_type *type, u_long *nentries, int flags) { long hashsize; LIST_HEAD(generic, generic) *hashtbl; int i; KASSERT(elements > 0, ("%s: bad elements", __func__)); + /* Exactly one of HASH_WAITOK and HASH_NOWAIT must be set. */ + KASSERT((flags & HASH_WAITOK) ^ (flags & HASH_NOWAIT), + ("Bad flags (0x%x) passed to phashinit_flags", flags)); + for (i = 1, hashsize = primes[1]; hashsize <= elements;) { i++; if (i == NPRIMES) @@ -122,9 +130,25 @@ phashinit(int elements, struct malloc_type *type, u_long *nentries) hashsize = primes[i]; } hashsize = primes[i - 1]; - hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK); + + hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, + hash_mflags(flags)); + if (hashtbl == NULL) + return (NULL); + for (i = 0; i < hashsize; i++) LIST_INIT(&hashtbl[i]); *nentries = hashsize; return (hashtbl); } + +/* + * Allocate and initialize a prime number sized hash table with default flag: + * may sleep. + */ +void * +phashinit(int elements, struct malloc_type *type, u_long *nentries) +{ + + return (phashinit_flags(elements, type, nentries, HASH_WAITOK)); +} |