128993443SEd Schouten /*- 228993443SEd Schouten * Copyright (c) 1982, 1986, 1991, 1993 328993443SEd Schouten * The Regents of the University of California. All rights reserved. 428993443SEd Schouten * (c) UNIX System Laboratories, Inc. 528993443SEd Schouten * All or some portions of this file are derived from material licensed 628993443SEd Schouten * to the University of California by American Telephone and Telegraph 728993443SEd Schouten * Co. or Unix System Laboratories, Inc. and are reproduced herein with 828993443SEd Schouten * the permission of UNIX System Laboratories, Inc. 928993443SEd Schouten * 1028993443SEd Schouten * Redistribution and use in source and binary forms, with or without 1128993443SEd Schouten * modification, are permitted provided that the following conditions 1228993443SEd Schouten * are met: 1328993443SEd Schouten * 1. Redistributions of source code must retain the above copyright 1428993443SEd Schouten * notice, this list of conditions and the following disclaimer. 1528993443SEd Schouten * 2. Redistributions in binary form must reproduce the above copyright 1628993443SEd Schouten * notice, this list of conditions and the following disclaimer in the 1728993443SEd Schouten * documentation and/or other materials provided with the distribution. 18*69a28758SEd Maste * 3. Neither the name of the University nor the names of its contributors 1928993443SEd Schouten * may be used to endorse or promote products derived from this software 2028993443SEd Schouten * without specific prior written permission. 2128993443SEd Schouten * 2228993443SEd Schouten * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2328993443SEd Schouten * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2428993443SEd Schouten * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2528993443SEd Schouten * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2628993443SEd Schouten * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2728993443SEd Schouten * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2828993443SEd Schouten * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2928993443SEd Schouten * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3028993443SEd Schouten * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3128993443SEd Schouten * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3228993443SEd Schouten * SUCH DAMAGE. 3328993443SEd Schouten * 3428993443SEd Schouten * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 3528993443SEd Schouten */ 3628993443SEd Schouten 3728993443SEd Schouten #include <sys/cdefs.h> 3828993443SEd Schouten __FBSDID("$FreeBSD$"); 3928993443SEd Schouten 4028993443SEd Schouten #include <sys/param.h> 4128993443SEd Schouten #include <sys/systm.h> 4228993443SEd Schouten #include <sys/malloc.h> 4328993443SEd Schouten 44d5f0ea7cSSepherosa Ziehau static __inline int 45d5f0ea7cSSepherosa Ziehau hash_mflags(int flags) 46d5f0ea7cSSepherosa Ziehau { 47d5f0ea7cSSepherosa Ziehau 48d5f0ea7cSSepherosa Ziehau return ((flags & HASH_NOWAIT) ? M_NOWAIT : M_WAITOK); 49d5f0ea7cSSepherosa Ziehau } 50d5f0ea7cSSepherosa Ziehau 5128993443SEd Schouten /* 5228993443SEd Schouten * General routine to allocate a hash table with control of memory flags. 5328993443SEd Schouten */ 5428993443SEd Schouten void * 5528993443SEd Schouten hashinit_flags(int elements, struct malloc_type *type, u_long *hashmask, 5628993443SEd Schouten int flags) 5728993443SEd Schouten { 5828993443SEd Schouten long hashsize; 5928993443SEd Schouten LIST_HEAD(generic, generic) *hashtbl; 6028993443SEd Schouten int i; 6128993443SEd Schouten 6293a1b4c4SGleb Smirnoff KASSERT(elements > 0, ("%s: bad elements", __func__)); 6328993443SEd Schouten /* Exactly one of HASH_WAITOK and HASH_NOWAIT must be set. */ 6428993443SEd Schouten KASSERT((flags & HASH_WAITOK) ^ (flags & HASH_NOWAIT), 6528993443SEd Schouten ("Bad flags (0x%x) passed to hashinit_flags", flags)); 6628993443SEd Schouten 6728993443SEd Schouten for (hashsize = 1; hashsize <= elements; hashsize <<= 1) 6828993443SEd Schouten continue; 6928993443SEd Schouten hashsize >>= 1; 7028993443SEd Schouten 71d5f0ea7cSSepherosa Ziehau hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, 72d5f0ea7cSSepherosa Ziehau hash_mflags(flags)); 7328993443SEd Schouten if (hashtbl != NULL) { 7428993443SEd Schouten for (i = 0; i < hashsize; i++) 7528993443SEd Schouten LIST_INIT(&hashtbl[i]); 7628993443SEd Schouten *hashmask = hashsize - 1; 7728993443SEd Schouten } 7828993443SEd Schouten return (hashtbl); 7928993443SEd Schouten } 8028993443SEd Schouten 8128993443SEd Schouten /* 8228993443SEd Schouten * Allocate and initialize a hash table with default flag: may sleep. 8328993443SEd Schouten */ 8428993443SEd Schouten void * 8528993443SEd Schouten hashinit(int elements, struct malloc_type *type, u_long *hashmask) 8628993443SEd Schouten { 8728993443SEd Schouten 8828993443SEd Schouten return (hashinit_flags(elements, type, hashmask, HASH_WAITOK)); 8928993443SEd Schouten } 9028993443SEd Schouten 9128993443SEd Schouten void 9228993443SEd Schouten hashdestroy(void *vhashtbl, struct malloc_type *type, u_long hashmask) 9328993443SEd Schouten { 9428993443SEd Schouten LIST_HEAD(generic, generic) *hashtbl, *hp; 9528993443SEd Schouten 9628993443SEd Schouten hashtbl = vhashtbl; 9728993443SEd Schouten for (hp = hashtbl; hp <= &hashtbl[hashmask]; hp++) 98029f99dcSBjoern A. Zeeb KASSERT(LIST_EMPTY(hp), ("%s: hashtbl %p not empty " 99029f99dcSBjoern A. Zeeb "(malloc type %s)", __func__, hashtbl, type->ks_shortdesc)); 10028993443SEd Schouten free(hashtbl, type); 10128993443SEd Schouten } 10228993443SEd Schouten 10328993443SEd Schouten static const int primes[] = { 1, 13, 31, 61, 127, 251, 509, 761, 1021, 1531, 10428993443SEd Schouten 2039, 2557, 3067, 3583, 4093, 4603, 5119, 5623, 6143, 10528993443SEd Schouten 6653, 7159, 7673, 8191, 12281, 16381, 24571, 32749 }; 10602abd400SPedro F. Giffuni #define NPRIMES nitems(primes) 10728993443SEd Schouten 10828993443SEd Schouten /* 109f8ce3dfaSSepherosa Ziehau * General routine to allocate a prime number sized hash table with control of 110f8ce3dfaSSepherosa Ziehau * memory flags. 11128993443SEd Schouten */ 11228993443SEd Schouten void * 113f8ce3dfaSSepherosa Ziehau phashinit_flags(int elements, struct malloc_type *type, u_long *nentries, int flags) 11428993443SEd Schouten { 11528993443SEd Schouten long hashsize; 11628993443SEd Schouten LIST_HEAD(generic, generic) *hashtbl; 117d5f0ea7cSSepherosa Ziehau int i; 11828993443SEd Schouten 11993a1b4c4SGleb Smirnoff KASSERT(elements > 0, ("%s: bad elements", __func__)); 120f8ce3dfaSSepherosa Ziehau /* Exactly one of HASH_WAITOK and HASH_NOWAIT must be set. */ 121f8ce3dfaSSepherosa Ziehau KASSERT((flags & HASH_WAITOK) ^ (flags & HASH_NOWAIT), 122f8ce3dfaSSepherosa Ziehau ("Bad flags (0x%x) passed to phashinit_flags", flags)); 123f8ce3dfaSSepherosa Ziehau 12428993443SEd Schouten for (i = 1, hashsize = primes[1]; hashsize <= elements;) { 12528993443SEd Schouten i++; 12628993443SEd Schouten if (i == NPRIMES) 12728993443SEd Schouten break; 12828993443SEd Schouten hashsize = primes[i]; 12928993443SEd Schouten } 13028993443SEd Schouten hashsize = primes[i - 1]; 131f8ce3dfaSSepherosa Ziehau 132d5f0ea7cSSepherosa Ziehau hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, 133d5f0ea7cSSepherosa Ziehau hash_mflags(flags)); 134f8ce3dfaSSepherosa Ziehau if (hashtbl == NULL) 135f8ce3dfaSSepherosa Ziehau return (NULL); 136f8ce3dfaSSepherosa Ziehau 13728993443SEd Schouten for (i = 0; i < hashsize; i++) 13828993443SEd Schouten LIST_INIT(&hashtbl[i]); 13928993443SEd Schouten *nentries = hashsize; 14028993443SEd Schouten return (hashtbl); 14128993443SEd Schouten } 142f8ce3dfaSSepherosa Ziehau 143f8ce3dfaSSepherosa Ziehau /* 144f8ce3dfaSSepherosa Ziehau * Allocate and initialize a prime number sized hash table with default flag: 145f8ce3dfaSSepherosa Ziehau * may sleep. 146f8ce3dfaSSepherosa Ziehau */ 147f8ce3dfaSSepherosa Ziehau void * 148f8ce3dfaSSepherosa Ziehau phashinit(int elements, struct malloc_type *type, u_long *nentries) 149f8ce3dfaSSepherosa Ziehau { 150f8ce3dfaSSepherosa Ziehau 151f8ce3dfaSSepherosa Ziehau return (phashinit_flags(elements, type, nentries, HASH_WAITOK)); 152f8ce3dfaSSepherosa Ziehau } 153