123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- /* $OpenBSD: kern_subr.c,v 1.44 2015/03/14 03:38:50 jsg Exp $ */
- /* $NetBSD: kern_subr.c,v 1.15 1996/04/09 17:21:56 ragge Exp $ */
- /*
- * Copyright (c) 1982, 1986, 1991, 1993
- * The Regents of the University of California. All rights reserved.
- * (c) UNIX System Laboratories, Inc.
- * All or some portions of this file are derived from material licensed
- * to the University of California by American Telephone and Telegraph
- * Co. or Unix System Laboratories, Inc. and are reproduced herein with
- * the permission of UNIX System Laboratories, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94
- */
- #include <sys/param.h>
- #include <sys/systm.h>
- #include <sys/proc.h>
- #include <sys/sched.h>
- #include <sys/malloc.h>
- #include <sys/queue.h>
- #include <sys/resourcevar.h>
- int
- uiomove(void *cp, size_t n, struct uio *uio)
- {
- struct iovec *iov;
- size_t cnt;
- int error = 0;
- struct proc *p;
- p = uio->uio_procp;
- #ifdef DIAGNOSTIC
- if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE)
- panic("uiomove: mode");
- if (uio->uio_segflg == UIO_USERSPACE && p != curproc)
- panic("uiomove: proc");
- #endif
- while (n > 0 && uio->uio_resid) {
- iov = uio->uio_iov;
- cnt = iov->iov_len;
- if (cnt == 0) {
- uio->uio_iov++;
- uio->uio_iovcnt--;
- continue;
- }
- if (cnt > n)
- cnt = n;
- switch (uio->uio_segflg) {
- case UIO_USERSPACE:
- if (curcpu()->ci_schedstate.spc_schedflags &
- SPCF_SHOULDYIELD)
- preempt(NULL);
- if (uio->uio_rw == UIO_READ)
- error = copyout(cp, iov->iov_base, cnt);
- else
- error = copyin(iov->iov_base, cp, cnt);
- if (error)
- return (error);
- break;
- case UIO_SYSSPACE:
- if (uio->uio_rw == UIO_READ)
- error = kcopy(cp, iov->iov_base, cnt);
- else
- error = kcopy(iov->iov_base, cp, cnt);
- if (error)
- return(error);
- }
- iov->iov_base = (caddr_t)iov->iov_base + cnt;
- iov->iov_len -= cnt;
- uio->uio_resid -= cnt;
- uio->uio_offset += cnt;
- cp = (caddr_t)cp + cnt;
- n -= cnt;
- }
- return (error);
- }
- int
- uiomovei(void *cp, int n, struct uio *uio)
- {
- if (n < 0)
- return 0;
- return uiomove(cp, (size_t)n, uio);
- }
- /*
- * Give next character to user as result of read.
- */
- int
- ureadc(int c, struct uio *uio)
- {
- struct iovec *iov;
- if (uio->uio_resid == 0)
- #ifdef DIAGNOSTIC
- panic("ureadc: zero resid");
- #else
- return (EINVAL);
- #endif
- again:
- if (uio->uio_iovcnt <= 0)
- #ifdef DIAGNOSTIC
- panic("ureadc: non-positive iovcnt");
- #else
- return (EINVAL);
- #endif
- iov = uio->uio_iov;
- if (iov->iov_len <= 0) {
- uio->uio_iovcnt--;
- uio->uio_iov++;
- goto again;
- }
- switch (uio->uio_segflg) {
- case UIO_USERSPACE:
- {
- char tmp = c;
- if (copyout(&tmp, iov->iov_base, sizeof(char)) != 0)
- return (EFAULT);
- }
- break;
- case UIO_SYSSPACE:
- *(char *)iov->iov_base = c;
- break;
- }
- iov->iov_base = (caddr_t)iov->iov_base + 1;
- iov->iov_len--;
- uio->uio_resid--;
- uio->uio_offset++;
- return (0);
- }
- /*
- * General routine to allocate a hash table.
- */
- void *
- hashinit(int elements, int type, int flags, u_long *hashmask)
- {
- u_long hashsize, i;
- LIST_HEAD(generic, generic) *hashtbl;
- if (elements <= 0)
- panic("hashinit: bad cnt");
- for (hashsize = 1; hashsize < elements; hashsize <<= 1)
- continue;
- hashtbl = mallocarray(hashsize, sizeof(*hashtbl), type, flags);
- if (hashtbl == NULL)
- return NULL;
- for (i = 0; i < hashsize; i++)
- LIST_INIT(&hashtbl[i]);
- *hashmask = hashsize - 1;
- return (hashtbl);
- }
- /*
- * "Mountroot/startup hook" types, functions, and variables.
- */
- struct hook_desc_head startuphook_list =
- TAILQ_HEAD_INITIALIZER(startuphook_list);
- struct hook_desc_head mountroothook_list =
- TAILQ_HEAD_INITIALIZER(mountroothook_list);
- void *
- hook_establish(struct hook_desc_head *head, int tail, void (*fn)(void *),
- void *arg)
- {
- struct hook_desc *hdp;
- hdp = malloc(sizeof(*hdp), M_DEVBUF, M_NOWAIT);
- if (hdp == NULL)
- return (NULL);
- hdp->hd_fn = fn;
- hdp->hd_arg = arg;
- if (tail)
- TAILQ_INSERT_TAIL(head, hdp, hd_list);
- else
- TAILQ_INSERT_HEAD(head, hdp, hd_list);
- return (hdp);
- }
- void
- hook_disestablish(struct hook_desc_head *head, void *vhook)
- {
- struct hook_desc *hdp;
- #ifdef DIAGNOSTIC
- for (hdp = TAILQ_FIRST(head); hdp != NULL;
- hdp = TAILQ_NEXT(hdp, hd_list))
- if (hdp == vhook)
- break;
- if (hdp == NULL)
- return;
- #endif
- hdp = vhook;
- TAILQ_REMOVE(head, hdp, hd_list);
- free(hdp, M_DEVBUF, sizeof(*hdp));
- }
- /*
- * Run hooks. Startup hooks are invoked right after scheduler_start but
- * before root is mounted. Shutdown hooks are invoked immediately before the
- * system is halted or rebooted, i.e. after file systems unmounted,
- * after crash dump done, etc.
- */
- void
- dohooks(struct hook_desc_head *head, int flags)
- {
- struct hook_desc *hdp, *hdp_temp;
- if ((flags & HOOK_REMOVE) == 0) {
- TAILQ_FOREACH_SAFE(hdp, head, hd_list, hdp_temp) {
- (*hdp->hd_fn)(hdp->hd_arg);
- }
- } else {
- while ((hdp = TAILQ_FIRST(head)) != NULL) {
- TAILQ_REMOVE(head, hdp, hd_list);
- (*hdp->hd_fn)(hdp->hd_arg);
- if ((flags & HOOK_FREE) != 0)
- free(hdp, M_DEVBUF, sizeof(*hdp));
- }
- }
- }
|