diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 1fe40de6ebe3..1754d9f95f2c 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -11327,17 +11327,16 @@ void sched_change_end(struct sched_change_ctx *ctx) if (p->sched_class->switched_to) p->sched_class->switched_to(rq, p); + /* + * Check if the task can preempt the current in case the class + * was upgraded. Note that none of the switch*_from() methods + * know the new class and none of the switch*_to() methods know + * the old class so we must resched here. + */ + if (ctx->queued) + wakeup_preempt(rq, p, 0); + if (ctx->running) { - /* - * If this was a class promotion; let the old class - * know it got preempted. Note that none of the - * switch*_from() methods know the new class and none - * of the switch*_to() methods know the old class. - */ - if (sched_class_above(p->sched_class, ctx->class)) { - rq->next_class->wakeup_preempt(rq, p, 0); - rq->next_class = p->sched_class; - } /* * If this was a degradation in class; make sure to * reschedule. diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 57360f5cdde4..0f2364479f9d 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -6463,12 +6463,20 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags) load = cfs_rq->sum_weight; if (curr && curr->on_rq) load += avg_vruntime_weight(cfs_rq, curr->h_load.weight); - - weight = avg_vruntime_weight(cfs_rq, se->h_load.weight); - lag *= load + weight; if (WARN_ON_ONCE(!load)) load = 1; - lag = div64_long(lag, load); + + weight = avg_vruntime_weight(cfs_rq, se->h_load.weight); + + /* + * Rewrite, because the product (W + w_i)*vl'_i might + * overflow s64: + * + * vl_i = (W + w_i)*vl'_i / W + * = (W*vl'_i + w_i*vl'_i) / W + * = vl'_i + w_i*vl'_i/W + */ + lag += div64_long(lag * weight, load); /* * A heavy entity (relative to the tree) will pull the