summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/kern/subr_hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/kern/subr_hash.c')
-rw-r--r--freebsd/sys/kern/subr_hash.c48
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));
+}