Commit | Line | Data |
---|---|---|
984263bc MD |
1 | /* |
2 | * Copyright (c) 1999 Peter Wemm <peter@FreeBSD.org> | |
3 | * All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * 2. Redistributions in binary form must reproduce the above copyright | |
11 | * notice, this list of conditions and the following disclaimer in the | |
12 | * documentation and/or other materials provided with the distribution. | |
13 | * | |
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
24 | * SUCH DAMAGE. | |
984263bc MD |
25 | */ |
26 | ||
27 | #include <sys/param.h> | |
28 | #include <sys/systm.h> | |
29 | #include <sys/proc.h> | |
30 | #include <sys/kthread.h> | |
31 | #include <sys/ptrace.h> | |
32 | #include <sys/resourcevar.h> | |
33 | #include <sys/signalvar.h> | |
34 | #include <sys/unistd.h> | |
35 | #include <sys/wait.h> | |
36 | ||
37 | #include <machine/stdarg.h> | |
38 | ||
a3c18566 | 39 | static struct lwkt_token kpsus_token = LWKT_TOKEN_INITIALIZER(kpsus_token); |
cd8ab232 MD |
40 | |
41 | ||
496907b0 | 42 | /* |
7325bc31 | 43 | * Create a new lightweight kernel thread. |
496907b0 | 44 | */ |
aa2693a5 | 45 | static int __printflike(6, 0) |
7325bc31 | 46 | _kthread_create(void (*func)(void *), void *arg, |
aa2693a5 | 47 | struct thread **tdp, int cpu, bool schedule_now, const char *fmt, __va_list ap) |
496907b0 MD |
48 | { |
49 | thread_t td; | |
7325bc31 | 50 | int flags = 0; |
496907b0 | 51 | |
7325bc31 | 52 | td = lwkt_alloc_thread(NULL, LWKT_THREAD_STACK, cpu, flags); |
496907b0 MD |
53 | if (tdp) |
54 | *tdp = td; | |
55 | cpu_set_thread_handler(td, kthread_exit, func, arg); | |
496907b0 MD |
56 | |
57 | /* | |
58 | * Set up arg0 for 'ps' etc | |
59 | */ | |
379210cb | 60 | kvsnprintf(td->td_comm, sizeof(td->td_comm), fmt, ap); |
496907b0 | 61 | |
60055ede SG |
62 | td->td_ucred = crhold(proc0.p_ucred); |
63 | ||
496907b0 MD |
64 | /* |
65 | * Schedule the thread to run | |
66 | */ | |
aa2693a5 FT |
67 | if (schedule_now) |
68 | lwkt_schedule(td); | |
7325bc31 | 69 | |
496907b0 MD |
70 | return 0; |
71 | } | |
72 | ||
aa2693a5 FT |
73 | /* Create a new lightweight kernel thread and do not schedule it */ |
74 | int | |
75 | kthread_alloc(void (*func)(void *), void *arg, | |
76 | struct thread **tdp, const char *fmt, ...) | |
77 | { | |
78 | __va_list ap; | |
79 | int ret; | |
80 | ||
81 | __va_start(ap, fmt); | |
82 | ret = _kthread_create(func, arg, tdp, -1, false, fmt, ap); | |
83 | __va_end(ap); | |
84 | ||
85 | return ret; | |
86 | } | |
87 | ||
7325bc31 AHJ |
88 | /* |
89 | * Creates a lwkt. No CPU preference. | |
90 | */ | |
91 | int | |
92 | kthread_create(void (*func)(void *), void *arg, | |
93 | struct thread **tdp, const char *fmt, ...) | |
94 | { | |
70c5c55f AH |
95 | __va_list ap; |
96 | int ret; | |
97 | ||
98 | __va_start(ap, fmt); | |
aa2693a5 | 99 | ret = _kthread_create(func, arg, tdp, -1, true, fmt, ap); |
70c5c55f AH |
100 | __va_end(ap); |
101 | ||
102 | return ret; | |
7325bc31 AHJ |
103 | } |
104 | ||
105 | /* | |
106 | * Creates a lwkt and schedule it to run in a specific CPU. | |
107 | * | |
108 | */ | |
be13c473 MD |
109 | int |
110 | kthread_create_cpu(void (*func)(void *), void *arg, | |
111 | struct thread **tdp, int cpu, const char *fmt, ...) | |
112 | { | |
70c5c55f AH |
113 | __va_list ap; |
114 | int ret; | |
115 | ||
116 | __va_start(ap, fmt); | |
aa2693a5 | 117 | ret = _kthread_create(func, arg, tdp, cpu, true, fmt, ap); |
70c5c55f AH |
118 | __va_end(ap); |
119 | ||
120 | return ret; | |
be13c473 MD |
121 | } |
122 | ||
d2d8515b | 123 | #if 0 |
496907b0 MD |
124 | /* |
125 | * Same as kthread_create() but you can specify a custom stack size. | |
126 | */ | |
127 | int | |
128 | kthread_create_stk(void (*func)(void *), void *arg, | |
be13c473 | 129 | struct thread **tdp, int stksize, const char *fmt, ...) |
496907b0 MD |
130 | { |
131 | thread_t td; | |
132 | __va_list ap; | |
133 | ||
95cf7db1 | 134 | td = lwkt_alloc_thread(NULL, stksize, -1, 0); |
496907b0 MD |
135 | if (tdp) |
136 | *tdp = td; | |
137 | cpu_set_thread_handler(td, kthread_exit, func, arg); | |
cd8ab232 | 138 | |
496907b0 | 139 | __va_start(ap, fmt); |
379210cb | 140 | kvsnprintf(td->td_comm, sizeof(td->td_comm), fmt, ap); |
496907b0 MD |
141 | __va_end(ap); |
142 | ||
143 | lwkt_schedule(td); | |
144 | return 0; | |
145 | } | |
d2d8515b | 146 | #endif |
496907b0 MD |
147 | |
148 | /* | |
149 | * Destroy an LWKT thread. Warning! This function is not called when | |
150 | * a process exits, cpu_proc_exit() directly calls cpu_thread_exit() and | |
151 | * uses a different reaping mechanism. | |
152 | * | |
153 | * XXX duplicates lwkt_exit() | |
154 | */ | |
155 | void | |
156 | kthread_exit(void) | |
157 | { | |
158 | lwkt_exit(); | |
159 | } | |
160 | ||
984263bc MD |
161 | /* |
162 | * Start a kernel process. This is called after a fork() call in | |
163 | * mi_startup() in the file kern/init_main.c. | |
164 | * | |
165 | * This function is used to start "internal" daemons and intended | |
166 | * to be called from SYSINIT(). | |
cd8ab232 MD |
167 | * |
168 | * These threads are created MPSAFE. | |
984263bc MD |
169 | */ |
170 | void | |
77153250 | 171 | kproc_start(const void *udata) |
984263bc MD |
172 | { |
173 | const struct kproc_desc *kp = udata; | |
174 | int error; | |
175 | ||
176 | error = kthread_create((void (*)(void *))kp->func, NULL, | |
a7a95662 | 177 | kp->global_threadpp, "%s", kp->arg0); |
26a0694b | 178 | lwkt_setpri(*kp->global_threadpp, TDPRI_KERN_DAEMON); |
984263bc MD |
179 | if (error) |
180 | panic("kproc_start: %s: error %d", kp->arg0, error); | |
181 | } | |
182 | ||
984263bc MD |
183 | /* |
184 | * Advise a kernel process to suspend (or resume) in its main loop. | |
185 | * Participation is voluntary. | |
186 | */ | |
187 | int | |
bc6dffab | 188 | suspend_kproc(struct thread *td, int timo) |
984263bc | 189 | { |
0cfcada1 | 190 | if (td->td_proc == NULL) { |
cd8ab232 | 191 | lwkt_gettoken(&kpsus_token); |
4643740a MD |
192 | /* request thread pause */ |
193 | atomic_set_int(&td->td_mpflags, TDF_MP_STOPREQ); | |
0cfcada1 | 194 | wakeup(td); |
4643740a | 195 | while (td->td_mpflags & TDF_MP_STOPREQ) { |
377d4740 | 196 | int error = tsleep(td, 0, "suspkp", timo); |
0cfcada1 MD |
197 | if (error == EWOULDBLOCK) |
198 | break; | |
199 | } | |
4643740a | 200 | atomic_clear_int(&td->td_mpflags, TDF_MP_STOPREQ); |
cd8ab232 | 201 | lwkt_reltoken(&kpsus_token); |
0cfcada1 MD |
202 | return(0); |
203 | } else { | |
204 | return(EINVAL); /* not a kernel thread */ | |
205 | } | |
984263bc MD |
206 | } |
207 | ||
208 | void | |
0cfcada1 | 209 | kproc_suspend_loop(void) |
984263bc | 210 | { |
0cfcada1 MD |
211 | struct thread *td = curthread; |
212 | ||
4643740a | 213 | if (td->td_mpflags & TDF_MP_STOPREQ) { |
cd8ab232 | 214 | lwkt_gettoken(&kpsus_token); |
4643740a MD |
215 | atomic_clear_int(&td->td_mpflags, TDF_MP_STOPREQ); |
216 | while ((td->td_mpflags & TDF_MP_WAKEREQ) == 0) { | |
0cfcada1 | 217 | wakeup(td); |
377d4740 | 218 | tsleep(td, 0, "kpsusp", 0); |
0cfcada1 | 219 | } |
4643740a | 220 | atomic_clear_int(&td->td_mpflags, TDF_MP_WAKEREQ); |
0cfcada1 | 221 | wakeup(td); |
cd8ab232 | 222 | lwkt_reltoken(&kpsus_token); |
984263bc MD |
223 | } |
224 | } | |
0cfcada1 | 225 |