From b939bb368a066226976eaa73e48128f94e283a9f Mon Sep 17 00:00:00 2001 From: Randall Stewart Date: Mon, 15 Jan 2007 15:06:28 +0000 Subject: [PATCH] Reviewed by: rwatson Approved by: gnn Add a new function hashinit_flags() which allows NOT-waiting for memory (or waiting). The old hashinit() function now calls hashinit_flags(..., HASH_WAITOK); --- share/man/man9/Makefile | 3 ++- share/man/man9/hashinit.9 | 28 ++++++++++++++++++++++++-- sys/kern/kern_subr.c | 42 +++++++++++++++++++++++++++++++++------ sys/sys/systm.h | 7 ++++++- 4 files changed, 70 insertions(+), 10 deletions(-) diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index c50a0b57f9b1..6cab4a45c9fd 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 15fdb3bc0361..888e7f5ba9f2 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 ba288acfcdfc..cc195376577e 100644 --- a/sys/kern/kern_subr.c +++ b/sys/kern/kern_subr.c @@ -358,10 +358,11 @@ ureadc(int c, struct uio *uio) } /* - * 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 96b937da3531..e84bf1b2ab16 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);