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