Module Name: src Committed By: pooka Date: Tue Dec 1 09:50:51 UTC 2009
Modified Files: src/sys/rump/librump/rumpkern: intr.c locks.c rump.c rump_private.h scheduler.c threads.c Log Message: Almost there for virtual CPU MP support: * support bound kernel threads * bind softint threads to specific virtual cpus + remove now-unnecessary locks from softint code Now, if we only had MI CPU_INFO_FOREACH() .... (hi rmind ;) To generate a diff of this commit: cvs rdiff -u -r1.21 -r1.22 src/sys/rump/librump/rumpkern/intr.c cvs rdiff -u -r1.35 -r1.36 src/sys/rump/librump/rumpkern/locks.c cvs rdiff -u -r1.142 -r1.143 src/sys/rump/librump/rumpkern/rump.c cvs rdiff -u -r1.36 -r1.37 src/sys/rump/librump/rumpkern/rump_private.h cvs rdiff -u -r1.7 -r1.8 src/sys/rump/librump/rumpkern/scheduler.c cvs rdiff -u -r1.3 -r1.4 src/sys/rump/librump/rumpkern/threads.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.21 src/sys/rump/librump/rumpkern/intr.c:1.22 --- src/sys/rump/librump/rumpkern/intr.c:1.21 Wed Nov 11 16:46:50 2009 +++ src/sys/rump/librump/rumpkern/intr.c Tue Dec 1 09:50:51 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: intr.c,v 1.21 2009/11/11 16:46:50 pooka Exp $ */ +/* $NetBSD: intr.c,v 1.22 2009/12/01 09:50:51 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.21 2009/11/11 16:46:50 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.22 2009/12/01 09:50:51 pooka Exp $"); #include <sys/param.h> #include <sys/cpu.h> @@ -58,10 +58,10 @@ }; static struct rumpuser_mtx *si_mtx; -static struct softint_lev { +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; @@ -117,15 +117,17 @@ for (;;) { callout_hardclock(); - if (++ticks == hz) { - time_uptime++; - ticks = 0; - } - /* wait until the next tick. XXX: what if the clock changes? */ while (rumpuser_cv_timedwait(clockcv, clockmtx, curtime.tv_sec, curtime.tv_nsec) == 0) continue; + + /* if !maincpu: continue */ + + if (++ticks == hz) { + time_uptime++; + ticks = 0; + } clkgen++; timespecadd(&clockup, &tick, &clockup); @@ -147,11 +149,18 @@ void *funarg; bool mpsafe; int mylevel = (uintptr_t)arg; - struct softint_lev *si_lvl; + struct softint_lev *si_lvlp, *si_lvl; + struct cpu_data *cd = &curcpu()->ci_data; rump_unschedule(); - si_lvl = &softints[mylevel]; + si_lvlp = cd->cpu_softcpu; + si_lvl = &si_lvlp[mylevel]; + + /* + * XXX: si_mtx is unnecessary, and should open an interface + * which allows to use schedmtx for the cv wait + */ rumpuser_mutex_enter_nowrap(si_mtx); for (;;) { if (!LIST_EMPTY(&si_lvl->si_pending)) { @@ -191,38 +200,54 @@ } void +rump_intr_init() +{ + + rumpuser_mutex_init(&si_mtx); + rumpuser_cv_init(&clockcv); + rumpuser_mutex_init(&clockmtx); +} + +void softint_init(struct cpu_info *ci) { + struct cpu_data *cd = &ci->ci_data; + struct softint_lev *slev; int rv, i; - rumpuser_mutex_init(&si_mtx); + if (!rump_threads) + return; + + slev = kmem_alloc(sizeof(struct softint_lev) * SOFTINT_COUNT, KM_SLEEP); for (i = 0; i < SOFTINT_COUNT; i++) { - rumpuser_cv_init(&softints[i].si_cv); - LIST_INIT(&softints[i].si_pending); + rumpuser_cv_init(&slev[i].si_cv); + LIST_INIT(&slev[i].si_pending); } + cd->cpu_softcpu = slev; - 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); - } + 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 | KTHREAD_INTR, - NULL, doclock, NULL, NULL, "rumpclk"); + rumpuser_mutex_enter(clockmtx); + for (i = 0; i < ncpu; i++) { + rv = kthread_create(PRI_NONE, + KTHREAD_MPSAFE | KTHREAD_INTR, + cpu_lookup(i), doclock, NULL, NULL, + "rumpclk%d", i); if (rv) panic("clock thread creation failed: %d", rv); - - /* make sure we have a clocktime before returning */ - rumpuser_cv_wait(clockcv, clockmtx); - rumpuser_mutex_exit(clockmtx); } + + /* + * Make sure we have a clocktime before returning. + * XXX: mp + */ + rumpuser_cv_wait(clockcv, clockmtx); + rumpuser_mutex_exit(clockmtx); } /* @@ -254,17 +279,17 @@ softint_schedule(void *arg) { struct softint *si = arg; + struct cpu_data *cd = &curcpu()->ci_data; + struct softint_lev *si_lvl = cd->cpu_softcpu; if (!rump_threads) { si->si_func(si->si_arg); } else { - rumpuser_mutex_enter(si_mtx); if (!(si->si_flags & SI_ONLIST)) { - LIST_INSERT_HEAD(&softints[si->si_level].si_pending, + LIST_INSERT_HEAD(&si_lvl[si->si_level].si_pending, si, si_entries); si->si_flags |= SI_ONLIST; } - rumpuser_mutex_exit(si_mtx); } } @@ -286,14 +311,17 @@ void rump_softint_run(struct cpu_info *ci) { + struct cpu_data *cd = &ci->ci_data; + struct softint_lev *si_lvl = cd->cpu_softcpu; int i; - rumpuser_mutex_enter_nowrap(si_mtx); + if (!rump_threads) + return; + for (i = 0; i < SOFTINT_COUNT; i++) { - if (!LIST_EMPTY(&softints[i].si_pending)) - rumpuser_cv_signal(softints[i].si_cv); + if (!LIST_EMPTY(&si_lvl[i].si_pending)) + rumpuser_cv_signal(si_lvl[i].si_cv); } - rumpuser_mutex_exit(si_mtx); } bool Index: src/sys/rump/librump/rumpkern/locks.c diff -u src/sys/rump/librump/rumpkern/locks.c:1.35 src/sys/rump/librump/rumpkern/locks.c:1.36 --- src/sys/rump/librump/rumpkern/locks.c:1.35 Thu Nov 26 17:29:34 2009 +++ src/sys/rump/librump/rumpkern/locks.c Tue Dec 1 09:50:51 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: locks.c,v 1.35 2009/11/26 17:29:34 pooka Exp $ */ +/* $NetBSD: locks.c,v 1.36 2009/12/01 09:50:51 pooka Exp $ */ /* * Copyright (c) 2007, 2008 Antti Kantee. All Rights Reserved. @@ -29,7 +29,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: locks.c,v 1.35 2009/11/26 17:29:34 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: locks.c,v 1.36 2009/12/01 09:50:51 pooka Exp $"); #include <sys/param.h> #include <sys/kmem.h> @@ -330,7 +330,7 @@ if (!rumpuser_mutex_tryenter(rump_giantlock)) { struct lwp *l = curlwp; - rump_unschedule_cpu(l); + rump_unschedule_cpu1(l); rumpuser_mutex_enter_nowrap(rump_giantlock); rump_schedule_cpu(l); } @@ -369,6 +369,10 @@ { _kernel_unlock(nlocks, countp); + /* + * XXX: technically we should unschedule_cpu1() here, but that + * requires rump_intr_enter/exit to be implemented. + */ rump_unschedule_cpu(curlwp); } Index: src/sys/rump/librump/rumpkern/rump.c diff -u src/sys/rump/librump/rumpkern/rump.c:1.142 src/sys/rump/librump/rumpkern/rump.c:1.143 --- src/sys/rump/librump/rumpkern/rump.c:1.142 Fri Nov 27 17:55:04 2009 +++ src/sys/rump/librump/rumpkern/rump.c Tue Dec 1 09:50:51 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: rump.c,v 1.142 2009/11/27 17:55:04 pooka Exp $ */ +/* $NetBSD: rump.c,v 1.143 2009/12/01 09:50:51 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -28,7 +28,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.142 2009/11/27 17:55:04 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.143 2009/12/01 09:50:51 pooka Exp $"); #include <sys/param.h> #include <sys/atomic.h> @@ -60,6 +60,7 @@ #include <sys/tty.h> #include <sys/uidinfo.h> #include <sys/vmem.h> +#include <sys/xcall.h> #include <rump/rumpuser.h> @@ -180,6 +181,7 @@ char buf[256]; struct proc *p; struct lwp *l; + int i; int error; /* not reentrant */ @@ -209,6 +211,7 @@ } rumpuser_thrinit(rump_user_schedule, rump_user_unschedule, rump_threads); + rump_intr_init(); /* init minimal lwp/cpu context */ l = &lwp0; @@ -233,6 +236,7 @@ uvm_ra_init(); mutex_obj_init(); + callout_startup(); kprintf_init(); loginit(); @@ -266,9 +270,16 @@ rumpuser_set_curlwp(NULL); rump_schedule(); - callout_startup(); - callout_init_cpu(rump_cpu); - selsysinit(rump_cpu); + /* we are mostly go. do per-cpu subsystem init */ + for (i = 0; i < ncpu; i++) { + struct cpu_info *ci = cpu_lookup(i); + + callout_init_cpu(ci); + softint_init(ci); + xc_init_cpu(ci); + pool_cache_cpu_init(ci); + selsysinit(ci); + } sysctl_init(); kqueue_init(); @@ -277,7 +288,6 @@ percpu_init(); fd_sys_init(); module_init(); - softint_init(rump_cpu); devsw_init(); pipe_init(); Index: src/sys/rump/librump/rumpkern/rump_private.h diff -u src/sys/rump/librump/rumpkern/rump_private.h:1.36 src/sys/rump/librump/rumpkern/rump_private.h:1.37 --- src/sys/rump/librump/rumpkern/rump_private.h:1.36 Thu Nov 26 20:58:51 2009 +++ src/sys/rump/librump/rumpkern/rump_private.h Tue Dec 1 09:50:51 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: rump_private.h,v 1.36 2009/11/26 20:58:51 pooka Exp $ */ +/* $NetBSD: rump_private.h,v 1.37 2009/12/01 09:50:51 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -92,6 +92,7 @@ void rump_unschedule(void); void rump_schedule_cpu(struct lwp *); void rump_unschedule_cpu(struct lwp *); +void rump_unschedule_cpu1(struct lwp *); void rump_user_schedule(int); void rump_user_unschedule(int, int *); @@ -102,6 +103,7 @@ void kernel_unlock_allbutone(int *); void kernel_ununlock_allbutone(int); +void rump_intr_init(void); void rump_softint_run(struct cpu_info *); #endif /* _SYS_RUMP_PRIVATE_H_ */ Index: src/sys/rump/librump/rumpkern/scheduler.c diff -u src/sys/rump/librump/rumpkern/scheduler.c:1.7 src/sys/rump/librump/rumpkern/scheduler.c:1.8 --- src/sys/rump/librump/rumpkern/scheduler.c:1.7 Mon Nov 9 19:16:18 2009 +++ src/sys/rump/librump/rumpkern/scheduler.c Tue Dec 1 09:50:51 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: scheduler.c,v 1.7 2009/11/09 19:16:18 pooka Exp $ */ +/* $NetBSD: scheduler.c,v 1.8 2009/12/01 09:50:51 pooka Exp $ */ /* * Copyright (c) 2009 Antti Kantee. All Rights Reserved. @@ -29,12 +29,13 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: scheduler.c,v 1.7 2009/11/09 19:16:18 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: scheduler.c,v 1.8 2009/12/01 09:50:51 pooka Exp $"); #include <sys/param.h> #include <sys/cpu.h> #include <sys/kmem.h> #include <sys/mutex.h> +#include <sys/namei.h> #include <sys/queue.h> #include <sys/select.h> @@ -43,15 +44,21 @@ #include "rump_private.h" /* should go for MAXCPUS at some point */ -static struct cpu_info rump_cpus[1]; +static struct cpu_info rump_cpus[MAXCPUS]; static struct rumpcpu { struct cpu_info *rcpu_ci; - SLIST_ENTRY(rumpcpu) rcpu_entries; -} rcpu_storage[1]; + int rcpu_flags; + struct rumpuser_cv *rcpu_cv; + LIST_ENTRY(rumpcpu) rcpu_entries; +} rcpu_storage[MAXCPUS]; struct cpu_info *rump_cpu = &rump_cpus[0]; int ncpu = 1; -static SLIST_HEAD(,rumpcpu) cpu_freelist = SLIST_HEAD_INITIALIZER(cpu_freelist); +#define RCPU_WANTED 0x01 /* someone wants this specific CPU */ +#define RCPU_BUSY 0x02 /* CPU is busy */ +#define RCPU_FREELIST 0x04 /* CPU is on freelist */ + +static LIST_HEAD(,rumpcpu) cpu_freelist = LIST_HEAD_INITIALIZER(cpu_freelist); static struct rumpuser_mtx *schedmtx; static struct rumpuser_cv *schedcv, *lwp0cv; @@ -81,7 +88,9 @@ ci->ci_schedstate.spc_mutex = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); rcpu->rcpu_ci = ci; - SLIST_INSERT_HEAD(&cpu_freelist, rcpu, rcpu_entries); + LIST_INSERT_HEAD(&cpu_freelist, rcpu, rcpu_entries); + rcpu->rcpu_flags = RCPU_FREELIST; + rumpuser_cv_init(&rcpu->rcpu_cv); } } @@ -129,12 +138,36 @@ struct rumpcpu *rcpu; rumpuser_mutex_enter_nowrap(schedmtx); - while ((rcpu = SLIST_FIRST(&cpu_freelist)) == NULL) - rumpuser_cv_wait_nowrap(schedcv, schedmtx); - SLIST_REMOVE_HEAD(&cpu_freelist, rcpu_entries); + if (l->l_pflag & LP_BOUND) { + KASSERT(l->l_cpu != NULL); + rcpu = &rcpu_storage[l->l_cpu-&rump_cpus[0]]; + if (rcpu->rcpu_flags & RCPU_BUSY) { + KASSERT((rcpu->rcpu_flags & RCPU_FREELIST) == 0); + while (rcpu->rcpu_flags & RCPU_BUSY) { + rcpu->rcpu_flags |= RCPU_WANTED; + rumpuser_cv_wait_nowrap(rcpu->rcpu_cv, + schedmtx); + } + rcpu->rcpu_flags &= ~RCPU_WANTED; + } else { + KASSERT(rcpu->rcpu_flags & (RCPU_FREELIST|RCPU_WANTED)); + } + if (rcpu->rcpu_flags & RCPU_FREELIST) { + LIST_REMOVE(rcpu, rcpu_entries); + rcpu->rcpu_flags &= ~RCPU_FREELIST; + } + } else { + while ((rcpu = LIST_FIRST(&cpu_freelist)) == NULL) { + rumpuser_cv_wait_nowrap(schedcv, schedmtx); + } + KASSERT(rcpu->rcpu_flags & RCPU_FREELIST); + LIST_REMOVE(rcpu, rcpu_entries); + rcpu->rcpu_flags &= ~RCPU_FREELIST; + KASSERT(l->l_cpu == NULL); + l->l_cpu = rcpu->rcpu_ci; + } + rcpu->rcpu_flags |= RCPU_BUSY; rumpuser_mutex_exit(schedmtx); - KASSERT(l->l_cpu == NULL); - l->l_cpu = rcpu->rcpu_ci; l->l_mutex = rcpu->rcpu_ci->ci_schedstate.spc_mutex; } @@ -178,20 +211,41 @@ void rump_unschedule_cpu(struct lwp *l) { + + if ((l->l_pflag & LP_INTR) == 0) + rump_softint_run(l->l_cpu); + rump_unschedule_cpu1(l); +} + +void +rump_unschedule_cpu1(struct lwp *l) +{ struct rumpcpu *rcpu; struct cpu_info *ci; ci = l->l_cpu; - if ((l->l_pflag & LP_INTR) == 0) - rump_softint_run(ci); - - l->l_cpu = NULL; + if ((l->l_pflag & LP_BOUND) == 0) { + l->l_cpu = NULL; + } rcpu = &rcpu_storage[ci-&rump_cpus[0]]; KASSERT(rcpu->rcpu_ci == ci); + KASSERT(rcpu->rcpu_flags & RCPU_BUSY); rumpuser_mutex_enter_nowrap(schedmtx); - SLIST_INSERT_HEAD(&cpu_freelist, rcpu, rcpu_entries); - rumpuser_cv_signal(schedcv); + if (rcpu->rcpu_flags & RCPU_WANTED) { + /* + * The assumption is that there will usually be max 1 + * thread waiting on the rcpu_cv, so broadcast is fine. + * (and the current structure requires it because of + * only a bitmask being used for wanting). + */ + rumpuser_cv_broadcast(rcpu->rcpu_cv); + } else { + LIST_INSERT_HEAD(&cpu_freelist, rcpu, rcpu_entries); + rcpu->rcpu_flags |= RCPU_FREELIST; + rumpuser_cv_signal(schedcv); + } + rcpu->rcpu_flags &= ~RCPU_BUSY; rumpuser_mutex_exit(schedmtx); } Index: src/sys/rump/librump/rumpkern/threads.c diff -u src/sys/rump/librump/rumpkern/threads.c:1.3 src/sys/rump/librump/rumpkern/threads.c:1.4 --- src/sys/rump/librump/rumpkern/threads.c:1.3 Mon Nov 9 19:02:49 2009 +++ src/sys/rump/librump/rumpkern/threads.c Tue Dec 1 09:50:51 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: threads.c,v 1.3 2009/11/09 19:02:49 pooka Exp $ */ +/* $NetBSD: threads.c,v 1.4 2009/12/01 09:50:51 pooka Exp $ */ /* * Copyright (c) 2007-2009 Antti Kantee. All Rights Reserved. @@ -29,7 +29,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: threads.c,v 1.3 2009/11/09 19:02:49 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: threads.c,v 1.4 2009/12/01 09:50:51 pooka Exp $"); #include <sys/param.h> #include <sys/kmem.h> @@ -122,10 +122,7 @@ } else panic("threads not available, setenv RUMP_THREADS 1"); } - KASSERT(fmt != NULL); - if (ci != NULL) - panic("%s: bounded threads not supported", __func__); k = rumpuser_malloc(sizeof(struct kthdesc), 0); k->f = func; @@ -135,6 +132,10 @@ l->l_pflag |= LP_MPSAFE; if (flags & KTHREAD_INTR) l->l_pflag |= LP_INTR; + if (ci) { + l->l_pflag |= LP_BOUND; + l->l_cpu = ci; + } rv = rumpuser_thread_create(threadbouncer, k, thrname); if (rv) return rv;