subr_hash.c revision 1549
1224090Sdougb/* 2254897Serwin * Copyright (c) 1982, 1986, 1991, 1993 3224090Sdougb * The Regents of the University of California. All rights reserved. 4224090Sdougb * (c) UNIX System Laboratories, Inc. 5224090Sdougb * All or some portions of this file are derived from material licensed 6224090Sdougb * to the University of California by American Telephone and Telegraph 7224090Sdougb * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8224090Sdougb * the permission of UNIX System Laboratories, Inc. 9224090Sdougb * 10224090Sdougb * Redistribution and use in source and binary forms, with or without 11224090Sdougb * modification, are permitted provided that the following conditions 12224090Sdougb * are met: 13224090Sdougb * 1. Redistributions of source code must retain the above copyright 14224090Sdougb * notice, this list of conditions and the following disclaimer. 15224090Sdougb * 2. Redistributions in binary form must reproduce the above copyright 16224090Sdougb * notice, this list of conditions and the following disclaimer in the 17254897Serwin * documentation and/or other materials provided with the distribution. 18224090Sdougb * 3. All advertising materials mentioning features or use of this software 19224090Sdougb * must display the following acknowledgement: 20224090Sdougb * This product includes software developed by the University of 21224090Sdougb * California, Berkeley and its contributors. 22224090Sdougb * 4. Neither the name of the University nor the names of its contributors 23224090Sdougb * may be used to endorse or promote products derived from this software 24224090Sdougb * without specific prior written permission. 25224090Sdougb * 26224090Sdougb * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27224090Sdougb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28224090Sdougb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29224090Sdougb * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30224090Sdougb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31224090Sdougb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32224090Sdougb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33224090Sdougb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34224090Sdougb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35224090Sdougb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36224090Sdougb * SUCH DAMAGE. 37224090Sdougb * 38224090Sdougb * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 39224090Sdougb */ 40224090Sdougb 41224090Sdougb#include <sys/param.h> 42224090Sdougb#include <sys/systm.h> 43224090Sdougb#include <sys/proc.h> 44224090Sdougb#include <sys/malloc.h> 45224090Sdougb#include <sys/queue.h> 46224090Sdougb 47224090Sdougbint 48224090Sdougbuiomove(cp, n, uio) 49224090Sdougb register caddr_t cp; 50224090Sdougb register int n; 51224090Sdougb register struct uio *uio; 52224090Sdougb{ 53224090Sdougb register struct iovec *iov; 54224090Sdougb u_int cnt; 55224090Sdougb int error = 0; 56224090Sdougb 57224090Sdougb#ifdef DIAGNOSTIC 58224090Sdougb if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE) 59224090Sdougb panic("uiomove: mode"); 60224090Sdougb if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) 61224090Sdougb panic("uiomove proc"); 62224090Sdougb#endif 63224090Sdougb while (n > 0 && uio->uio_resid) { 64224090Sdougb iov = uio->uio_iov; 65224090Sdougb cnt = iov->iov_len; 66224090Sdougb if (cnt == 0) { 67224090Sdougb uio->uio_iov++; 68224090Sdougb uio->uio_iovcnt--; 69224090Sdougb continue; 70224090Sdougb } 71224090Sdougb if (cnt > n) 72224090Sdougb cnt = n; 73224090Sdougb switch (uio->uio_segflg) { 74224090Sdougb 75224090Sdougb case UIO_USERSPACE: 76224090Sdougb case UIO_USERISPACE: 77224090Sdougb if (uio->uio_rw == UIO_READ) 78224090Sdougb error = copyout(cp, iov->iov_base, cnt); 79224090Sdougb else 80234010Sdougb error = copyin(iov->iov_base, cp, cnt); 81234010Sdougb if (error) 82234010Sdougb return (error); 83234010Sdougb break; 84234010Sdougb 85234010Sdougb case UIO_SYSSPACE: 86234010Sdougb if (uio->uio_rw == UIO_READ) 87234010Sdougb bcopy((caddr_t)cp, iov->iov_base, cnt); 88234010Sdougb else 89234010Sdougb bcopy(iov->iov_base, (caddr_t)cp, cnt); 90234010Sdougb break; 91234010Sdougb } 92234010Sdougb iov->iov_base += cnt; 93224090Sdougb iov->iov_len -= cnt; 94224090Sdougb uio->uio_resid -= cnt; 95224090Sdougb uio->uio_offset += cnt; 96234010Sdougb cp += cnt; 97234010Sdougb n -= cnt; 98234010Sdougb } 99234010Sdougb return (error); 100234010Sdougb} 101234010Sdougb 102234010Sdougb/* 103234010Sdougb * Give next character to user as result of read. 104234010Sdougb */ 105234010Sdougbint 106224090Sdougbureadc(c, uio) 107224090Sdougb register int c; 108224090Sdougb register struct uio *uio; 109234010Sdougb{ 110234010Sdougb register struct iovec *iov; 111234010Sdougb 112234010Sdougbagain: 113234010Sdougb if (uio->uio_iovcnt == 0 || uio->uio_resid == 0) 114234010Sdougb panic("ureadc"); 115234010Sdougb iov = uio->uio_iov; 116234010Sdougb if (iov->iov_len == 0) { 117234010Sdougb uio->uio_iovcnt--; 118234010Sdougb uio->uio_iov++; 119234010Sdougb goto again; 120234010Sdougb } 121224090Sdougb switch (uio->uio_segflg) { 122224090Sdougb 123224090Sdougb case UIO_USERSPACE: 124234010Sdougb if (subyte(iov->iov_base, c) < 0) 125234010Sdougb return (EFAULT); 126234010Sdougb break; 127234010Sdougb 128234010Sdougb case UIO_SYSSPACE: 129234010Sdougb *iov->iov_base = c; 130234010Sdougb break; 131234010Sdougb 132234010Sdougb case UIO_USERISPACE: 133234010Sdougb if (suibyte(iov->iov_base, c) < 0) 134234010Sdougb return (EFAULT); 135234010Sdougb break; 136224090Sdougb } 137224090Sdougb iov->iov_base++; 138224090Sdougb iov->iov_len--; 139224090Sdougb uio->uio_resid--; 140224090Sdougb uio->uio_offset++; 141234010Sdougb return (0); 142234010Sdougb} 143234010Sdougb 144234010Sdougb#ifdef vax /* unused except by ct.c, other oddities XXX */ 145234010Sdougb/* 146234010Sdougb * Get next character written in by user from uio. 147234010Sdougb */ 148234010Sdougbint 149234010Sdougbuwritec(uio) 150234010Sdougb struct uio *uio; 151234010Sdougb{ 152234010Sdougb register struct iovec *iov; 153234010Sdougb register int c; 154234010Sdougb 155224090Sdougb if (uio->uio_resid <= 0) 156224090Sdougb return (-1); 157224090Sdougbagain: 158234010Sdougb if (uio->uio_iovcnt <= 0) 159234010Sdougb panic("uwritec"); 160234010Sdougb iov = uio->uio_iov; 161234010Sdougb if (iov->iov_len == 0) { 162234010Sdougb uio->uio_iov++; 163234010Sdougb if (--uio->uio_iovcnt == 0) 164234010Sdougb return (-1); 165234010Sdougb goto again; 166234010Sdougb } 167234010Sdougb switch (uio->uio_segflg) { 168234010Sdougb 169234010Sdougb case UIO_USERSPACE: 170224090Sdougb c = fubyte(iov->iov_base); 171224090Sdougb break; 172224090Sdougb 173234010Sdougb case UIO_SYSSPACE: 174234010Sdougb c = *(u_char *) iov->iov_base; 175234010Sdougb break; 176234010Sdougb 177234010Sdougb case UIO_USERISPACE: 178234010Sdougb c = fuibyte(iov->iov_base); 179234010Sdougb break; 180234010Sdougb } 181234010Sdougb if (c < 0) 182234010Sdougb return (-1); 183234010Sdougb iov->iov_base++; 184224090Sdougb iov->iov_len--; 185224090Sdougb uio->uio_resid--; 186224090Sdougb uio->uio_offset++; 187224090Sdougb return (c); 188} 189#endif /* vax */ 190 191/* 192 * General routine to allocate a hash table. 193 */ 194void * 195hashinit(elements, type, hashmask) 196 int elements, type; 197 u_long *hashmask; 198{ 199 long hashsize; 200 LIST_HEAD(generic, generic) *hashtbl; 201 int i; 202 203 if (elements <= 0) 204 panic("hashinit: bad cnt"); 205 for (hashsize = 1; hashsize <= elements; hashsize <<= 1) 206 continue; 207 hashsize >>= 1; 208 hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK); 209 for (i = 0; i < hashsize; i++) 210 LIST_INIT(&hashtbl[i]); 211 *hashmask = hashsize - 1; 212 return (hashtbl); 213} 214