kern: Add phashinit_flags(), which allows malloc(M_NOWAIT)

It will be used for the upcoming LRO hash table initialization.
And probably will be useful in other cases, when M_WAITOK can't
be used.

Reviewed by:	jhb, kib
Sponsored by:	Microsoft OSTC
Differential Revision:	https://reviews.freebsd.org/D6138
This commit is contained in:
Sepherosa Ziehau 2016-05-03 07:17:13 +00:00
parent 453130d9bf
commit f8ce3dfaf1
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=298956
3 changed files with 46 additions and 9 deletions

View File

@ -25,11 +25,11 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd January 23, 2016 .Dd April 29, 2016
.Dt HASHINIT 9 .Dt HASHINIT 9
.Os .Os
.Sh NAME .Sh NAME
.Nm hashinit , hashinit_flags , hashdestroy , phashinit .Nm hashinit , hashinit_flags , hashdestroy , phashinit , phashinit_flags
.Nd manage kernel hash tables .Nd manage kernel hash tables
.Sh SYNOPSIS .Sh SYNOPSIS
.In sys/malloc.h .In sys/malloc.h
@ -45,12 +45,14 @@
.Fn hashdestroy "void *hashtbl" "struct malloc_type *type" "u_long hashmask" .Fn hashdestroy "void *hashtbl" "struct malloc_type *type" "u_long hashmask"
.Ft "void *" .Ft "void *"
.Fn phashinit "int nelements" "struct malloc_type *type" "u_long *nentries" .Fn phashinit "int nelements" "struct malloc_type *type" "u_long *nentries"
.Fn phashinit_flags "int nelements" "struct malloc_type *type" "u_long *nentries" "int flags"
.Sh DESCRIPTION .Sh DESCRIPTION
The The
.Fn hashinit , .Fn hashinit ,
.Fn hashinit_flags .Fn hashinit_flags ,
and
.Fn phashinit .Fn phashinit
and
.Fn phashinit_flags
functions allocate space for hash tables of size given by the argument functions allocate space for hash tables of size given by the argument
.Fa nelements . .Fa nelements .
.Pp .Pp
@ -71,6 +73,12 @@ function operates like
but also accepts an additional argument but also accepts an additional argument
.Fa flags .Fa flags
which control various options during allocation. which control various options during allocation.
.Fn phashinit_flags
function operates like
.Fn phashinit
but also accepts an additional argument
.Fa flags
which control various options during allocation.
Allocated hash tables are contiguous arrays of Allocated hash tables are contiguous arrays of
.Xr LIST_HEAD 3 .Xr LIST_HEAD 3
entries, allocated using entries, allocated using
@ -100,13 +108,19 @@ must be used with one of the following values.
.It Dv HASH_NOWAIT .It Dv HASH_NOWAIT
Any malloc performed by the Any malloc performed by the
.Fn hashinit_flags .Fn hashinit_flags
and
.Fn phashinit_flags
function will not be allowed to wait, and therefore may fail. function will not be allowed to wait, and therefore may fail.
.It Dv HASH_WAITOK .It Dv HASH_WAITOK
Any malloc performed by Any malloc performed by
.Fn hashinit_flags .Fn hashinit_flags
and
.Fn phashinit_flags
function is allowed to wait for memory. function is allowed to wait for memory.
This is also the behavior of This is also the behavior of
.Fn hashinit . .Fn hashinit
and
.Fn phashinit .
.El .El
.Sh IMPLEMENTATION NOTES .Sh IMPLEMENTATION NOTES
The largest prime hash value chosen by The largest prime hash value chosen by

View File

@ -104,16 +104,21 @@ static const int primes[] = { 1, 13, 31, 61, 127, 251, 509, 761, 1021, 1531,
#define NPRIMES nitems(primes) #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 * 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; long hashsize;
LIST_HEAD(generic, generic) *hashtbl; LIST_HEAD(generic, generic) *hashtbl;
int i; int i, m_flags;
KASSERT(elements > 0, ("%s: bad elements", __func__)); 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;) { for (i = 1, hashsize = primes[1]; hashsize <= elements;) {
i++; i++;
if (i == NPRIMES) if (i == NPRIMES)
@ -121,9 +126,25 @@ phashinit(int elements, struct malloc_type *type, u_long *nentries)
hashsize = primes[i]; hashsize = primes[i];
} }
hashsize = primes[i - 1]; hashsize = primes[i - 1];
hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK);
m_flags = (flags & HASH_NOWAIT) ? M_NOWAIT : M_WAITOK;
hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, m_flags);
if (hashtbl == NULL)
return (NULL);
for (i = 0; i < hashsize; i++) for (i = 0; i < hashsize; i++)
LIST_INIT(&hashtbl[i]); LIST_INIT(&hashtbl[i]);
*nentries = hashsize; *nentries = hashsize;
return (hashtbl); 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));
}

View File

@ -189,6 +189,8 @@ void *hashinit_flags(int count, struct malloc_type *type,
#define HASH_WAITOK 0x00000002 #define HASH_WAITOK 0x00000002
void *phashinit(int count, struct malloc_type *type, u_long *nentries); void *phashinit(int count, struct malloc_type *type, u_long *nentries);
void *phashinit_flags(int count, struct malloc_type *type, u_long *nentries,
int flags);
void g_waitidle(void); void g_waitidle(void);
void panic(const char *, ...) __dead2 __printflike(1, 2); void panic(const char *, ...) __dead2 __printflike(1, 2);