summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/man/man9/Makefile3
-rw-r--r--share/man/man9/hashinit.928
-rw-r--r--sys/kern/kern_subr.c42
-rw-r--r--sys/sys/systm.h7
4 files changed, 70 insertions, 10 deletions
diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile
index c50a0b5..6cab4a4 100644
--- a/share/man/man9/Makefile
+++ b/share/man/man9/Makefile
@@ -599,7 +599,8 @@ MLINKS+=hash.9 hash32.9 \
hash.9 hash32_strn.9 \
hash.9 hash32_strne.9
MLINKS+=hashinit.9 hashdestroy.9 \
- hashinit.9 phashinit.9
+ hashinit.9 phashinit.9 \
+ hashinit.9 hashinit_flags.9
MLINKS+=ieee80211.9 ieee80211_attach.9 \
ieee80211.9 ieee80211_chan2ieee.9 \
ieee80211.9 ieee80211_chan2mode.9 \
diff --git a/share/man/man9/hashinit.9 b/share/man/man9/hashinit.9
index 15fdb3b..888e7f5 100644
--- a/share/man/man9/hashinit.9
+++ b/share/man/man9/hashinit.9
@@ -29,7 +29,7 @@
.Dt HASHINIT 9
.Os
.Sh NAME
-.Nm hashinit , hashdestroy , phashinit
+.Nm hashinit , hashinit_flags, hashdestroy , phashinit
.Nd manage kernel hash tables
.Sh SYNOPSIS
.In sys/malloc.h
@@ -38,12 +38,15 @@
.Ft "void *"
.Fn hashinit "int nelements" "struct malloc_type *type" "u_long *hashmask"
.Ft void
+.Fn hashinit_flags "int nelements" "struct malloc_type *type" "u_long *hashmask" "int flags"
+.Ft void
.Fn hashdestroy "void *hashtbl" "struct malloc_type *type" "u_long hashmask"
.Ft "void *"
.Fn phashinit "int nelements" "struct malloc_type *type" "u_long *nentries"
.Sh DESCRIPTION
The
-.Fn hashinit
+.Fn hashinit ,
+.Fn hashinit_flags
and
.Fn phashinit
functions allocate space for hash tables of size given by the argument
@@ -59,6 +62,13 @@ The
function allocates hash tables that are sized to the largest prime
number less than or equal to argument
.Fa nelements .
+The
+.Fn hashinit_flags
+functionn operates like
+.Fn hashinit
+but also accepts an additional argument
+.Fa flags
+which control various options during allocation.
Allocated hash tables are contiguous arrays of
.Xr LIST_HEAD 3
entries, allocated using
@@ -80,6 +90,20 @@ The argument
should be the bit mask returned by the call to
.Fn hashinit
that allocated the hash table.
+The argument
+.Fa flags
+must be used with one of the following values.
+.Pp
+.Bl -tag -width ".Dv HASH_NOWAIT" -offset indent -compact
+.It Dv HASH_NOWAIT
+Any malloc performed by the
+.Fn hashinit_flags
+function will not be allowed to wait, and therefore may fail.
+.It Dv HASH_WAITOK
+Any malloc performed by the
+.Fn hashinit_flags
+function is allowed to wait for memory.
+.El
.Sh IMPLEMENTATION NOTES
The largest prime hash value chosen by
.Fn phashinit
diff --git a/sys/kern/kern_subr.c b/sys/kern/kern_subr.c
index ba288ac..cc19537 100644
--- a/sys/kern/kern_subr.c
+++ b/sys/kern/kern_subr.c
@@ -358,10 +358,11 @@ again:
}
/*
- * General routine to allocate a hash table.
+ * General routine to allocate a hash table with control of memory flags.
*/
void *
-hashinit(int elements, struct malloc_type *type, u_long *hashmask)
+hashinit_flags(int elements, struct malloc_type *type, u_long *hashmask,
+ int flags)
{
long hashsize;
LIST_HEAD(generic, generic) *hashtbl;
@@ -369,16 +370,45 @@ hashinit(int elements, struct malloc_type *type, u_long *hashmask)
if (elements <= 0)
panic("hashinit: bad elements");
+
+ /* Check for valid flags. */
+ KASSERT(flags | (HASH_WAITOK | HASH_NOWAIT) ==
+ (HASH_WAITOK | HASH_NOWAIT),
+ ("Bad flags (0x%x) passed to hashinit_flags", flags));
+
+ /* Exactly one of HASH_WAITOK and HASH_NOWAIT must be set. */
+ KASSERT((flags & HASH_WAITOK) ^ (flags & HASH_NOWAIT),
+ ("Both WAITOK and NOWAIT passed to hashinit_flags"));
+
for (hashsize = 1; hashsize <= elements; hashsize <<= 1)
continue;
hashsize >>= 1;
- hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK);
- for (i = 0; i < hashsize; i++)
- LIST_INIT(&hashtbl[i]);
- *hashmask = 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);
+
+ if (hashtbl != NULL) {
+ for (i = 0; i < hashsize; i++)
+ LIST_INIT(&hashtbl[i]);
+ *hashmask = hashsize - 1;
+ }
return (hashtbl);
}
+/*
+ * Allocate and initialize a hash table with default flag: may sleep.
+ */
+void *
+hashinit(int elements, struct malloc_type *type, u_long *hashmask)
+{
+
+ return (hashinit_flags(elements, type, hashmask, HASH_WAITOK));
+}
+
void
hashdestroy(void *vhashtbl, struct malloc_type *type, u_long hashmask)
{
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index 96b937d..e84bf1b 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -134,7 +134,12 @@ int nullop(void);
int eopnotsupp(void);
int ureadc(int, struct uio *);
void hashdestroy(void *, struct malloc_type *, u_long);
-void *hashinit(int count, struct malloc_type *type, u_long *hashmask);
+void *hashinit(int count, struct malloc_type *type, u_long *hashmark);
+void *hashinit_flags(int count, struct malloc_type *type,
+ u_long *hashmask, int flags);
+#define HASH_NOWAIT 0x00000001
+#define HASH_WAITOK 0x00000002
+
void *phashinit(int count, struct malloc_type *type, u_long *nentries);
void g_waitidle(void);
OpenPOWER on IntegriCloud