From d87af38ca063b9782ed8e05a68691890f58d489c Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Fri, 2 Aug 2013 10:46:40 -0700 Subject: [PATCH] kernel - Fix panic when usched is used to force a cpu w/the dfly scheduler * Fix a panic for 'usched dfly:0x1 sh', or other similar cpu forcing mechanic. * The scheduler was not being notified of the forced migration which caused it to assert on a sanity check later on. Add the needed infrastructure. Reported-by: vsrinivas --- sys/kern/usched_bsd4.c | 10 +++++++++- sys/kern/usched_dfly.c | 28 +++++++++++++++++++++++++++- sys/kern/usched_dummy.c | 10 +++++++++- sys/sys/usched.h | 1 + 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/sys/kern/usched_bsd4.c b/sys/kern/usched_bsd4.c index 1ea8afcf79..625050bce2 100644 --- a/sys/kern/usched_bsd4.c +++ b/sys/kern/usched_bsd4.c @@ -108,6 +108,7 @@ static void bsd4_kick_helper(struct lwp *lp); static struct lwp *bsd4_chooseproc_locked(struct lwp *chklp); static void bsd4_remrunqueue_locked(struct lwp *lp); static void bsd4_setrunqueue_locked(struct lwp *lp); +static void bsd4_changedcpu(struct lwp *lp); struct usched usched_bsd4 = { { NULL }, @@ -124,7 +125,8 @@ struct usched usched_bsd4 = { bsd4_exiting, bsd4_uload_update, NULL, /* setcpumask not supported */ - bsd4_yield + bsd4_yield, + bsd4_changedcpu }; struct usched_bsd4_pcpu { @@ -1209,6 +1211,12 @@ bsd4_yield(struct lwp *lp) need_user_resched(); } +static +void +bsd4_changedcpu(struct lwp *lp __unused) +{ +} + /* * Called from fork1() when a new child process is being created. * diff --git a/sys/kern/usched_dfly.c b/sys/kern/usched_dfly.c index e8cba632fb..32a7511445 100644 --- a/sys/kern/usched_dfly.c +++ b/sys/kern/usched_dfly.c @@ -144,6 +144,7 @@ static struct lwp *dfly_chooseproc_locked(dfly_pcpu_t rdd, dfly_pcpu_t dd, struct lwp *chklp, int worst); static void dfly_remrunqueue_locked(dfly_pcpu_t dd, struct lwp *lp); static void dfly_setrunqueue_locked(dfly_pcpu_t dd, struct lwp *lp); +static void dfly_changedcpu(struct lwp *lp); struct usched usched_dfly = { { NULL }, @@ -160,7 +161,8 @@ struct usched usched_dfly = { dfly_exiting, dfly_uload_update, NULL, /* setcpumask not supported */ - dfly_yield + dfly_yield, + dfly_changedcpu }; /* @@ -1135,6 +1137,30 @@ dfly_yield(struct lwp *lp) need_user_resched(); } +/* + * Thread was forcefully migrated to another cpu. Normally forced migrations + * are used for iterations and the kernel returns to the original cpu before + * returning and this is not needed. However, if the kernel migrates a + * thread to another cpu and wants to leave it there, it has to call this + * scheduler helper. + * + * Note that the lwkt_migratecpu() function also released the thread, so + * we don't have to worry about that. + */ +static +void +dfly_changedcpu(struct lwp *lp) +{ + dfly_pcpu_t dd = &dfly_pcpu[lp->lwp_qcpu]; + dfly_pcpu_t rdd = &dfly_pcpu[mycpu->gd_cpuid]; + + if (dd != rdd) { + spin_lock(&dd->spin); + dfly_changeqcpu_locked(lp, dd, rdd); + spin_unlock(&dd->spin); + } +} + /* * Called from fork1() when a new child process is being created. * diff --git a/sys/kern/usched_dummy.c b/sys/kern/usched_dummy.c index 85413748cd..919e27a0a9 100644 --- a/sys/kern/usched_dummy.c +++ b/sys/kern/usched_dummy.c @@ -72,6 +72,7 @@ static void dummy_forking(struct lwp *plp, struct lwp *lp); static void dummy_exiting(struct lwp *plp, struct proc *child); static void dummy_uload_update(struct lwp *lp); static void dummy_yield(struct lwp *lp); +static void dummy_changedcpu(struct lwp *lp); struct usched usched_dummy = { { NULL }, @@ -88,7 +89,8 @@ struct usched usched_dummy = { dummy_exiting, dummy_uload_update, NULL, /* setcpumask not supported */ - dummy_yield + dummy_yield, + dummy_changedcpu }; struct usched_dummy_pcpu { @@ -366,6 +368,12 @@ dummy_yield(struct lwp *lp) need_user_resched(); } +static +void +dummy_changedcpu(struct lwp *lp __unused) +{ +} + /* * DUMMY_RESETPRIORITY * diff --git a/sys/sys/usched.h b/sys/sys/usched.h index 664b85f8c6..6285e62713 100644 --- a/sys/sys/usched.h +++ b/sys/sys/usched.h @@ -44,6 +44,7 @@ struct usched { void (*uload_update)(struct lwp *); void (*setcpumask)(struct usched *, cpumask_t); void (*yield)(struct lwp *); + void (*changedcpu)(struct lwp *); }; union usched_data { -- 2.41.0