diff options
-rw-r--r-- | share/man/man9/Makefile | 3 | ||||
-rw-r--r-- | share/man/man9/hashinit.9 | 28 | ||||
-rw-r--r-- | sys/kern/kern_subr.c | 42 | ||||
-rw-r--r-- | 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 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); |