LCOV - code coverage report
Current view: top level - kern - kern_subr.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 114 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 7 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: kern_subr.c,v 1.50 2018/04/29 17:26:31 anton 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/resourcevar.h>
      47             : 
      48             : int
      49           0 : uiomove(void *cp, size_t n, struct uio *uio)
      50             : {
      51             :         struct iovec *iov;
      52             :         size_t cnt;
      53             :         int error = 0;
      54             : 
      55             : #ifdef DIAGNOSTIC
      56           0 :         if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE)
      57           0 :                 panic("uiomove: mode");
      58           0 :         if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
      59           0 :                 panic("uiomove: proc");
      60             : #endif
      61             : 
      62           0 :         if (n > uio->uio_resid)
      63           0 :                 n = uio->uio_resid;
      64             : 
      65           0 :         while (n > 0) {
      66           0 :                 iov = uio->uio_iov;
      67           0 :                 cnt = iov->iov_len;
      68           0 :                 if (cnt == 0) {
      69           0 :                         KASSERT(uio->uio_iovcnt > 0);
      70           0 :                         uio->uio_iov++;
      71           0 :                         uio->uio_iovcnt--;
      72           0 :                         continue;
      73             :                 }
      74           0 :                 if (cnt > n)
      75           0 :                         cnt = n;
      76           0 :                 switch (uio->uio_segflg) {
      77             : 
      78             :                 case UIO_USERSPACE:
      79           0 :                         sched_pause(preempt);
      80           0 :                         if (uio->uio_rw == UIO_READ)
      81           0 :                                 error = copyout(cp, iov->iov_base, cnt);
      82             :                         else
      83           0 :                                 error = copyin(iov->iov_base, cp, cnt);
      84           0 :                         if (error)
      85           0 :                                 return (error);
      86             :                         break;
      87             : 
      88             :                 case UIO_SYSSPACE:
      89           0 :                         if (uio->uio_rw == UIO_READ)
      90           0 :                                 error = kcopy(cp, iov->iov_base, cnt);
      91             :                         else
      92           0 :                                 error = kcopy(iov->iov_base, cp, cnt);
      93           0 :                         if (error)
      94           0 :                                 return(error);
      95             :                 }
      96           0 :                 iov->iov_base = (caddr_t)iov->iov_base + cnt;
      97           0 :                 iov->iov_len -= cnt;
      98           0 :                 uio->uio_resid -= cnt;
      99           0 :                 uio->uio_offset += cnt;
     100           0 :                 cp = (caddr_t)cp + cnt;
     101           0 :                 n -= cnt;
     102             :         }
     103           0 :         return (error);
     104           0 : }
     105             : 
     106             : /*
     107             :  * Give next character to user as result of read.
     108             :  */
     109             : int
     110           0 : ureadc(int c, struct uio *uio)
     111             : {
     112             :         struct iovec *iov;
     113             : 
     114           0 :         if (uio->uio_resid == 0)
     115             : #ifdef DIAGNOSTIC
     116           0 :                 panic("ureadc: zero resid");
     117             : #else
     118             :                 return (EINVAL);
     119             : #endif
     120             : again:
     121           0 :         if (uio->uio_iovcnt <= 0)
     122             : #ifdef DIAGNOSTIC
     123           0 :                 panic("ureadc: non-positive iovcnt");
     124             : #else
     125             :                 return (EINVAL);
     126             : #endif
     127           0 :         iov = uio->uio_iov;
     128           0 :         if (iov->iov_len <= 0) {
     129           0 :                 uio->uio_iovcnt--;
     130           0 :                 uio->uio_iov++;
     131           0 :                 goto again;
     132             :         }
     133           0 :         switch (uio->uio_segflg) {
     134             : 
     135             :         case UIO_USERSPACE:
     136             :         {
     137           0 :                 char tmp = c;
     138             : 
     139           0 :                 if (copyout(&tmp, iov->iov_base, sizeof(char)) != 0)
     140           0 :                         return (EFAULT);
     141           0 :         }
     142             :                 break;
     143             : 
     144             :         case UIO_SYSSPACE:
     145           0 :                 *(char *)iov->iov_base = c;
     146           0 :                 break;
     147             :         }
     148           0 :         iov->iov_base = (caddr_t)iov->iov_base + 1;
     149           0 :         iov->iov_len--;
     150           0 :         uio->uio_resid--;
     151           0 :         uio->uio_offset++;
     152           0 :         return (0);
     153           0 : }
     154             : 
     155             : /*
     156             :  * General routine to allocate a hash table.
     157             :  */
     158             : void *
     159           0 : hashinit(int elements, int type, int flags, u_long *hashmask)
     160             : {
     161             :         u_long hashsize, i;
     162             :         LIST_HEAD(generic, generic) *hashtbl;
     163             : 
     164           0 :         if (elements <= 0)
     165           0 :                 panic("hashinit: bad cnt");
     166           0 :         if ((elements & (elements - 1)) == 0)
     167           0 :                 hashsize = elements;
     168             :         else
     169           0 :                 for (hashsize = 1; hashsize < elements; hashsize <<= 1)
     170             :                         continue;
     171           0 :         hashtbl = mallocarray(hashsize, sizeof(*hashtbl), type, flags);
     172           0 :         if (hashtbl == NULL)
     173           0 :                 return NULL;
     174           0 :         for (i = 0; i < hashsize; i++)
     175           0 :                 LIST_INIT(&hashtbl[i]);
     176           0 :         *hashmask = hashsize - 1;
     177           0 :         return (hashtbl);
     178           0 : }
     179             : 
     180             : void
     181           0 : hashfree(void *hash, int elements, int type)
     182             : {
     183             :         u_long hashsize;
     184           0 :         LIST_HEAD(generic, generic) *hashtbl = hash;
     185             : 
     186           0 :         if (elements <= 0)
     187           0 :                 panic("hashfree: bad cnt");
     188           0 :         if ((elements & (elements - 1)) == 0)
     189           0 :                 hashsize = elements;
     190             :         else
     191           0 :                 for (hashsize = 1; hashsize < elements; hashsize <<= 1)
     192             :                         continue;
     193             : 
     194           0 :         free(hashtbl, type, sizeof(*hashtbl) * hashsize);
     195           0 : }
     196             : 
     197             : /*
     198             :  * "startup hook" types, functions, and variables.
     199             :  */
     200             : 
     201             : struct hook_desc_head startuphook_list =
     202             :     TAILQ_HEAD_INITIALIZER(startuphook_list);
     203             : 
     204             : void *
     205           0 : hook_establish(struct hook_desc_head *head, int tail, void (*fn)(void *),
     206             :     void *arg)
     207             : {
     208             :         struct hook_desc *hdp;
     209             : 
     210           0 :         hdp = malloc(sizeof(*hdp), M_DEVBUF, M_NOWAIT);
     211           0 :         if (hdp == NULL)
     212           0 :                 return (NULL);
     213             : 
     214           0 :         hdp->hd_fn = fn;
     215           0 :         hdp->hd_arg = arg;
     216           0 :         if (tail)
     217           0 :                 TAILQ_INSERT_TAIL(head, hdp, hd_list);
     218             :         else
     219           0 :                 TAILQ_INSERT_HEAD(head, hdp, hd_list);
     220             : 
     221           0 :         return (hdp);
     222           0 : }
     223             : 
     224             : void
     225           0 : hook_disestablish(struct hook_desc_head *head, void *vhook)
     226             : {
     227             :         struct hook_desc *hdp;
     228             : 
     229             : #ifdef DIAGNOSTIC
     230           0 :         for (hdp = TAILQ_FIRST(head); hdp != NULL;
     231           0 :             hdp = TAILQ_NEXT(hdp, hd_list))
     232           0 :                 if (hdp == vhook)
     233             :                         break;
     234           0 :         if (hdp == NULL)
     235           0 :                 return;
     236             : #endif
     237           0 :         hdp = vhook;
     238           0 :         TAILQ_REMOVE(head, hdp, hd_list);
     239           0 :         free(hdp, M_DEVBUF, sizeof(*hdp));
     240           0 : }
     241             : 
     242             : /*
     243             :  * Run hooks.  Startup hooks are invoked right after scheduler_start but
     244             :  * before root is mounted.  Shutdown hooks are invoked immediately before the
     245             :  * system is halted or rebooted, i.e. after file systems unmounted,
     246             :  * after crash dump done, etc.
     247             :  */
     248             : void
     249           0 : dohooks(struct hook_desc_head *head, int flags)
     250             : {
     251             :         struct hook_desc *hdp, *hdp_temp;
     252             : 
     253           0 :         if ((flags & HOOK_REMOVE) == 0) {
     254           0 :                 TAILQ_FOREACH_SAFE(hdp, head, hd_list, hdp_temp) {
     255           0 :                         (*hdp->hd_fn)(hdp->hd_arg);
     256             :                 }
     257             :         } else {
     258           0 :                 while ((hdp = TAILQ_FIRST(head)) != NULL) {
     259           0 :                         TAILQ_REMOVE(head, hdp, hd_list);
     260           0 :                         (*hdp->hd_fn)(hdp->hd_arg);
     261           0 :                         if ((flags & HOOK_FREE) != 0)
     262           0 :                                 free(hdp, M_DEVBUF, sizeof(*hdp));
     263             :                 }
     264             :         }
     265           0 : }

Generated by: LCOV version 1.13