[BACK]Return to kern_subr.c CVS log [TXT][DIR] Up to [local] / sys / kern

Annotation of sys/kern/kern_subr.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: kern_subr.c,v 1.31 2007/05/16 17:27:30 art Exp $      */
                      2: /*     $NetBSD: kern_subr.c,v 1.15 1996/04/09 17:21:56 ragge Exp $     */
                      3:
                      4: /*
                      5:  * Copyright (c) 1982, 1986, 1991, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  * (c) UNIX System Laboratories, Inc.
                      8:  * All or some portions of this file are derived from material licensed
                      9:  * to the University of California by American Telephone and Telegraph
                     10:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                     11:  * the permission of UNIX System Laboratories, Inc.
                     12:  *
                     13:  * Redistribution and use in source and binary forms, with or without
                     14:  * modification, are permitted provided that the following conditions
                     15:  * are met:
                     16:  * 1. Redistributions of source code must retain the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer.
                     18:  * 2. Redistributions in binary form must reproduce the above copyright
                     19:  *    notice, this list of conditions and the following disclaimer in the
                     20:  *    documentation and/or other materials provided with the distribution.
                     21:  * 3. Neither the name of the University nor the names of its contributors
                     22:  *    may be used to endorse or promote products derived from this software
                     23:  *    without specific prior written permission.
                     24:  *
                     25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     35:  * SUCH DAMAGE.
                     36:  *
                     37:  *     @(#)kern_subr.c 8.3 (Berkeley) 1/21/94
                     38:  */
                     39:
                     40: #include <sys/param.h>
                     41: #include <sys/systm.h>
                     42: #include <sys/proc.h>
                     43: #include <sys/sched.h>
                     44: #include <sys/malloc.h>
                     45: #include <sys/queue.h>
                     46: #include <sys/kernel.h>
                     47: #include <sys/resourcevar.h>
                     48:
                     49: int
                     50: uiomove(void *cp, int n, struct uio *uio)
                     51: {
                     52:        struct iovec *iov;
                     53:        u_int cnt;
                     54:        int error = 0;
                     55:        struct proc *p;
                     56:
                     57:        p = uio->uio_procp;
                     58:
                     59: #ifdef DIAGNOSTIC
                     60:        if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE)
                     61:                panic("uiomove: mode");
                     62:        if (uio->uio_segflg == UIO_USERSPACE && p != curproc)
                     63:                panic("uiomove: proc");
                     64: #endif
                     65:        while (n > 0 && uio->uio_resid) {
                     66:                iov = uio->uio_iov;
                     67:                cnt = iov->iov_len;
                     68:                if (cnt == 0) {
                     69:                        uio->uio_iov++;
                     70:                        uio->uio_iovcnt--;
                     71:                        continue;
                     72:                }
                     73:                if (cnt > n)
                     74:                        cnt = n;
                     75:                switch (uio->uio_segflg) {
                     76:
                     77:                case UIO_USERSPACE:
                     78:                        if (curcpu()->ci_schedstate.spc_schedflags &
                     79:                            SPCF_SHOULDYIELD)
                     80:                                preempt(NULL);
                     81:                        if (uio->uio_rw == UIO_READ)
                     82:                                error = copyout(cp, iov->iov_base, cnt);
                     83:                        else
                     84:                                error = copyin(iov->iov_base, cp, cnt);
                     85:                        if (error)
                     86:                                return (error);
                     87:                        break;
                     88:
                     89:                case UIO_SYSSPACE:
                     90:                        if (uio->uio_rw == UIO_READ)
                     91:                                error = kcopy(cp, iov->iov_base, cnt);
                     92:                        else
                     93:                                error = kcopy(iov->iov_base, cp, cnt);
                     94:                        if (error)
                     95:                                return(error);
                     96:                }
                     97:                iov->iov_base = (caddr_t)iov->iov_base + cnt;
                     98:                iov->iov_len -= cnt;
                     99:                uio->uio_resid -= cnt;
                    100:                uio->uio_offset += cnt;
                    101:                cp = (caddr_t)cp + cnt;
                    102:                n -= cnt;
                    103:        }
                    104:        return (error);
                    105: }
                    106:
                    107: /*
                    108:  * Give next character to user as result of read.
                    109:  */
                    110: int
                    111: ureadc(int c, struct uio *uio)
                    112: {
                    113:        struct iovec *iov;
                    114:
                    115:        if (uio->uio_resid == 0)
                    116: #ifdef DIAGNOSTIC
                    117:                panic("ureadc: zero resid");
                    118: #else
                    119:                return (EINVAL);
                    120: #endif
                    121: again:
                    122:        if (uio->uio_iovcnt <= 0)
                    123: #ifdef DIAGNOSTIC
                    124:                panic("ureadc: non-positive iovcnt");
                    125: #else
                    126:                return (EINVAL);
                    127: #endif
                    128:        iov = uio->uio_iov;
                    129:        if (iov->iov_len <= 0) {
                    130:                uio->uio_iovcnt--;
                    131:                uio->uio_iov++;
                    132:                goto again;
                    133:        }
                    134:        switch (uio->uio_segflg) {
                    135:
                    136:        case UIO_USERSPACE:
                    137:        {
                    138:                char tmp = c;
                    139:
                    140:                if (copyout(&tmp, iov->iov_base, sizeof(char)) != 0)
                    141:                        return (EFAULT);
                    142:        }
                    143:                break;
                    144:
                    145:        case UIO_SYSSPACE:
                    146:                *(char *)iov->iov_base = c;
                    147:                break;
                    148:        }
                    149:        iov->iov_base = (caddr_t)iov->iov_base + 1;
                    150:        iov->iov_len--;
                    151:        uio->uio_resid--;
                    152:        uio->uio_offset++;
                    153:        return (0);
                    154: }
                    155:
                    156: /*
                    157:  * General routine to allocate a hash table.
                    158:  */
                    159: void *
                    160: hashinit(int elements, int type, int flags, u_long *hashmask)
                    161: {
                    162:        u_long hashsize, i;
                    163:        LIST_HEAD(generic, generic) *hashtbl;
                    164:
                    165:        if (elements <= 0)
                    166:                panic("hashinit: bad cnt");
                    167:        for (hashsize = 1; hashsize < elements; hashsize <<= 1)
                    168:                continue;
                    169:        hashtbl = malloc(hashsize * sizeof(*hashtbl), type, flags);
                    170:        if (hashtbl == NULL)
                    171:                return NULL;
                    172:        for (i = 0; i < hashsize; i++)
                    173:                LIST_INIT(&hashtbl[i]);
                    174:        *hashmask = hashsize - 1;
                    175:        return (hashtbl);
                    176: }
                    177:
                    178: /*
                    179:  * "Shutdown/startup hook" types, functions, and variables.
                    180:  */
                    181:
                    182: struct hook_desc_head startuphook_list =
                    183:     TAILQ_HEAD_INITIALIZER(startuphook_list);
                    184: struct hook_desc_head shutdownhook_list =
                    185:     TAILQ_HEAD_INITIALIZER(shutdownhook_list);
                    186: struct hook_desc_head mountroothook_list =
                    187:     TAILQ_HEAD_INITIALIZER(mountroothook_list);
                    188:
                    189: void *
                    190: hook_establish(struct hook_desc_head *head, int tail, void (*fn)(void *),
                    191:     void *arg)
                    192: {
                    193:        struct hook_desc *hdp;
                    194:
                    195:        hdp = (struct hook_desc *)malloc(sizeof (*hdp), M_DEVBUF, M_NOWAIT);
                    196:        if (hdp == NULL)
                    197:                return (NULL);
                    198:
                    199:        hdp->hd_fn = fn;
                    200:        hdp->hd_arg = arg;
                    201:        if (tail)
                    202:                TAILQ_INSERT_TAIL(head, hdp, hd_list);
                    203:        else
                    204:                TAILQ_INSERT_HEAD(head, hdp, hd_list);
                    205:
                    206:        return (hdp);
                    207: }
                    208:
                    209: void
                    210: hook_disestablish(struct hook_desc_head *head, void *vhook)
                    211: {
                    212:        struct hook_desc *hdp;
                    213:
                    214: #ifdef DIAGNOSTIC
                    215:        for (hdp = TAILQ_FIRST(head); hdp != NULL;
                    216:            hdp = TAILQ_NEXT(hdp, hd_list))
                    217:                 if (hdp == vhook)
                    218:                        break;
                    219:        if (hdp == NULL)
                    220:                panic("hook_disestablish: hook not established");
                    221: #endif
                    222:        hdp = vhook;
                    223:        TAILQ_REMOVE(head, hdp, hd_list);
                    224:        free(hdp, M_DEVBUF);
                    225: }
                    226:
                    227: /*
                    228:  * Run hooks.  Startup hooks are invoked right after scheduler_start but
                    229:  * before root is mounted.  Shutdown hooks are invoked immediately before the
                    230:  * system is halted or rebooted, i.e. after file systems unmounted,
                    231:  * after crash dump done, etc.
                    232:  */
                    233: void
                    234: dohooks(struct hook_desc_head *head, int flags)
                    235: {
                    236:        struct hook_desc *hdp;
                    237:
                    238:        if ((flags & HOOK_REMOVE) == 0) {
                    239:                TAILQ_FOREACH(hdp, head, hd_list) {
                    240:                        (*hdp->hd_fn)(hdp->hd_arg);
                    241:                }
                    242:        } else {
                    243:                while ((hdp = TAILQ_FIRST(head)) != NULL) {
                    244:                        TAILQ_REMOVE(head, hdp, hd_list);
                    245:                        (*hdp->hd_fn)(hdp->hd_arg);
                    246:                        if ((flags & HOOK_FREE) != 0)
                    247:                                free(hdp, M_DEVBUF);
                    248:                }
                    249:        }
                    250: }
                    251:
                    252: /*
                    253:  * "Power hook" types, functions, and variables.
                    254:  */
                    255:
                    256: struct powerhook_desc {
                    257:        CIRCLEQ_ENTRY(powerhook_desc) sfd_list;
                    258:        void    (*sfd_fn)(int, void *);
                    259:        void    *sfd_arg;
                    260: };
                    261:
                    262: CIRCLEQ_HEAD(, powerhook_desc) powerhook_list =
                    263:        CIRCLEQ_HEAD_INITIALIZER(powerhook_list);
                    264:
                    265: void *
                    266: powerhook_establish(void (*fn)(int, void *), void *arg)
                    267: {
                    268:        struct powerhook_desc *ndp;
                    269:
                    270:        ndp = (struct powerhook_desc *)
                    271:            malloc(sizeof(*ndp), M_DEVBUF, M_NOWAIT);
                    272:        if (ndp == NULL)
                    273:                return NULL;
                    274:
                    275:        ndp->sfd_fn = fn;
                    276:        ndp->sfd_arg = arg;
                    277:        CIRCLEQ_INSERT_HEAD(&powerhook_list, ndp, sfd_list);
                    278:
                    279:        return (ndp);
                    280: }
                    281:
                    282: void
                    283: powerhook_disestablish(void *vhook)
                    284: {
                    285: #ifdef DIAGNOSTIC
                    286:        struct powerhook_desc *dp;
                    287:
                    288:        CIRCLEQ_FOREACH(dp, &powerhook_list, sfd_list)
                    289:                 if (dp == vhook)
                    290:                        break;
                    291:        if (dp == NULL)
                    292:                panic("powerhook_disestablish: hook not established");
                    293: #endif
                    294:
                    295:        CIRCLEQ_REMOVE(&powerhook_list, (struct powerhook_desc *)vhook,
                    296:                sfd_list);
                    297:        free(vhook, M_DEVBUF);
                    298: }
                    299:
                    300: /*
                    301:  * Run power hooks.
                    302:  */
                    303: void
                    304: dopowerhooks(int why)
                    305: {
                    306:        struct powerhook_desc *dp;
                    307:        int s;
                    308:
                    309:        s = splhigh();
                    310:        if (why == PWR_RESUME) {
                    311:                CIRCLEQ_FOREACH_REVERSE(dp, &powerhook_list, sfd_list) {
                    312:                        (*dp->sfd_fn)(why, dp->sfd_arg);
                    313:                }
                    314:        } else {
                    315:                CIRCLEQ_FOREACH(dp, &powerhook_list, sfd_list) {
                    316:                        (*dp->sfd_fn)(why, dp->sfd_arg);
                    317:                }
                    318:        }
                    319:        splx(s);
                    320: }

CVSweb