mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
sched: fix get_cpu_idle_time() with core scheduling
get_cpu_idle_time() is calling vcpu_runstate_get() for an idle vcpu. With core scheduling active this is fragile, as idle vcpus are assigned to other scheduling units temporarily, and that assignment is changed in some cases without holding the scheduling lock, and vcpu_runstate_get() is using v->sched_unit as parameter for unit_schedule_[un]lock_irq(), resulting in an ASSERT() triggering in unlock in case v->sched_unit has changed meanwhile. Fix that by using a local unit variable holding the correct unit. Signed-off-by: Juergen Gross <jgross@suse.com> Reviewed-by: Dario Faggioli <dfaggioli@suse.com>
This commit is contained in:
1 parent
7ad2164e92
commit
132cbe8f35
1 file changed
+11
-2
+11
-2
@@ -308,17 +308,26 @@ void vcpu_runstate_get(const struct vcpu *v,
|
||||
{
|
||||
spinlock_t *lock;
|
||||
s_time_t delta;
|
||||
struct sched_unit *unit;
|
||||
|
||||
rcu_read_lock(&sched_res_rculock);
|
||||
|
||||
lock = likely(v == current) ? NULL : unit_schedule_lock_irq(v->sched_unit);
|
||||
/*
|
||||
* Be careful in case of an idle vcpu: the assignment to a unit might
|
||||
* change even with the scheduling lock held, so be sure to use the
|
||||
* correct unit for locking in order to avoid triggering an ASSERT() in
|
||||
* the unlock function.
|
||||
*/
|
||||
unit = is_idle_vcpu(v) ? get_sched_res(v->processor)->sched_unit_idle
|
||||
: v->sched_unit;
|
||||
lock = likely(v == current) ? NULL : unit_schedule_lock_irq(unit);
|
||||
memcpy(runstate, &v->runstate, sizeof(*runstate));
|
||||
delta = NOW() - runstate->state_entry_time;
|
||||
if ( delta > 0 )
|
||||
runstate->time[runstate->state] += delta;
|
||||
|
||||
if ( unlikely(lock != NULL) )
|
||||
unit_schedule_unlock_irq(lock, v->sched_unit);
|
||||
unit_schedule_unlock_irq(lock, unit);
|
||||
|
||||
rcu_read_unlock(&sched_res_rculock);
|
||||
}
|
||||
|
||||