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$
.\"
.Dd January 23, 2016
.Dd April 29, 2016
.Dt HASHINIT 9
.Os
.Sh NAME
.Nm hashinit , hashinit_flags , hashdestroy , phashinit
.Nm hashinit , hashinit_flags , hashdestroy , phashinit , phashinit_flags
.Nd manage kernel hash tables
.Sh SYNOPSIS
.In sys/malloc.h
@ -45,12 +45,14 @@
.Fn hashdestroy "void *hashtbl" "struct malloc_type *type" "u_long hashmask"
.Ft "void *"
.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
The
.Fn hashinit ,
.Fn hashinit_flags
and
.Fn hashinit_flags ,
.Fn phashinit
and
.Fn phashinit_flags
functions allocate space for hash tables of size given by the argument
.Fa nelements .
.Pp
@ -71,6 +73,12 @@ function operates like
but also accepts an additional argument
.Fa flags
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
.Xr LIST_HEAD 3
entries, allocated using
@ -100,13 +108,19 @@ must be used with one of the following values.
.It Dv HASH_NOWAIT
Any malloc performed by the
.Fn hashinit_flags
and
.Fn phashinit_flags
function will not be allowed to wait, and therefore may fail.
.It Dv HASH_WAITOK
Any malloc performed by
.Fn hashinit_flags
and
.Fn phashinit_flags
function is allowed to wait for memory.
This is also the behavior of
.Fn hashinit .
.Fn hashinit
and
.Fn phashinit .
.El
.Sh IMPLEMENTATION NOTES
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)
/*
* 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 *
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;
LIST_HEAD(generic, generic) *hashtbl;
int i;
int i, m_flags;
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;) {
i++;
if (i == NPRIMES)
@ -121,9 +126,25 @@ phashinit(int elements, struct malloc_type *type, u_long *nentries)
hashsize = primes[i];
}
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++)
LIST_INIT(&hashtbl[i]);
*nentries = hashsize;
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
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 panic(const char *, ...) __dead2 __printflike(1, 2);