Tue Aug 10 21:32:38 2010 UTC ()
Don't create the percpu clock interrupt threads as softint threads
because they aren't softint threads.  This fixes callouts in
situations where there is nothing else happening in the rump kernel
(i.e. no threads executed which would trigger the softints when
they unschedule).


(pooka)
diff -r1.30 -r1.31 src/sys/rump/librump/rumpkern/intr.c

cvs diff -r1.30 -r1.31 src/sys/rump/librump/rumpkern/intr.c (switch to unified diff)

--- src/sys/rump/librump/rumpkern/intr.c 2010/08/10 19:16:04 1.30
+++ src/sys/rump/librump/rumpkern/intr.c 2010/08/10 21:32:38 1.31
@@ -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
53struct softint { 53struct 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
62struct softint_lev { 62struct 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
67kcondvar_t lbolt; /* Oh Kath Ra */ 67kcondvar_t lbolt; /* Oh Kath Ra */
68 68
69static u_int ticks; 69static u_int ticks;
70 70
71static u_int 71static u_int
72rumptc_get(struct timecounter *tc) 72rumptc_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
79static struct timecounter rumptc = { 79static 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 */
91static void 91static void
92doclock(void *noarg) 92doclock(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 */
148static void 148static void
149sithread(void *arg) 149sithread(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
190void 190void
191rump_intr_init() 191rump_intr_init()
192{ 192{
193 193
194 cv_init(&lbolt, "oh kath ra"); 194 cv_init(&lbolt, "oh kath ra");
195} 195}
196 196
197void 197void
198softint_init(struct cpu_info *ci) 198softint_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 */
246void * 246void *
247softint_establish(u_int flags, void (*func)(void *), void *arg) 247softint_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
261void 261void
262softint_schedule(void *arg) 262softint_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 */
280void 280void
281softint_disestablish(void *cook) 281softint_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
292void 292void
293rump_softint_run(struct cpu_info *ci) 293rump_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
308bool 308bool
309cpu_intr_p(void) 309cpu_intr_p(void)
310{ 310{
311 311
312 return false; 312 return false;
313} 313}
314 314
315bool 315bool
316cpu_softintr_p(void) 316cpu_softintr_p(void)
317{ 317{
318 318
319 return curlwp->l_pflag & LP_INTR; 319 return curlwp->l_pflag & LP_INTR;
320} 320}