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