Module Name: src Committed By: pooka Date: Mon Nov 9 19:16:18 UTC 2009
Modified Files: src/sys/rump/librump/rumpkern: intr.c scheduler.c Log Message: Hash out soft interrupts to be a little closer to real softints: * split them into levels * allow only one per level to be active at a time * fire softints only when we are unscheduling from a CPU instead of immediately in softint_schedule(). this will later morph into return from interrupt, but that part isn't done yet. To generate a diff of this commit: cvs rdiff -u -r1.19 -r1.20 src/sys/rump/librump/rumpkern/intr.c cvs rdiff -u -r1.6 -r1.7 src/sys/rump/librump/rumpkern/scheduler.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/rump/librump/rumpkern/intr.c diff -u src/sys/rump/librump/rumpkern/intr.c:1.19 src/sys/rump/librump/rumpkern/intr.c:1.20 --- src/sys/rump/librump/rumpkern/intr.c:1.19 Fri Nov 6 15:22:16 2009 +++ src/sys/rump/librump/rumpkern/intr.c Mon Nov 9 19:16:18 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: intr.c,v 1.19 2009/11/06 15:22:16 pooka Exp $ */ +/* $NetBSD: intr.c,v 1.20 2009/11/09 19:16:18 pooka Exp $ */ /* * Copyright (c) 2008 Antti Kantee. All Rights Reserved. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.19 2009/11/06 15:22:16 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.20 2009/11/09 19:16:18 pooka Exp $"); #include <sys/param.h> #include <sys/cpu.h> @@ -47,46 +47,21 @@ #define SI_MPSAFE 0x01 #define SI_ONLIST 0x02 #define SI_KILLME 0x04 + struct softint { void (*si_func)(void *); void *si_arg; int si_flags; + int si_level; LIST_ENTRY(softint) si_entries; }; -static LIST_HEAD(, softint) si_pending = LIST_HEAD_INITIALIZER(si_pending); -static kmutex_t si_mtx; -static kcondvar_t si_cv; - -#define INTRTHREAD_DEFAULT 2 -#define INTRTHREAD_MAX 20 -static int wrkidle, wrktotal; - -static void sithread(void *); - -static void -makeworker(bool bootstrap) -{ - int rv; - if (wrktotal > INTRTHREAD_MAX) { - /* XXX: ratecheck */ - printf("maximum interrupt threads (%d) reached\n", - INTRTHREAD_MAX); - return; - } - rv = kthread_create(PRI_NONE, KTHREAD_MPSAFE | KTHREAD_INTR, NULL, - sithread, NULL, NULL, "rumpsi"); - if (rv) { - if (bootstrap) - panic("intr thread creation failed %d", rv); - else - printf("intr thread creation failed %d\n", rv); - } else { - wrkidle++; - wrktotal++; - } -} +static struct rumpuser_mtx *si_mtx; +static struct softint_lev { + struct rumpuser_cv *si_cv; + LIST_HEAD(, softint) si_pending; +} softints[SOFTINT_COUNT]; /* rumpuser structures since we call rumpuser interfaces directly */ static struct rumpuser_cv *clockcv; @@ -160,7 +135,9 @@ } /* - * run a scheduled soft interrupt + * Soft interrupt execution thread. Note that we run without a CPU + * context until we start processing the interrupt. This is to avoid + * lock recursion. */ static void sithread(void *arg) @@ -169,62 +146,78 @@ void (*func)(void *) = NULL; void *funarg; bool mpsafe; + int mylevel = (uintptr_t)arg; + struct softint_lev *si_lvl; + + rump_unschedule(); - mutex_enter(&si_mtx); + si_lvl = &softints[mylevel]; + rumpuser_mutex_enter_nowrap(si_mtx); for (;;) { - if (!LIST_EMPTY(&si_pending)) { - si = LIST_FIRST(&si_pending); + if (!LIST_EMPTY(&si_lvl->si_pending)) { + si = LIST_FIRST(&si_lvl->si_pending); func = si->si_func; funarg = si->si_arg; mpsafe = si->si_flags & SI_MPSAFE; si->si_flags &= ~SI_ONLIST; LIST_REMOVE(si, si_entries); - if (si->si_flags & SI_KILLME) + if (si->si_flags & SI_KILLME) { + rumpuser_mutex_exit(si_mtx); + rump_schedule(); softint_disestablish(si); + rump_unschedule(); + rumpuser_mutex_enter_nowrap(si_mtx); + continue; + } } else { - cv_wait(&si_cv, &si_mtx); + rumpuser_cv_wait_nowrap(si_lvl->si_cv, si_mtx); continue; } - wrkidle--; - if (__predict_false(wrkidle == 0)) - makeworker(false); - mutex_exit(&si_mtx); + rumpuser_mutex_exit(si_mtx); + rump_schedule(); if (!mpsafe) KERNEL_LOCK(1, curlwp); func(funarg); if (!mpsafe) KERNEL_UNLOCK_ONE(curlwp); + rump_unschedule(); - mutex_enter(&si_mtx); - wrkidle++; + rumpuser_mutex_enter_nowrap(si_mtx); } + + panic("sithread unreachable"); } void softint_init(struct cpu_info *ci) { - int rv; + int rv, i; - mutex_init(&si_mtx, MUTEX_DEFAULT, IPL_NONE); - cv_init(&si_cv, "intrw8"); /* cv of temporary w8ness */ + rumpuser_mutex_init(&si_mtx); + for (i = 0; i < SOFTINT_COUNT; i++) { + rumpuser_cv_init(&softints[i].si_cv); + LIST_INIT(&softints[i].si_pending); + } rumpuser_cv_init(&clockcv); rumpuser_mutex_init(&clockmtx); /* XXX: should have separate "wanttimer" control */ if (rump_threads) { + for (i = 0; i < SOFTINT_COUNT; i++) { + rv = kthread_create(PRI_NONE, + KTHREAD_MPSAFE | KTHREAD_INTR, NULL, + sithread, (void *)(uintptr_t)i, + NULL, "rumpsi%d", i); + } + rumpuser_mutex_enter(clockmtx); - rv = kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, doclock, - NULL, NULL, "rumpclk"); + rv = kthread_create(PRI_NONE, KTHREAD_MPSAFE | KTHREAD_INTR, + NULL, doclock, NULL, NULL, "rumpclk"); if (rv) panic("clock thread creation failed: %d", rv); - mutex_enter(&si_mtx); - while (wrktotal < INTRTHREAD_DEFAULT) { - makeworker(true); - } - mutex_exit(&si_mtx); /* make sure we have a clocktime before returning */ rumpuser_cv_wait(clockcv, clockmtx); @@ -251,6 +244,8 @@ si->si_func = func; si->si_arg = arg; si->si_flags = flags & SOFTINT_MPSAFE ? SI_MPSAFE : 0; + si->si_level = flags & SOFTINT_LVLMASK; + KASSERT(si->si_level < SOFTINT_COUNT); return si; } @@ -263,13 +258,13 @@ if (!rump_threads) { si->si_func(si->si_arg); } else { - mutex_enter(&si_mtx); + rumpuser_mutex_enter(si_mtx); if (!(si->si_flags & SI_ONLIST)) { - LIST_INSERT_HEAD(&si_pending, si, si_entries); + LIST_INSERT_HEAD(&softints[si->si_level].si_pending, + si, si_entries); si->si_flags |= SI_ONLIST; } - cv_signal(&si_cv); - mutex_exit(&si_mtx); + rumpuser_mutex_exit(si_mtx); } } @@ -279,13 +274,28 @@ { struct softint *si = cook; + rumpuser_mutex_enter(si_mtx); if (si->si_flags & SI_ONLIST) { si->si_flags |= SI_KILLME; return; } + rumpuser_mutex_exit(si_mtx); kmem_free(si, sizeof(*si)); } +void +rump_softint_run(struct cpu_info *ci) +{ + int i; + + rumpuser_mutex_enter_nowrap(si_mtx); + for (i = 0; i < SOFTINT_COUNT; i++) { + if (!LIST_EMPTY(&softints[i].si_pending)) + rumpuser_cv_signal(softints[i].si_cv); + } + rumpuser_mutex_exit(si_mtx); +} + bool cpu_intr_p(void) { @@ -293,10 +303,9 @@ return false; } -/* yea, we lie a bit for now */ bool cpu_softintr_p(void) { - return false; + return curlwp->l_pflag & LP_INTR; } Index: src/sys/rump/librump/rumpkern/scheduler.c diff -u src/sys/rump/librump/rumpkern/scheduler.c:1.6 src/sys/rump/librump/rumpkern/scheduler.c:1.7 --- src/sys/rump/librump/rumpkern/scheduler.c:1.6 Fri Nov 6 16:15:16 2009 +++ src/sys/rump/librump/rumpkern/scheduler.c Mon Nov 9 19:16:18 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: scheduler.c,v 1.6 2009/11/06 16:15:16 pooka Exp $ */ +/* $NetBSD: scheduler.c,v 1.7 2009/11/09 19:16:18 pooka Exp $ */ /* * Copyright (c) 2009 Antti Kantee. All Rights Reserved. @@ -29,7 +29,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: scheduler.c,v 1.6 2009/11/06 16:15:16 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: scheduler.c,v 1.7 2009/11/09 19:16:18 pooka Exp $"); #include <sys/param.h> #include <sys/cpu.h> @@ -182,6 +182,9 @@ struct cpu_info *ci; ci = l->l_cpu; + if ((l->l_pflag & LP_INTR) == 0) + rump_softint_run(ci); + l->l_cpu = NULL; rcpu = &rcpu_storage[ci-&rump_cpus[0]]; KASSERT(rcpu->rcpu_ci == ci);