@@ -872,14 +872,16 @@ struct sched_entity *__pick_first_entity(struct cfs_rq *cfs_rq)
872872 *
873873 * Which allows an EDF like search on (sub)trees.
874874 */
875- static struct sched_entity * pick_eevdf (struct cfs_rq * cfs_rq )
875+ static struct sched_entity * __pick_eevdf (struct cfs_rq * cfs_rq )
876876{
877877 struct rb_node * node = cfs_rq -> tasks_timeline .rb_root .rb_node ;
878878 struct sched_entity * curr = cfs_rq -> curr ;
879879 struct sched_entity * best = NULL ;
880+ struct sched_entity * best_left = NULL ;
880881
881882 if (curr && (!curr -> on_rq || !entity_eligible (cfs_rq , curr )))
882883 curr = NULL ;
884+ best = curr ;
883885
884886 /*
885887 * 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)
900902 }
901903
902904 /*
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
906906 */
907- if (!best || deadline_gt (deadline , best , se )) {
907+ if (!best || deadline_gt (deadline , best , se ))
908908 best = se ;
909- if (best -> deadline == best -> min_deadline )
910- break ;
911- }
912909
913910 /*
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
916913 */
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 */
917957 if (node -> rb_left &&
918958 __node_2_se (node -> rb_left )-> min_deadline == se -> min_deadline ) {
919959 node = node -> rb_left ;
920960 continue ;
921961 }
922962
963+ /* else min_deadline is in the right branch */
923964 node = node -> rb_right ;
924965 }
966+ return NULL ;
967+ }
925968
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 );
928972
929- if (unlikely (! best ) ) {
973+ if (! se ) {
930974 struct sched_entity * left = __pick_first_entity (cfs_rq );
931975 if (left ) {
932976 pr_err ("EEVDF scheduling fail, picking leftmost\n" );
933977 return left ;
934978 }
935979 }
936980
937- return best ;
981+ return se ;
938982}
939983
940984#ifdef CONFIG_SCHED_DEBUG
@@ -3613,6 +3657,7 @@ static void reweight_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
36133657 */
36143658 deadline = div_s64 (deadline * old_weight , weight );
36153659 se -> deadline = se -> vruntime + deadline ;
3660+ min_deadline_cb_propagate (& se -> run_node , NULL );
36163661 }
36173662
36183663#ifdef CONFIG_SMP
0 commit comments