Two EEVDF fixes.
Signed-off-by: Ingo Molnar <mingo@kernel.org> -----BEGIN PGP SIGNATURE----- iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAmUrDzARHG1pbmdvQGtl cm5lbC5vcmcACgkQEnMQ0APhK1hJuQ//cumay4Bv4IK6NoVgLSECYmXNTWuK/83y siHkiuyoH39Ikm8HNSJKJVcWv2KNiCFJPBtQ/aEVzIMrBDtPZnYDmU9DNTpB1e8b BN+72jiZ4RSsySyG0Nkr6XC6eAeNpvhW1BgcjjoTIodvycGiaTrHopEvQX/BefWa OCZZYElBsPTtK30IlUKN0TUxTEZuWdVaIihbmu9fAVa5gYvlCtOmFwwSC54SQjDG uusKyxiLrkvR+zXzLyRYiXYIb147/OnXRWAiVmM7jfk/SnUFq9IeWU08iDNYU++d K5cw/vedBP3mwo0sgybrRDqyxFrdpbU2o08cX2yj2FTIJDf2zW+KQGoyQyqcrnEk 1coYnMu3+OdZBNfq6OY6mwwk2aRsJwR3BhOmMBpTPN9NYWKrsq0UWBISk/X+8iJU KoL7wSSrODQa973ElSvc4s5beyNVxYykjO7cLZGsFFuOIxDLS8PTXGL4C+jlizk3 vbuINtVtKNf5Zl0sjukEWZhCcp/bftakyRfTMCsRFqoQGpLlc++TRVuQt5uvxis4 u7flazmP4JfQyTsmN4QKxOnBy1AJA5LlEnv4yrII5dPj4Smf/1TPUo7j6Mbfu0Ai pvpkG5SjjTjfL94qABSz88O4bBzZFHDlZ4MhJuyWkN5PFBi2xtfAf7sSrVOQnIb1 IvjOLAlTJlQ= =Raax -----END PGP SIGNATURE----- Merge tag 'sched-urgent-2023-10-14' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull scheduler fixes from Ingo Molnar: "Two EEVDF fixes" * tag 'sched-urgent-2023-10-14' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: sched/eevdf: Fix pick_eevdf() sched/eevdf: Fix min_deadline heap integrity
This commit is contained in:
commit
42578c7bf6
@ -872,14 +872,16 @@ struct sched_entity *__pick_first_entity(struct cfs_rq *cfs_rq)
|
||||
*
|
||||
* Which allows an EDF like search on (sub)trees.
|
||||
*/
|
||||
static struct sched_entity *pick_eevdf(struct cfs_rq *cfs_rq)
|
||||
static struct sched_entity *__pick_eevdf(struct cfs_rq *cfs_rq)
|
||||
{
|
||||
struct rb_node *node = cfs_rq->tasks_timeline.rb_root.rb_node;
|
||||
struct sched_entity *curr = cfs_rq->curr;
|
||||
struct sched_entity *best = NULL;
|
||||
struct sched_entity *best_left = NULL;
|
||||
|
||||
if (curr && (!curr->on_rq || !entity_eligible(cfs_rq, curr)))
|
||||
curr = NULL;
|
||||
best = curr;
|
||||
|
||||
/*
|
||||
* Once selected, run a task until it either becomes non-eligible or
|
||||
@ -900,33 +902,75 @@ static struct sched_entity *pick_eevdf(struct cfs_rq *cfs_rq)
|
||||
}
|
||||
|
||||
/*
|
||||
* If this entity has an earlier deadline than the previous
|
||||
* best, take this one. If it also has the earliest deadline
|
||||
* of its subtree, we're done.
|
||||
* Now we heap search eligible trees for the best (min_)deadline
|
||||
*/
|
||||
if (!best || deadline_gt(deadline, best, se)) {
|
||||
if (!best || deadline_gt(deadline, best, se))
|
||||
best = se;
|
||||
if (best->deadline == best->min_deadline)
|
||||
|
||||
/*
|
||||
* Every se in a left branch is eligible, keep track of the
|
||||
* branch with the best min_deadline
|
||||
*/
|
||||
if (node->rb_left) {
|
||||
struct sched_entity *left = __node_2_se(node->rb_left);
|
||||
|
||||
if (!best_left || deadline_gt(min_deadline, best_left, left))
|
||||
best_left = left;
|
||||
|
||||
/*
|
||||
* min_deadline is in the left branch. rb_left and all
|
||||
* descendants are eligible, so immediately switch to the second
|
||||
* loop.
|
||||
*/
|
||||
if (left->min_deadline == se->min_deadline)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the earlest deadline in this subtree is in the fully
|
||||
* eligible left half of our space, go there.
|
||||
*/
|
||||
/* min_deadline is at this node, no need to look right */
|
||||
if (se->deadline == se->min_deadline)
|
||||
break;
|
||||
|
||||
/* else min_deadline is in the right branch. */
|
||||
node = node->rb_right;
|
||||
}
|
||||
|
||||
/*
|
||||
* We ran into an eligible node which is itself the best.
|
||||
* (Or nr_running == 0 and both are NULL)
|
||||
*/
|
||||
if (!best_left || (s64)(best_left->min_deadline - best->deadline) > 0)
|
||||
return best;
|
||||
|
||||
/*
|
||||
* Now best_left and all of its children are eligible, and we are just
|
||||
* looking for deadline == min_deadline
|
||||
*/
|
||||
node = &best_left->run_node;
|
||||
while (node) {
|
||||
struct sched_entity *se = __node_2_se(node);
|
||||
|
||||
/* min_deadline is the current node */
|
||||
if (se->deadline == se->min_deadline)
|
||||
return se;
|
||||
|
||||
/* min_deadline is in the left branch */
|
||||
if (node->rb_left &&
|
||||
__node_2_se(node->rb_left)->min_deadline == se->min_deadline) {
|
||||
node = node->rb_left;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* else min_deadline is in the right branch */
|
||||
node = node->rb_right;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!best || (curr && deadline_gt(deadline, best, curr)))
|
||||
best = curr;
|
||||
static struct sched_entity *pick_eevdf(struct cfs_rq *cfs_rq)
|
||||
{
|
||||
struct sched_entity *se = __pick_eevdf(cfs_rq);
|
||||
|
||||
if (unlikely(!best)) {
|
||||
if (!se) {
|
||||
struct sched_entity *left = __pick_first_entity(cfs_rq);
|
||||
if (left) {
|
||||
pr_err("EEVDF scheduling fail, picking leftmost\n");
|
||||
@ -934,7 +978,7 @@ static struct sched_entity *pick_eevdf(struct cfs_rq *cfs_rq)
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
return se;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCHED_DEBUG
|
||||
@ -3613,6 +3657,7 @@ static void reweight_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
|
||||
*/
|
||||
deadline = div_s64(deadline * old_weight, weight);
|
||||
se->deadline = se->vruntime + deadline;
|
||||
min_deadline_cb_propagate(&se->run_node, NULL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
Loading…
Reference in New Issue
Block a user