| @@ -1,320 +1,320 @@ | | | @@ -1,320 +1,320 @@ |
1 | /* $NetBSD: intr.c,v 1.30 2010/08/10 19:16:04 pooka Exp $ */ | | 1 | /* $NetBSD: intr.c,v 1.31 2010/08/10 21:32:38 pooka Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2008 Antti Kantee. All Rights Reserved. | | 4 | * Copyright (c) 2008 Antti Kantee. All Rights Reserved. |
5 | * | | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | | 7 | * modification, are permitted provided that the following conditions |
8 | * are met: | | 8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright | | 9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | | 10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright | | 11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the | | 12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. | | 13 | * documentation and/or other materials provided with the distribution. |
14 | * | | 14 | * |
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS | | 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS |
16 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | | 16 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | | 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
18 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | | 18 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | | 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
25 | * SUCH DAMAGE. | | 25 | * SUCH DAMAGE. |
26 | */ | | 26 | */ |
27 | | | 27 | |
28 | #include <sys/cdefs.h> | | 28 | #include <sys/cdefs.h> |
29 | __KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.30 2010/08/10 19:16:04 pooka Exp $"); | | 29 | __KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.31 2010/08/10 21:32:38 pooka Exp $"); |
30 | | | 30 | |
31 | #include <sys/param.h> | | 31 | #include <sys/param.h> |
32 | #include <sys/atomic.h> | | 32 | #include <sys/atomic.h> |
33 | #include <sys/cpu.h> | | 33 | #include <sys/cpu.h> |
34 | #include <sys/kernel.h> | | 34 | #include <sys/kernel.h> |
35 | #include <sys/kmem.h> | | 35 | #include <sys/kmem.h> |
36 | #include <sys/kthread.h> | | 36 | #include <sys/kthread.h> |
37 | #include <sys/malloc.h> | | 37 | #include <sys/malloc.h> |
38 | #include <sys/intr.h> | | 38 | #include <sys/intr.h> |
39 | #include <sys/timetc.h> | | 39 | #include <sys/timetc.h> |
40 | | | 40 | |
41 | #include <rump/rumpuser.h> | | 41 | #include <rump/rumpuser.h> |
42 | | | 42 | |
43 | #include "rump_private.h" | | 43 | #include "rump_private.h" |
44 | | | 44 | |
45 | /* | | 45 | /* |
46 | * Interrupt simulator. It executes hardclock() and softintrs. | | 46 | * Interrupt simulator. It executes hardclock() and softintrs. |
47 | */ | | 47 | */ |
48 | | | 48 | |
49 | #define SI_MPSAFE 0x01 | | 49 | #define SI_MPSAFE 0x01 |
50 | #define SI_ONLIST 0x02 | | 50 | #define SI_ONLIST 0x02 |
51 | #define SI_KILLME 0x04 | | 51 | #define SI_KILLME 0x04 |
52 | | | 52 | |
53 | struct softint { | | 53 | struct softint { |
54 | void (*si_func)(void *); | | 54 | void (*si_func)(void *); |
55 | void *si_arg; | | 55 | void *si_arg; |
56 | int si_flags; | | 56 | int si_flags; |
57 | int si_level; | | 57 | int si_level; |
58 | | | 58 | |
59 | LIST_ENTRY(softint) si_entries; | | 59 | LIST_ENTRY(softint) si_entries; |
60 | }; | | 60 | }; |
61 | | | 61 | |
62 | struct softint_lev { | | 62 | struct softint_lev { |
63 | struct rumpuser_cv *si_cv; | | 63 | struct rumpuser_cv *si_cv; |
64 | LIST_HEAD(, softint) si_pending; | | 64 | LIST_HEAD(, softint) si_pending; |
65 | }; | | 65 | }; |
66 | | | 66 | |
67 | kcondvar_t lbolt; /* Oh Kath Ra */ | | 67 | kcondvar_t lbolt; /* Oh Kath Ra */ |
68 | | | 68 | |
69 | static u_int ticks; | | 69 | static u_int ticks; |
70 | | | 70 | |
71 | static u_int | | 71 | static u_int |
72 | rumptc_get(struct timecounter *tc) | | 72 | rumptc_get(struct timecounter *tc) |
73 | { | | 73 | { |
74 | | | 74 | |
75 | KASSERT(rump_threads); | | 75 | KASSERT(rump_threads); |
76 | return ticks; | | 76 | return ticks; |
77 | } | | 77 | } |
78 | | | 78 | |
79 | static struct timecounter rumptc = { | | 79 | static struct timecounter rumptc = { |
80 | .tc_get_timecount = rumptc_get, | | 80 | .tc_get_timecount = rumptc_get, |
81 | .tc_poll_pps = NULL, | | 81 | .tc_poll_pps = NULL, |
82 | .tc_counter_mask = ~0, | | 82 | .tc_counter_mask = ~0, |
83 | .tc_frequency = 0, | | 83 | .tc_frequency = 0, |
84 | .tc_name = "rumpclk", | | 84 | .tc_name = "rumpclk", |
85 | .tc_quality = 0, | | 85 | .tc_quality = 0, |
86 | }; | | 86 | }; |
87 | | | 87 | |
88 | /* | | 88 | /* |
89 | * clock "interrupt" | | 89 | * clock "interrupt" |
90 | */ | | 90 | */ |
91 | static void | | 91 | static void |
92 | doclock(void *noarg) | | 92 | doclock(void *noarg) |
93 | { | | 93 | { |
94 | struct timespec clockbase, clockup; | | 94 | struct timespec clockbase, clockup; |
95 | struct timespec thetick, curtime; | | 95 | struct timespec thetick, curtime; |
96 | struct rumpuser_cv *clockcv; | | 96 | struct rumpuser_cv *clockcv; |
97 | struct rumpuser_mtx *clockmtx; | | 97 | struct rumpuser_mtx *clockmtx; |
98 | uint64_t sec, nsec; | | 98 | uint64_t sec, nsec; |
99 | int error; | | 99 | int error; |
100 | extern int hz; | | 100 | extern int hz; |
101 | | | 101 | |
102 | memset(&clockup, 0, sizeof(clockup)); | | 102 | memset(&clockup, 0, sizeof(clockup)); |
103 | rumpuser_gettime(&sec, &nsec, &error); | | 103 | rumpuser_gettime(&sec, &nsec, &error); |
104 | clockbase.tv_sec = sec; | | 104 | clockbase.tv_sec = sec; |
105 | clockbase.tv_nsec = nsec; | | 105 | clockbase.tv_nsec = nsec; |
106 | curtime = clockbase; | | 106 | curtime = clockbase; |
107 | thetick.tv_sec = 0; | | 107 | thetick.tv_sec = 0; |
108 | thetick.tv_nsec = 1000000000/hz; | | 108 | thetick.tv_nsec = 1000000000/hz; |
109 | | | 109 | |
110 | /* XXX: dummies */ | | 110 | /* XXX: dummies */ |
111 | rumpuser_cv_init(&clockcv); | | 111 | rumpuser_cv_init(&clockcv); |
112 | rumpuser_mutex_init(&clockmtx); | | 112 | rumpuser_mutex_init(&clockmtx); |
113 | | | 113 | |
114 | rumpuser_mutex_enter(clockmtx); | | 114 | rumpuser_mutex_enter(clockmtx); |
115 | for (;;) { | | 115 | for (;;) { |
116 | callout_hardclock(); | | 116 | callout_hardclock(); |
117 | | | 117 | |
118 | /* wait until the next tick. XXX: what if the clock changes? */ | | 118 | /* wait until the next tick. XXX: what if the clock changes? */ |
119 | while (rumpuser_cv_timedwait(clockcv, clockmtx, | | 119 | while (rumpuser_cv_timedwait(clockcv, clockmtx, |
120 | curtime.tv_sec, curtime.tv_nsec) == 0) | | 120 | curtime.tv_sec, curtime.tv_nsec) == 0) |
121 | continue; | | 121 | continue; |
122 | | | 122 | |
123 | /* XXX: sync with a) virtual clock b) host clock */ | | 123 | /* XXX: sync with a) virtual clock b) host clock */ |
124 | timespecadd(&clockup, &clockbase, &curtime); | | 124 | timespecadd(&clockup, &clockbase, &curtime); |
125 | timespecadd(&clockup, &thetick, &clockup); | | 125 | timespecadd(&clockup, &thetick, &clockup); |
126 | | | 126 | |
127 | #if 0 | | 127 | #if 0 |
128 | /* CPU_IS_PRIMARY is MD and hence unreliably correct here */ | | 128 | /* CPU_IS_PRIMARY is MD and hence unreliably correct here */ |
129 | if (!CPU_IS_PRIMARY(curcpu())) | | 129 | if (!CPU_IS_PRIMARY(curcpu())) |
130 | continue; | | 130 | continue; |
131 | #else | | 131 | #else |
132 | if (curcpu()->ci_index != 0) | | 132 | if (curcpu()->ci_index != 0) |
133 | continue; | | 133 | continue; |
134 | #endif | | 134 | #endif |
135 | | | 135 | |
136 | if ((++ticks % hz) == 0) { | | 136 | if ((++ticks % hz) == 0) { |
137 | cv_broadcast(&lbolt); | | 137 | cv_broadcast(&lbolt); |
138 | } | | 138 | } |
139 | tc_ticktock(); | | 139 | tc_ticktock(); |
140 | } | | 140 | } |
141 | } | | 141 | } |
142 | | | 142 | |
143 | /* | | 143 | /* |
144 | * Soft interrupt execution thread. This thread is pinned to the | | 144 | * Soft interrupt execution thread. This thread is pinned to the |
145 | * same CPU that scheduled the interrupt, so we don't need to do | | 145 | * same CPU that scheduled the interrupt, so we don't need to do |
146 | * lock against si_lvl. | | 146 | * lock against si_lvl. |
147 | */ | | 147 | */ |
148 | static void | | 148 | static void |
149 | sithread(void *arg) | | 149 | sithread(void *arg) |
150 | { | | 150 | { |
151 | struct softint *si; | | 151 | struct softint *si; |
152 | void (*func)(void *) = NULL; | | 152 | void (*func)(void *) = NULL; |
153 | void *funarg; | | 153 | void *funarg; |
154 | bool mpsafe; | | 154 | bool mpsafe; |
155 | int mylevel = (uintptr_t)arg; | | 155 | int mylevel = (uintptr_t)arg; |
156 | struct softint_lev *si_lvlp, *si_lvl; | | 156 | struct softint_lev *si_lvlp, *si_lvl; |
157 | struct cpu_data *cd = &curcpu()->ci_data; | | 157 | struct cpu_data *cd = &curcpu()->ci_data; |
158 | | | 158 | |
159 | si_lvlp = cd->cpu_softcpu; | | 159 | si_lvlp = cd->cpu_softcpu; |
160 | si_lvl = &si_lvlp[mylevel]; | | 160 | si_lvl = &si_lvlp[mylevel]; |
161 | | | 161 | |
162 | for (;;) { | | 162 | for (;;) { |
163 | if (!LIST_EMPTY(&si_lvl->si_pending)) { | | 163 | if (!LIST_EMPTY(&si_lvl->si_pending)) { |
164 | si = LIST_FIRST(&si_lvl->si_pending); | | 164 | si = LIST_FIRST(&si_lvl->si_pending); |
165 | func = si->si_func; | | 165 | func = si->si_func; |
166 | funarg = si->si_arg; | | 166 | funarg = si->si_arg; |
167 | mpsafe = si->si_flags & SI_MPSAFE; | | 167 | mpsafe = si->si_flags & SI_MPSAFE; |
168 | | | 168 | |
169 | si->si_flags &= ~SI_ONLIST; | | 169 | si->si_flags &= ~SI_ONLIST; |
170 | LIST_REMOVE(si, si_entries); | | 170 | LIST_REMOVE(si, si_entries); |
171 | if (si->si_flags & SI_KILLME) { | | 171 | if (si->si_flags & SI_KILLME) { |
172 | softint_disestablish(si); | | 172 | softint_disestablish(si); |
173 | continue; | | 173 | continue; |
174 | } | | 174 | } |
175 | } else { | | 175 | } else { |
176 | rump_schedlock_cv_wait(si_lvl->si_cv); | | 176 | rump_schedlock_cv_wait(si_lvl->si_cv); |
177 | continue; | | 177 | continue; |
178 | } | | 178 | } |
179 | | | 179 | |
180 | if (!mpsafe) | | 180 | if (!mpsafe) |
181 | KERNEL_LOCK(1, curlwp); | | 181 | KERNEL_LOCK(1, curlwp); |
182 | func(funarg); | | 182 | func(funarg); |
183 | if (!mpsafe) | | 183 | if (!mpsafe) |
184 | KERNEL_UNLOCK_ONE(curlwp); | | 184 | KERNEL_UNLOCK_ONE(curlwp); |
185 | } | | 185 | } |
186 | | | 186 | |
187 | panic("sithread unreachable"); | | 187 | panic("sithread unreachable"); |
188 | } | | 188 | } |
189 | | | 189 | |
190 | void | | 190 | void |
191 | rump_intr_init() | | 191 | rump_intr_init() |
192 | { | | 192 | { |
193 | | | 193 | |
194 | cv_init(&lbolt, "oh kath ra"); | | 194 | cv_init(&lbolt, "oh kath ra"); |
195 | } | | 195 | } |
196 | | | 196 | |
197 | void | | 197 | void |
198 | softint_init(struct cpu_info *ci) | | 198 | softint_init(struct cpu_info *ci) |
199 | { | | 199 | { |
200 | struct cpu_data *cd = &ci->ci_data; | | 200 | struct cpu_data *cd = &ci->ci_data; |
201 | struct softint_lev *slev; | | 201 | struct softint_lev *slev; |
202 | int rv, i; | | 202 | int rv, i; |
203 | | | 203 | |
204 | if (!rump_threads) | | 204 | if (!rump_threads) |
205 | return; | | 205 | return; |
206 | | | 206 | |
207 | /* XXX */ | | 207 | /* XXX */ |
208 | if (ci->ci_index == 0) { | | 208 | if (ci->ci_index == 0) { |
209 | rumptc.tc_frequency = hz; | | 209 | rumptc.tc_frequency = hz; |
210 | tc_init(&rumptc); | | 210 | tc_init(&rumptc); |
211 | } | | 211 | } |
212 | | | 212 | |
213 | slev = kmem_alloc(sizeof(struct softint_lev) * SOFTINT_COUNT, KM_SLEEP); | | 213 | slev = kmem_alloc(sizeof(struct softint_lev) * SOFTINT_COUNT, KM_SLEEP); |
214 | for (i = 0; i < SOFTINT_COUNT; i++) { | | 214 | for (i = 0; i < SOFTINT_COUNT; i++) { |
215 | rumpuser_cv_init(&slev[i].si_cv); | | 215 | rumpuser_cv_init(&slev[i].si_cv); |
216 | LIST_INIT(&slev[i].si_pending); | | 216 | LIST_INIT(&slev[i].si_pending); |
217 | } | | 217 | } |
218 | cd->cpu_softcpu = slev; | | 218 | cd->cpu_softcpu = slev; |
219 | | | 219 | |
220 | /* softint might run on different physical CPU */ | | 220 | /* softint might run on different physical CPU */ |
221 | membar_sync(); | | 221 | membar_sync(); |
222 | | | 222 | |
223 | for (i = 0; i < SOFTINT_COUNT; i++) { | | 223 | for (i = 0; i < SOFTINT_COUNT; i++) { |
224 | rv = kthread_create(PRI_NONE, | | 224 | rv = kthread_create(PRI_NONE, |
225 | KTHREAD_MPSAFE | KTHREAD_INTR, ci, | | 225 | KTHREAD_MPSAFE | KTHREAD_INTR, ci, |
226 | sithread, (void *)(uintptr_t)i, | | 226 | sithread, (void *)(uintptr_t)i, |
227 | NULL, "rsi%d/%d", ci->ci_index, i); | | 227 | NULL, "rsi%d/%d", ci->ci_index, i); |
228 | } | | 228 | } |
229 | | | 229 | |
230 | rv = kthread_create(PRI_NONE, KTHREAD_MPSAFE | KTHREAD_INTR, | | 230 | rv = kthread_create(PRI_NONE, KTHREAD_MPSAFE, |
231 | ci, doclock, NULL, NULL, "rumpclk%d", ci->ci_index); | | 231 | ci, doclock, NULL, NULL, "rumpclk%d", ci->ci_index); |
232 | if (rv) | | 232 | if (rv) |
233 | panic("clock thread creation failed: %d", rv); | | 233 | panic("clock thread creation failed: %d", rv); |
234 | } | | 234 | } |
235 | | | 235 | |
236 | /* | | 236 | /* |
237 | * Soft interrupts bring two choices. If we are running with thread | | 237 | * Soft interrupts bring two choices. If we are running with thread |
238 | * support enabled, defer execution, otherwise execute in place. | | 238 | * support enabled, defer execution, otherwise execute in place. |
239 | * See softint_schedule(). | | 239 | * See softint_schedule(). |
240 | * | | 240 | * |
241 | * As there is currently no clear concept of when a thread finishes | | 241 | * As there is currently no clear concept of when a thread finishes |
242 | * work (although rump_clear_curlwp() is close), simply execute all | | 242 | * work (although rump_clear_curlwp() is close), simply execute all |
243 | * softints in the timer thread. This is probably not the most | | 243 | * softints in the timer thread. This is probably not the most |
244 | * efficient method, but good enough for now. | | 244 | * efficient method, but good enough for now. |
245 | */ | | 245 | */ |
246 | void * | | 246 | void * |
247 | softint_establish(u_int flags, void (*func)(void *), void *arg) | | 247 | softint_establish(u_int flags, void (*func)(void *), void *arg) |
248 | { | | 248 | { |
249 | struct softint *si; | | 249 | struct softint *si; |
250 | | | 250 | |
251 | si = malloc(sizeof(*si), M_TEMP, M_WAITOK); | | 251 | si = malloc(sizeof(*si), M_TEMP, M_WAITOK); |
252 | si->si_func = func; | | 252 | si->si_func = func; |
253 | si->si_arg = arg; | | 253 | si->si_arg = arg; |
254 | si->si_flags = flags & SOFTINT_MPSAFE ? SI_MPSAFE : 0; | | 254 | si->si_flags = flags & SOFTINT_MPSAFE ? SI_MPSAFE : 0; |
255 | si->si_level = flags & SOFTINT_LVLMASK; | | 255 | si->si_level = flags & SOFTINT_LVLMASK; |
256 | KASSERT(si->si_level < SOFTINT_COUNT); | | 256 | KASSERT(si->si_level < SOFTINT_COUNT); |
257 | | | 257 | |
258 | return si; | | 258 | return si; |
259 | } | | 259 | } |
260 | | | 260 | |
261 | void | | 261 | void |
262 | softint_schedule(void *arg) | | 262 | softint_schedule(void *arg) |
263 | { | | 263 | { |
264 | struct softint *si = arg; | | 264 | struct softint *si = arg; |
265 | struct cpu_data *cd = &curcpu()->ci_data; | | 265 | struct cpu_data *cd = &curcpu()->ci_data; |
266 | struct softint_lev *si_lvl = cd->cpu_softcpu; | | 266 | struct softint_lev *si_lvl = cd->cpu_softcpu; |
267 | | | 267 | |
268 | if (!rump_threads) { | | 268 | if (!rump_threads) { |
269 | si->si_func(si->si_arg); | | 269 | si->si_func(si->si_arg); |
270 | } else { | | 270 | } else { |
271 | if (!(si->si_flags & SI_ONLIST)) { | | 271 | if (!(si->si_flags & SI_ONLIST)) { |
272 | LIST_INSERT_HEAD(&si_lvl[si->si_level].si_pending, | | 272 | LIST_INSERT_HEAD(&si_lvl[si->si_level].si_pending, |
273 | si, si_entries); | | 273 | si, si_entries); |
274 | si->si_flags |= SI_ONLIST; | | 274 | si->si_flags |= SI_ONLIST; |
275 | } | | 275 | } |
276 | } | | 276 | } |
277 | } | | 277 | } |
278 | | | 278 | |
279 | /* flimsy disestablish: should wait for softints to finish */ | | 279 | /* flimsy disestablish: should wait for softints to finish */ |
280 | void | | 280 | void |
281 | softint_disestablish(void *cook) | | 281 | softint_disestablish(void *cook) |
282 | { | | 282 | { |
283 | struct softint *si = cook; | | 283 | struct softint *si = cook; |
284 | | | 284 | |
285 | if (si->si_flags & SI_ONLIST) { | | 285 | if (si->si_flags & SI_ONLIST) { |
286 | si->si_flags |= SI_KILLME; | | 286 | si->si_flags |= SI_KILLME; |
287 | return; | | 287 | return; |
288 | } | | 288 | } |
289 | free(si, M_TEMP); | | 289 | free(si, M_TEMP); |
290 | } | | 290 | } |
291 | | | 291 | |
292 | void | | 292 | void |
293 | rump_softint_run(struct cpu_info *ci) | | 293 | rump_softint_run(struct cpu_info *ci) |
294 | { | | 294 | { |
295 | struct cpu_data *cd = &ci->ci_data; | | 295 | struct cpu_data *cd = &ci->ci_data; |
296 | struct softint_lev *si_lvl = cd->cpu_softcpu; | | 296 | struct softint_lev *si_lvl = cd->cpu_softcpu; |
297 | int i; | | 297 | int i; |
298 | | | 298 | |
299 | if (!rump_threads) | | 299 | if (!rump_threads) |
300 | return; | | 300 | return; |
301 | | | 301 | |
302 | for (i = 0; i < SOFTINT_COUNT; i++) { | | 302 | for (i = 0; i < SOFTINT_COUNT; i++) { |
303 | if (!LIST_EMPTY(&si_lvl[i].si_pending)) | | 303 | if (!LIST_EMPTY(&si_lvl[i].si_pending)) |
304 | rumpuser_cv_signal(si_lvl[i].si_cv); | | 304 | rumpuser_cv_signal(si_lvl[i].si_cv); |
305 | } | | 305 | } |
306 | } | | 306 | } |
307 | | | 307 | |
308 | bool | | 308 | bool |
309 | cpu_intr_p(void) | | 309 | cpu_intr_p(void) |
310 | { | | 310 | { |
311 | | | 311 | |
312 | return false; | | 312 | return false; |
313 | } | | 313 | } |
314 | | | 314 | |
315 | bool | | 315 | bool |
316 | cpu_softintr_p(void) | | 316 | cpu_softintr_p(void) |
317 | { | | 317 | { |
318 | | | 318 | |
319 | return curlwp->l_pflag & LP_INTR; | | 319 | return curlwp->l_pflag & LP_INTR; |
320 | } | | 320 | } |