Register keyword removal
[dragonfly.git] / sys / kern / kern_subr.c
CommitLineData
984263bc
MD
1/*
2 * Copyright (c) 1982, 1986, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94
39 * $FreeBSD: src/sys/kern/kern_subr.c,v 1.31.2.2 2002/04/21 08:09:37 bde Exp $
1fd87d54 40 * $DragonFly: src/sys/kern/kern_subr.c,v 1.8 2003/07/26 19:42:11 rob Exp $
984263bc
MD
41 */
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/kernel.h>
46#include <sys/proc.h>
47#include <sys/malloc.h>
48#include <sys/lock.h>
49#include <sys/resourcevar.h>
50#include <sys/vnode.h>
51
52#include <vm/vm.h>
53#include <vm/vm_page.h>
54#include <vm/vm_map.h>
55
56int
57uiomove(cp, n, uio)
1fd87d54
RG
58 caddr_t cp;
59 int n;
60 struct uio *uio;
984263bc 61{
1fd87d54 62 struct iovec *iov;
984263bc
MD
63 u_int cnt;
64 int error = 0;
65 int save = 0;
d16a8831 66 int baseticks = ticks;
984263bc
MD
67
68 KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE,
69 ("uiomove: mode"));
dadab5e9 70 KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread,
984263bc
MD
71 ("uiomove proc"));
72
73 if (curproc) {
74 save = curproc->p_flag & P_DEADLKTREAT;
75 curproc->p_flag |= P_DEADLKTREAT;
76 }
77
78 while (n > 0 && uio->uio_resid) {
79 iov = uio->uio_iov;
80 cnt = iov->iov_len;
81 if (cnt == 0) {
82 uio->uio_iov++;
83 uio->uio_iovcnt--;
84 continue;
85 }
86 if (cnt > n)
87 cnt = n;
88
89 switch (uio->uio_segflg) {
90
91 case UIO_USERSPACE:
92 case UIO_USERISPACE:
d16a8831 93 if (ticks - baseticks >= hogticks) {
984263bc 94 uio_yield();
d16a8831
MD
95 baseticks = ticks;
96 }
984263bc
MD
97 if (uio->uio_rw == UIO_READ)
98 error = copyout(cp, iov->iov_base, cnt);
99 else
100 error = copyin(iov->iov_base, cp, cnt);
101 if (error)
102 break;
103 break;
104
105 case UIO_SYSSPACE:
106 if (uio->uio_rw == UIO_READ)
107 bcopy((caddr_t)cp, iov->iov_base, cnt);
108 else
109 bcopy(iov->iov_base, (caddr_t)cp, cnt);
110 break;
111 case UIO_NOCOPY:
112 break;
113 }
114 iov->iov_base += cnt;
115 iov->iov_len -= cnt;
116 uio->uio_resid -= cnt;
117 uio->uio_offset += cnt;
118 cp += cnt;
119 n -= cnt;
120 }
121 if (curproc)
122 curproc->p_flag = (curproc->p_flag & ~P_DEADLKTREAT) | save;
123 return (error);
124}
125
126int
127uiomoveco(cp, n, uio, obj)
128 caddr_t cp;
129 int n;
130 struct uio *uio;
131 struct vm_object *obj;
132{
133 struct iovec *iov;
134 u_int cnt;
135 int error;
d16a8831 136 int baseticks = ticks;
984263bc
MD
137
138 KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE,
139 ("uiomoveco: mode"));
dadab5e9 140 KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread,
984263bc
MD
141 ("uiomoveco proc"));
142
143 while (n > 0 && uio->uio_resid) {
144 iov = uio->uio_iov;
145 cnt = iov->iov_len;
146 if (cnt == 0) {
147 uio->uio_iov++;
148 uio->uio_iovcnt--;
149 continue;
150 }
151 if (cnt > n)
152 cnt = n;
153
154 switch (uio->uio_segflg) {
155
156 case UIO_USERSPACE:
157 case UIO_USERISPACE:
d16a8831 158 if (ticks - baseticks >= hogticks) {
984263bc 159 uio_yield();
d16a8831
MD
160 baseticks = ticks;
161 }
984263bc
MD
162 if (uio->uio_rw == UIO_READ) {
163#ifdef ENABLE_VFS_IOOPT
164 if (vfs_ioopt && ((cnt & PAGE_MASK) == 0) &&
165 ((((intptr_t) iov->iov_base) & PAGE_MASK) == 0) &&
166 ((uio->uio_offset & PAGE_MASK) == 0) &&
167 ((((intptr_t) cp) & PAGE_MASK) == 0)) {
168 error = vm_uiomove(&curproc->p_vmspace->vm_map, obj,
169 uio->uio_offset, cnt,
170 (vm_offset_t) iov->iov_base, NULL);
171 } else
172#endif
173 {
174 error = copyout(cp, iov->iov_base, cnt);
175 }
176 } else {
177 error = copyin(iov->iov_base, cp, cnt);
178 }
179 if (error)
180 return (error);
181 break;
182
183 case UIO_SYSSPACE:
184 if (uio->uio_rw == UIO_READ)
185 bcopy((caddr_t)cp, iov->iov_base, cnt);
186 else
187 bcopy(iov->iov_base, (caddr_t)cp, cnt);
188 break;
189 case UIO_NOCOPY:
190 break;
191 }
192 iov->iov_base += cnt;
193 iov->iov_len -= cnt;
194 uio->uio_resid -= cnt;
195 uio->uio_offset += cnt;
196 cp += cnt;
197 n -= cnt;
198 }
199 return (0);
200}
201
202#ifdef ENABLE_VFS_IOOPT
203
204int
205uioread(n, uio, obj, nread)
206 int n;
207 struct uio *uio;
208 struct vm_object *obj;
209 int *nread;
210{
211 int npagesmoved;
212 struct iovec *iov;
213 u_int cnt, tcnt;
214 int error;
7b95be2a 215 int baseticks = ticks;
984263bc
MD
216
217 *nread = 0;
218 if (vfs_ioopt < 2)
219 return 0;
220
221 error = 0;
222
223 while (n > 0 && uio->uio_resid) {
224 iov = uio->uio_iov;
225 cnt = iov->iov_len;
226 if (cnt == 0) {
227 uio->uio_iov++;
228 uio->uio_iovcnt--;
229 continue;
230 }
231 if (cnt > n)
232 cnt = n;
233
234 if ((uio->uio_segflg == UIO_USERSPACE) &&
235 ((((intptr_t) iov->iov_base) & PAGE_MASK) == 0) &&
236 ((uio->uio_offset & PAGE_MASK) == 0) ) {
237
238 if (cnt < PAGE_SIZE)
239 break;
240
241 cnt &= ~PAGE_MASK;
242
7b95be2a 243 if (ticks - baseticks >= hogticks) {
984263bc 244 uio_yield();
7b95be2a
MD
245 baseticks = ticks;
246 }
984263bc
MD
247 error = vm_uiomove(&curproc->p_vmspace->vm_map, obj,
248 uio->uio_offset, cnt,
249 (vm_offset_t) iov->iov_base, &npagesmoved);
250
251 if (npagesmoved == 0)
252 break;
253
254 tcnt = npagesmoved * PAGE_SIZE;
255 cnt = tcnt;
256
257 if (error)
258 break;
259
260 iov->iov_base += cnt;
261 iov->iov_len -= cnt;
262 uio->uio_resid -= cnt;
263 uio->uio_offset += cnt;
264 *nread += cnt;
265 n -= cnt;
266 } else {
267 break;
268 }
269 }
270 return error;
271}
272
273#endif
274
275/*
276 * Give next character to user as result of read.
277 */
278int
279ureadc(c, uio)
1fd87d54
RG
280 int c;
281 struct uio *uio;
984263bc 282{
1fd87d54 283 struct iovec *iov;
984263bc
MD
284
285again:
286 if (uio->uio_iovcnt == 0 || uio->uio_resid == 0)
287 panic("ureadc");
288 iov = uio->uio_iov;
289 if (iov->iov_len == 0) {
290 uio->uio_iovcnt--;
291 uio->uio_iov++;
292 goto again;
293 }
294 switch (uio->uio_segflg) {
295
296 case UIO_USERSPACE:
297 if (subyte(iov->iov_base, c) < 0)
298 return (EFAULT);
299 break;
300
301 case UIO_SYSSPACE:
302 *iov->iov_base = c;
303 break;
304
305 case UIO_USERISPACE:
306 if (suibyte(iov->iov_base, c) < 0)
307 return (EFAULT);
308 break;
309 case UIO_NOCOPY:
310 break;
311 }
312 iov->iov_base++;
313 iov->iov_len--;
314 uio->uio_resid--;
315 uio->uio_offset++;
316 return (0);
317}
318
319#ifdef vax /* unused except by ct.c, other oddities XXX */
320/*
321 * Get next character written in by user from uio.
322 */
323int
324uwritec(uio)
325 struct uio *uio;
326{
1fd87d54
RG
327 struct iovec *iov;
328 int c;
984263bc
MD
329
330 if (uio->uio_resid <= 0)
331 return (-1);
332again:
333 if (uio->uio_iovcnt <= 0)
334 panic("uwritec");
335 iov = uio->uio_iov;
336 if (iov->iov_len == 0) {
337 uio->uio_iov++;
338 if (--uio->uio_iovcnt == 0)
339 return (-1);
340 goto again;
341 }
342 switch (uio->uio_segflg) {
343
344 case UIO_USERSPACE:
345 c = fubyte(iov->iov_base);
346 break;
347
348 case UIO_SYSSPACE:
349 c = *(u_char *) iov->iov_base;
350 break;
351
352 case UIO_USERISPACE:
353 c = fuibyte(iov->iov_base);
354 break;
355 }
356 if (c < 0)
357 return (-1);
358 iov->iov_base++;
359 iov->iov_len--;
360 uio->uio_resid--;
361 uio->uio_offset++;
362 return (c);
363}
364#endif /* vax */
365
366/*
367 * General routine to allocate a hash table.
368 */
369void *
370hashinit(elements, type, hashmask)
371 int elements;
372 struct malloc_type *type;
373 u_long *hashmask;
374{
375 long hashsize;
376 LIST_HEAD(generic, generic) *hashtbl;
377 int i;
378
379 if (elements <= 0)
380 panic("hashinit: bad elements");
381 for (hashsize = 1; hashsize <= elements; hashsize <<= 1)
382 continue;
383 hashsize >>= 1;
384 hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK);
385 for (i = 0; i < hashsize; i++)
386 LIST_INIT(&hashtbl[i]);
387 *hashmask = hashsize - 1;
388 return (hashtbl);
389}
390
391static int primes[] = { 1, 13, 31, 61, 127, 251, 509, 761, 1021, 1531, 2039,
392 2557, 3067, 3583, 4093, 4603, 5119, 5623, 6143, 6653,
393 7159, 7673, 8191, 12281, 16381, 24571, 32749 };
394#define NPRIMES (sizeof(primes) / sizeof(primes[0]))
395
396/*
397 * General routine to allocate a prime number sized hash table.
398 */
399void *
400phashinit(elements, type, nentries)
401 int elements;
402 struct malloc_type *type;
403 u_long *nentries;
404{
405 long hashsize;
406 LIST_HEAD(generic, generic) *hashtbl;
407 int i;
408
409 if (elements <= 0)
410 panic("phashinit: bad elements");
411 for (i = 1, hashsize = primes[1]; hashsize <= elements;) {
412 i++;
413 if (i == NPRIMES)
414 break;
415 hashsize = primes[i];
416 }
417 hashsize = primes[i - 1];
418 hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK);
419 for (i = 0; i < hashsize; i++)
420 LIST_INIT(&hashtbl[i]);
421 *nentries = hashsize;
422 return (hashtbl);
423}
424