summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_subr.c42
-rw-r--r--sys/sys/systm.h7
2 files changed, 42 insertions, 7 deletions
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