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 $ 40 * $DragonFly: src/sys/kern/kern_subr.c,v 1.9 2003/07/28 04:56:35 hmp Exp $ 41 */ 42 43 #include "opt_ddb.h" 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/kernel.h> 48 #include <sys/proc.h> 49 #include <sys/malloc.h> 50 #include <sys/lock.h> 51 #include <sys/resourcevar.h> 52 #include <sys/vnode.h> 53 54 #include <ddb/ddb.h> 55 56 #include <vm/vm.h> 57 #include <vm/vm_page.h> 58 #include <vm/vm_map.h> 59 60 int 61 uiomove(cp, n, uio) 62 caddr_t cp; 63 int n; 64 struct uio *uio; 65 { 66 struct iovec *iov; 67 u_int cnt; 68 int error = 0; 69 int save = 0; 70 int baseticks = ticks; 71 72 KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, 73 ("uiomove: mode")); 74 KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, 75 ("uiomove proc")); 76 77 if (curproc) { 78 save = curproc->p_flag & P_DEADLKTREAT; 79 curproc->p_flag |= P_DEADLKTREAT; 80 } 81 82 while (n > 0 && uio->uio_resid) { 83 iov = uio->uio_iov; 84 cnt = iov->iov_len; 85 if (cnt == 0) { 86 uio->uio_iov++; 87 uio->uio_iovcnt--; 88 continue; 89 } 90 if (cnt > n) 91 cnt = n; 92 93 switch (uio->uio_segflg) { 94 95 case UIO_USERSPACE: 96 case UIO_USERISPACE: 97 if (ticks - baseticks >= hogticks) { 98 uio_yield(); 99 baseticks = ticks; 100 } 101 if (uio->uio_rw == UIO_READ) 102 error = copyout(cp, iov->iov_base, cnt); 103 else 104 error = copyin(iov->iov_base, cp, cnt); 105 if (error) 106 break; 107 break; 108 109 case UIO_SYSSPACE: 110 if (uio->uio_rw == UIO_READ) 111 bcopy((caddr_t)cp, iov->iov_base, cnt); 112 else 113 bcopy(iov->iov_base, (caddr_t)cp, cnt); 114 break; 115 case UIO_NOCOPY: 116 break; 117 } 118 iov->iov_base += cnt; 119 iov->iov_len -= cnt; 120 uio->uio_resid -= cnt; 121 uio->uio_offset += cnt; 122 cp += cnt; 123 n -= cnt; 124 } 125 if (curproc) 126 curproc->p_flag = (curproc->p_flag & ~P_DEADLKTREAT) | save; 127 return (error); 128 } 129 130 int 131 uiomoveco(cp, n, uio, obj) 132 caddr_t cp; 133 int n; 134 struct uio *uio; 135 struct vm_object *obj; 136 { 137 struct iovec *iov; 138 u_int cnt; 139 int error; 140 int baseticks = ticks; 141 142 KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, 143 ("uiomoveco: mode")); 144 KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, 145 ("uiomoveco proc")); 146 147 while (n > 0 && uio->uio_resid) { 148 iov = uio->uio_iov; 149 cnt = iov->iov_len; 150 if (cnt == 0) { 151 uio->uio_iov++; 152 uio->uio_iovcnt--; 153 continue; 154 } 155 if (cnt > n) 156 cnt = n; 157 158 switch (uio->uio_segflg) { 159 160 case UIO_USERSPACE: 161 case UIO_USERISPACE: 162 if (ticks - baseticks >= hogticks) { 163 uio_yield(); 164 baseticks = ticks; 165 } 166 if (uio->uio_rw == UIO_READ) { 167 #ifdef ENABLE_VFS_IOOPT 168 if (vfs_ioopt && ((cnt & PAGE_MASK) == 0) && 169 ((((intptr_t) iov->iov_base) & PAGE_MASK) == 0) && 170 ((uio->uio_offset & PAGE_MASK) == 0) && 171 ((((intptr_t) cp) & PAGE_MASK) == 0)) { 172 error = vm_uiomove(&curproc->p_vmspace->vm_map, obj, 173 uio->uio_offset, cnt, 174 (vm_offset_t) iov->iov_base, NULL); 175 } else 176 #endif 177 { 178 error = copyout(cp, iov->iov_base, cnt); 179 } 180 } else { 181 error = copyin(iov->iov_base, cp, cnt); 182 } 183 if (error) 184 return (error); 185 break; 186 187 case UIO_SYSSPACE: 188 if (uio->uio_rw == UIO_READ) 189 bcopy((caddr_t)cp, iov->iov_base, cnt); 190 else 191 bcopy(iov->iov_base, (caddr_t)cp, cnt); 192 break; 193 case UIO_NOCOPY: 194 break; 195 } 196 iov->iov_base += cnt; 197 iov->iov_len -= cnt; 198 uio->uio_resid -= cnt; 199 uio->uio_offset += cnt; 200 cp += cnt; 201 n -= cnt; 202 } 203 return (0); 204 } 205 206 #ifdef ENABLE_VFS_IOOPT 207 208 int 209 uioread(n, uio, obj, nread) 210 int n; 211 struct uio *uio; 212 struct vm_object *obj; 213 int *nread; 214 { 215 int npagesmoved; 216 struct iovec *iov; 217 u_int cnt, tcnt; 218 int error; 219 int baseticks = ticks; 220 221 *nread = 0; 222 if (vfs_ioopt < 2) 223 return 0; 224 225 error = 0; 226 227 while (n > 0 && uio->uio_resid) { 228 iov = uio->uio_iov; 229 cnt = iov->iov_len; 230 if (cnt == 0) { 231 uio->uio_iov++; 232 uio->uio_iovcnt--; 233 continue; 234 } 235 if (cnt > n) 236 cnt = n; 237 238 if ((uio->uio_segflg == UIO_USERSPACE) && 239 ((((intptr_t) iov->iov_base) & PAGE_MASK) == 0) && 240 ((uio->uio_offset & PAGE_MASK) == 0) ) { 241 242 if (cnt < PAGE_SIZE) 243 break; 244 245 cnt &= ~PAGE_MASK; 246 247 if (ticks - baseticks >= hogticks) { 248 uio_yield(); 249 baseticks = ticks; 250 } 251 error = vm_uiomove(&curproc->p_vmspace->vm_map, obj, 252 uio->uio_offset, cnt, 253 (vm_offset_t) iov->iov_base, &npagesmoved); 254 255 if (npagesmoved == 0) 256 break; 257 258 tcnt = npagesmoved * PAGE_SIZE; 259 cnt = tcnt; 260 261 if (error) 262 break; 263 264 iov->iov_base += cnt; 265 iov->iov_len -= cnt; 266 uio->uio_resid -= cnt; 267 uio->uio_offset += cnt; 268 *nread += cnt; 269 n -= cnt; 270 } else { 271 break; 272 } 273 } 274 return error; 275 } 276 277 #endif 278 279 /* 280 * Give next character to user as result of read. 281 */ 282 int 283 ureadc(c, uio) 284 int c; 285 struct uio *uio; 286 { 287 struct iovec *iov; 288 289 again: 290 if (uio->uio_iovcnt == 0 || uio->uio_resid == 0) 291 panic("ureadc"); 292 iov = uio->uio_iov; 293 if (iov->iov_len == 0) { 294 uio->uio_iovcnt--; 295 uio->uio_iov++; 296 goto again; 297 } 298 switch (uio->uio_segflg) { 299 300 case UIO_USERSPACE: 301 if (subyte(iov->iov_base, c) < 0) 302 return (EFAULT); 303 break; 304 305 case UIO_SYSSPACE: 306 *iov->iov_base = c; 307 break; 308 309 case UIO_USERISPACE: 310 if (suibyte(iov->iov_base, c) < 0) 311 return (EFAULT); 312 break; 313 case UIO_NOCOPY: 314 break; 315 } 316 iov->iov_base++; 317 iov->iov_len--; 318 uio->uio_resid--; 319 uio->uio_offset++; 320 return (0); 321 } 322 323 #ifdef vax /* unused except by ct.c, other oddities XXX */ 324 /* 325 * Get next character written in by user from uio. 326 */ 327 int 328 uwritec(uio) 329 struct uio *uio; 330 { 331 struct iovec *iov; 332 int c; 333 334 if (uio->uio_resid <= 0) 335 return (-1); 336 again: 337 if (uio->uio_iovcnt <= 0) 338 panic("uwritec"); 339 iov = uio->uio_iov; 340 if (iov->iov_len == 0) { 341 uio->uio_iov++; 342 if (--uio->uio_iovcnt == 0) 343 return (-1); 344 goto again; 345 } 346 switch (uio->uio_segflg) { 347 348 case UIO_USERSPACE: 349 c = fubyte(iov->iov_base); 350 break; 351 352 case UIO_SYSSPACE: 353 c = *(u_char *) iov->iov_base; 354 break; 355 356 case UIO_USERISPACE: 357 c = fuibyte(iov->iov_base); 358 break; 359 } 360 if (c < 0) 361 return (-1); 362 iov->iov_base++; 363 iov->iov_len--; 364 uio->uio_resid--; 365 uio->uio_offset++; 366 return (c); 367 } 368 #endif /* vax */ 369 370 /* 371 * General routine to allocate a hash table. 372 */ 373 void * 374 hashinit(elements, type, hashmask) 375 int elements; 376 struct malloc_type *type; 377 u_long *hashmask; 378 { 379 long hashsize; 380 LIST_HEAD(generic, generic) *hashtbl; 381 int i; 382 383 if (elements <= 0) 384 panic("hashinit: bad elements"); 385 for (hashsize = 1; hashsize <= elements; hashsize <<= 1) 386 continue; 387 hashsize >>= 1; 388 hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK); 389 for (i = 0; i < hashsize; i++) 390 LIST_INIT(&hashtbl[i]); 391 *hashmask = hashsize - 1; 392 return (hashtbl); 393 } 394 395 static int primes[] = { 1, 13, 31, 61, 127, 251, 509, 761, 1021, 1531, 2039, 396 2557, 3067, 3583, 4093, 4603, 5119, 5623, 6143, 6653, 397 7159, 7673, 8191, 12281, 16381, 24571, 32749 }; 398 #define NPRIMES (sizeof(primes) / sizeof(primes[0])) 399 400 /* 401 * General routine to allocate a prime number sized hash table. 402 */ 403 void * 404 phashinit(elements, type, nentries) 405 int elements; 406 struct malloc_type *type; 407 u_long *nentries; 408 { 409 long hashsize; 410 LIST_HEAD(generic, generic) *hashtbl; 411 int i; 412 413 if (elements <= 0) 414 panic("phashinit: bad elements"); 415 for (i = 1, hashsize = primes[1]; hashsize <= elements;) { 416 i++; 417 if (i == NPRIMES) 418 break; 419 hashsize = primes[i]; 420 } 421 hashsize = primes[i - 1]; 422 hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK); 423 for (i = 0; i < hashsize; i++) 424 LIST_INIT(&hashtbl[i]); 425 *nentries = hashsize; 426 return (hashtbl); 427 } 428 429 /* 430 * Simple DDB stack trace funtionality. 431 */ 432 void 433 backtrace(void) 434 { 435 436 #ifdef DDB 437 printf("Stack backtrace:\n"); 438 db_print_backtrace(); 439 #else 440 printf("Cannot print stack trace.\n"); 441 printf("DDB kernel option is needed.\n"); 442 #endif 443 } 444