Line data Source code
1 : /* $OpenBSD: kern_kthread.c,v 1.42 2018/07/05 14:42:30 visa Exp $ */
2 : /* $NetBSD: kern_kthread.c,v 1.3 1998/12/22 21:21:36 kleink Exp $ */
3 :
4 : /*-
5 : * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
6 : * All rights reserved.
7 : *
8 : * This code is derived from software contributed to The NetBSD Foundation
9 : * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10 : * NASA Ames Research Center.
11 : *
12 : * Redistribution and use in source and binary forms, with or without
13 : * modification, are permitted provided that the following conditions
14 : * are met:
15 : * 1. Redistributions of source code must retain the above copyright
16 : * notice, this list of conditions and the following disclaimer.
17 : * 2. Redistributions in binary form must reproduce the above copyright
18 : * notice, this list of conditions and the following disclaimer in the
19 : * documentation and/or other materials provided with the distribution.
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 : * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 : * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 : * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 : * POSSIBILITY OF SUCH DAMAGE.
32 : */
33 :
34 : #include <sys/param.h>
35 : #include <sys/systm.h>
36 : #include <sys/kthread.h>
37 : #include <sys/proc.h>
38 : #include <sys/wait.h>
39 : #include <sys/malloc.h>
40 : #include <sys/queue.h>
41 :
42 :
43 : /*
44 : * note that stdarg.h and the ansi style va_start macro is used for both
45 : * ansi and traditional c compilers.
46 : * XXX: this requires that stdarg.h define: va_alist and va_dcl
47 : */
48 : #include <sys/stdarg.h>
49 :
50 : int kthread_create_now;
51 :
52 : /*
53 : * Fork a kernel thread. Any process can request this to be done.
54 : * The VM space and limits, etc. will be shared with proc0.
55 : */
56 : int
57 0 : kthread_create(void (*func)(void *), void *arg,
58 : struct proc **newpp, const char *name)
59 : {
60 0 : struct proc *p;
61 : int error;
62 :
63 0 : KERNEL_LOCK();
64 :
65 : /*
66 : * First, create the new process. Share the memory, file
67 : * descriptors and don't leave the exit status around for the
68 : * parent to wait for.
69 : */
70 0 : error = fork1(&proc0, FORK_SHAREVM|FORK_SHAREFILES|FORK_NOZOMBIE|
71 : FORK_SYSTEM|FORK_SIGHAND, func, arg, NULL, &p);
72 0 : if (error) {
73 0 : KERNEL_UNLOCK();
74 0 : return (error);
75 : }
76 :
77 : /* Name it as specified. */
78 0 : strlcpy(p->p_p->ps_comm, name, sizeof p->p_p->ps_comm);
79 :
80 0 : KERNEL_UNLOCK();
81 :
82 : /* All done! */
83 0 : if (newpp != NULL)
84 0 : *newpp = p;
85 0 : return (0);
86 0 : }
87 :
88 : /*
89 : * Cause a kernel thread to exit. Assumes the exiting thread is the
90 : * current context.
91 : */
92 : void
93 0 : kthread_exit(int ecode)
94 : {
95 :
96 : /*
97 : * XXX What do we do with the exit code? Should we even bother
98 : * XXX with it? The parent (proc0) isn't going to do much with
99 : * XXX it.
100 : */
101 0 : if (ecode != 0)
102 0 : printf("WARNING: thread `%s' (%d) exits with status %d\n",
103 0 : curproc->p_p->ps_comm, curproc->p_tid, ecode);
104 :
105 0 : exit1(curproc, W_EXITCODE(ecode, 0), EXIT_NORMAL);
106 :
107 : /*
108 : * XXX Fool the compiler. Making exit1() __dead is a can
109 : * XXX of worms right now.
110 : */
111 0 : for (;;);
112 : }
113 :
114 : struct kthread_q {
115 : SIMPLEQ_ENTRY(kthread_q) kq_q;
116 : void (*kq_func)(void *);
117 : void *kq_arg;
118 : };
119 :
120 : SIMPLEQ_HEAD(, kthread_q) kthread_q = SIMPLEQ_HEAD_INITIALIZER(kthread_q);
121 :
122 : /*
123 : * Defer the creation of a kernel thread. Once the standard kernel threads
124 : * and processes have been created, this queue will be run to callback to
125 : * the caller to create threads for e.g. file systems and device drivers.
126 : */
127 : void
128 0 : kthread_create_deferred(void (*func)(void *), void *arg)
129 : {
130 : struct kthread_q *kq;
131 :
132 0 : if (kthread_create_now) {
133 0 : (*func)(arg);
134 0 : return;
135 : }
136 :
137 0 : kq = malloc(sizeof *kq, M_TEMP, M_NOWAIT|M_ZERO);
138 0 : if (kq == NULL)
139 0 : panic("unable to allocate kthread_q");
140 :
141 0 : kq->kq_func = func;
142 0 : kq->kq_arg = arg;
143 :
144 0 : SIMPLEQ_INSERT_TAIL(&kthread_q, kq, kq_q);
145 0 : }
146 :
147 : void
148 0 : kthread_run_deferred_queue(void)
149 : {
150 : struct kthread_q *kq;
151 :
152 : /* No longer need to defer kthread creation. */
153 0 : kthread_create_now = 1;
154 :
155 0 : while ((kq = SIMPLEQ_FIRST(&kthread_q)) != NULL) {
156 0 : SIMPLEQ_REMOVE_HEAD(&kthread_q, kq_q);
157 0 : (*kq->kq_func)(kq->kq_arg);
158 0 : free(kq, M_TEMP, sizeof(*kq));
159 : }
160 0 : }
|