@@ -872,14 +872,16 @@ struct sched_entity *__pick_first_entity(struct cfs_rq *cfs_rq)
872
872
*
873
873
* Which allows an EDF like search on (sub)trees.
874
874
*/
875
- static struct sched_entity * pick_eevdf (struct cfs_rq * cfs_rq )
875
+ static struct sched_entity * __pick_eevdf (struct cfs_rq * cfs_rq )
876
876
{
877
877
struct rb_node * node = cfs_rq -> tasks_timeline .rb_root .rb_node ;
878
878
struct sched_entity * curr = cfs_rq -> curr ;
879
879
struct sched_entity * best = NULL ;
880
+ struct sched_entity * best_left = NULL ;
880
881
881
882
if (curr && (!curr -> on_rq || !entity_eligible (cfs_rq , curr )))
882
883
curr = NULL ;
884
+ best = curr ;
883
885
884
886
/*
885
887
* Once selected, run a task until it either becomes non-eligible or
@@ -900,41 +902,83 @@ static struct sched_entity *pick_eevdf(struct cfs_rq *cfs_rq)
900
902
}
901
903
902
904
/*
903
- * If this entity has an earlier deadline than the previous
904
- * best, take this one. If it also has the earliest deadline
905
- * of its subtree, we're done.
905
+ * Now we heap search eligible trees for the best (min_)deadline
906
906
*/
907
- if (!best || deadline_gt (deadline , best , se )) {
907
+ if (!best || deadline_gt (deadline , best , se ))
908
908
best = se ;
909
- if (best -> deadline == best -> min_deadline )
910
- break ;
911
- }
912
909
913
910
/*
914
- * If the earlest deadline in this subtree is in the fully
915
- * eligible left half of our space, go there.
911
+ * Every se in a left branch is eligible, keep track of the
912
+ * branch with the best min_deadline
916
913
*/
914
+ if (node -> rb_left ) {
915
+ struct sched_entity * left = __node_2_se (node -> rb_left );
916
+
917
+ if (!best_left || deadline_gt (min_deadline , best_left , left ))
918
+ best_left = left ;
919
+
920
+ /*
921
+ * min_deadline is in the left branch. rb_left and all
922
+ * descendants are eligible, so immediately switch to the second
923
+ * loop.
924
+ */
925
+ if (left -> min_deadline == se -> min_deadline )
926
+ break ;
927
+ }
928
+
929
+ /* min_deadline is at this node, no need to look right */
930
+ if (se -> deadline == se -> min_deadline )
931
+ break ;
932
+
933
+ /* else min_deadline is in the right branch. */
934
+ node = node -> rb_right ;
935
+ }
936
+
937
+ /*
938
+ * We ran into an eligible node which is itself the best.
939
+ * (Or nr_running == 0 and both are NULL)
940
+ */
941
+ if (!best_left || (s64 )(best_left -> min_deadline - best -> deadline ) > 0 )
942
+ return best ;
943
+
944
+ /*
945
+ * Now best_left and all of its children are eligible, and we are just
946
+ * looking for deadline == min_deadline
947
+ */
948
+ node = & best_left -> run_node ;
949
+ while (node ) {
950
+ struct sched_entity * se = __node_2_se (node );
951
+
952
+ /* min_deadline is the current node */
953
+ if (se -> deadline == se -> min_deadline )
954
+ return se ;
955
+
956
+ /* min_deadline is in the left branch */
917
957
if (node -> rb_left &&
918
958
__node_2_se (node -> rb_left )-> min_deadline == se -> min_deadline ) {
919
959
node = node -> rb_left ;
920
960
continue ;
921
961
}
922
962
963
+ /* else min_deadline is in the right branch */
923
964
node = node -> rb_right ;
924
965
}
966
+ return NULL ;
967
+ }
925
968
926
- if (!best || (curr && deadline_gt (deadline , best , curr )))
927
- best = curr ;
969
+ static struct sched_entity * pick_eevdf (struct cfs_rq * cfs_rq )
970
+ {
971
+ struct sched_entity * se = __pick_eevdf (cfs_rq );
928
972
929
- if (unlikely (! best ) ) {
973
+ if (! se ) {
930
974
struct sched_entity * left = __pick_first_entity (cfs_rq );
931
975
if (left ) {
932
976
pr_err ("EEVDF scheduling fail, picking leftmost\n" );
933
977
return left ;
934
978
}
935
979
}
936
980
937
- return best ;
981
+ return se ;
938
982
}
939
983
940
984
#ifdef CONFIG_SCHED_DEBUG
@@ -3613,6 +3657,7 @@ static void reweight_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
3613
3657
*/
3614
3658
deadline = div_s64 (deadline * old_weight , weight );
3615
3659
se -> deadline = se -> vruntime + deadline ;
3660
+ min_deadline_cb_propagate (& se -> run_node , NULL );
3616
3661
}
3617
3662
3618
3663
#ifdef CONFIG_SMP
0 commit comments