aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir@xen.org>2011-04-27 13:38:08 +0100
committerKeir Fraser <keir@xen.org>2011-04-27 13:38:08 +0100
commit781b1e5b94446177c921e9ccdbb3b40b6653a3be (patch)
tree6baee3d6dd3a6c2b82b0edf444f2dfc278487d5c
parentc29e5e238d687d8aa1b7ce1cc36303397dcb2f86 (diff)
downloadxen-781b1e5b94446177c921e9ccdbb3b40b6653a3be.tar.gz
xen-781b1e5b94446177c921e9ccdbb3b40b6653a3be.tar.bz2
xen-781b1e5b94446177c921e9ccdbb3b40b6653a3be.zip
credit2: add a callback to migrate to a new cpu
In credit2, there needs to be a strong correlation between v->processor and the runqueue to which a vcpu is assigned; much of the code relies on this invariant. Allow credit2 to manage the actual migration itself. This fixes the most recent credit2 bug reported on the list (Xen BUG at sched_credit2.c:1606) in Xen 4.1, as well as the bug at sched_credit2.c:811 in -unstable (which catches the same condition earlier). Signed-off-by: George Dunlap <george.dunlap@eu.citrix.com> xen-unstable changeset: 23250:7745109e3c6e xen-unstable date: Wed Apr 27 13:36:15 2011 +0100
-rw-r--r--xen/common/sched_credit2.c36
-rw-r--r--xen/common/schedule.c6
-rw-r--r--xen/include/xen/sched-if.h2
3 files changed, 24 insertions, 20 deletions
diff --git a/xen/common/sched_credit2.c b/xen/common/sched_credit2.c
index 9924b09244..aed1d44840 100644
--- a/xen/common/sched_credit2.c
+++ b/xen/common/sched_credit2.c
@@ -1351,32 +1351,29 @@ out:
static int
csched_cpu_pick(const struct scheduler *ops, struct vcpu *vc)
{
- struct csched_vcpu * const svc = CSCHED_VCPU(vc);
int new_cpu;
- /* The scheduler interface doesn't have an explicit mechanism to
- * involve the choosable scheduler in the migrate process, so we
- * infer that a change may happen by the call to cpu_pick, and
- * remove it from the old runqueue while the lock for the old
- * runqueue is held. It can't be actively waiting to run. It
- * will be added to the new runqueue when it next wakes.
- *
- * If we want to be able to call pick() separately, we need to add
- * a mechansim to remove a vcpu from an old processor / runqueue
- * before releasing the lock. */
- BUG_ON(__vcpu_on_runq(svc));
-
new_cpu = choose_cpu(ops, vc);
- /* If we're suggesting moving to a different runqueue, remove it
- * from the old runqueue while we have the lock. It will be added
- * to the new one when it wakes. */
- if ( svc->rqd != NULL
- && RQD(ops, new_cpu) != svc->rqd )
- runq_deassign(ops, vc);
return new_cpu;
}
+static void
+csched_vcpu_migrate(
+ const struct scheduler *ops, struct vcpu *vc, unsigned int new_cpu)
+{
+ struct csched_vcpu * const svc = CSCHED_VCPU(vc);
+ struct csched_runqueue_data *trqd;
+
+ /* Check if new_cpu is valid */
+ BUG_ON(!cpu_isset(new_cpu, CSCHED_PRIV(ops)->initialized));
+
+ trqd = RQD(ops, new_cpu);
+
+ if ( trqd != svc->rqd )
+ migrate(ops, svc, trqd, NOW());
+}
+
static int
csched_dom_cntl(
const struct scheduler *ops,
@@ -2089,6 +2086,7 @@ const struct scheduler sched_credit2_def = {
.adjust = csched_dom_cntl,
.pick_cpu = csched_cpu_pick,
+ .migrate = csched_vcpu_migrate,
.do_schedule = csched_schedule,
.context_saved = csched_context_saved,
diff --git a/xen/common/schedule.c b/xen/common/schedule.c
index 129abe44e4..53a1353b47 100644
--- a/xen/common/schedule.c
+++ b/xen/common/schedule.c
@@ -490,7 +490,11 @@ static void vcpu_migrate(struct vcpu *v)
* Switch to new CPU, then unlock new and old CPU. This is safe because
* the lock pointer cant' change while the current lock is held.
*/
- v->processor = new_cpu;
+ if ( VCPU2OP(v)->migrate )
+ SCHED_OP(VCPU2OP(v), migrate, v, new_cpu);
+ else
+ v->processor = new_cpu;
+
if ( old_lock != new_lock )
spin_unlock(new_lock);
diff --git a/xen/include/xen/sched-if.h b/xen/include/xen/sched-if.h
index e8f0262a6b..702910b1b2 100644
--- a/xen/include/xen/sched-if.h
+++ b/xen/include/xen/sched-if.h
@@ -168,6 +168,8 @@ struct scheduler {
bool_t tasklet_work_scheduled);
int (*pick_cpu) (const struct scheduler *, struct vcpu *);
+ void (*migrate) (const struct scheduler *, struct vcpu *,
+ unsigned int);
int (*adjust) (const struct scheduler *, struct domain *,
struct xen_domctl_scheduler_op *);
int (*adjust_global) (const struct scheduler *,