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 : }
|