Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+59 -14
+59 -14
kernel/sched/fair.c
··· 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 ··· 902 900 } 903 901 904 902 /* 905 - * If this entity has an earlier deadline than the previous 906 - * best, take this one. If it also has the earliest deadline 907 - * of its subtree, we're done. 903 + * Now we heap search eligible trees for the best (min_)deadline 908 904 */ 909 - if (!best || deadline_gt(deadline, best, se)) { 905 + if (!best || deadline_gt(deadline, best, se)) 910 906 best = se; 911 - if (best->deadline == best->min_deadline) 907 + 908 + /* 909 + * Every se in a left branch is eligible, keep track of the 910 + * branch with the best min_deadline 911 + */ 912 + if (node->rb_left) { 913 + struct sched_entity *left = __node_2_se(node->rb_left); 914 + 915 + if (!best_left || deadline_gt(min_deadline, best_left, left)) 916 + best_left = left; 917 + 918 + /* 919 + * min_deadline is in the left branch. rb_left and all 920 + * descendants are eligible, so immediately switch to the second 921 + * loop. 922 + */ 923 + if (left->min_deadline == se->min_deadline) 912 924 break; 913 925 } 914 926 915 - /* 916 - * If the earlest deadline in this subtree is in the fully 917 - * eligible left half of our space, go there. 918 - */ 927 + /* min_deadline is at this node, no need to look right */ 928 + if (se->deadline == se->min_deadline) 929 + break; 930 + 931 + /* else min_deadline is in the right branch. */ 932 + node = node->rb_right; 933 + } 934 + 935 + /* 936 + * We ran into an eligible node which is itself the best. 937 + * (Or nr_running == 0 and both are NULL) 938 + */ 939 + if (!best_left || (s64)(best_left->min_deadline - best->deadline) > 0) 940 + return best; 941 + 942 + /* 943 + * Now best_left and all of its children are eligible, and we are just 944 + * looking for deadline == min_deadline 945 + */ 946 + node = &best_left->run_node; 947 + while (node) { 948 + struct sched_entity *se = __node_2_se(node); 949 + 950 + /* min_deadline is the current node */ 951 + if (se->deadline == se->min_deadline) 952 + return se; 953 + 954 + /* min_deadline is in the left branch */ 919 955 if (node->rb_left && 920 956 __node_2_se(node->rb_left)->min_deadline == se->min_deadline) { 921 957 node = node->rb_left; 922 958 continue; 923 959 } 924 960 961 + /* else min_deadline is in the right branch */ 925 962 node = node->rb_right; 926 963 } 964 + return NULL; 965 + } 927 966 928 - if (!best || (curr && deadline_gt(deadline, best, curr))) 929 - best = curr; 967 + static struct sched_entity *pick_eevdf(struct cfs_rq *cfs_rq) 968 + { 969 + struct sched_entity *se = __pick_eevdf(cfs_rq); 930 970 931 - if (unlikely(!best)) { 971 + if (!se) { 932 972 struct sched_entity *left = __pick_first_entity(cfs_rq); 933 973 if (left) { 934 974 pr_err("EEVDF scheduling fail, picking leftmost\n"); ··· 978 934 } 979 935 } 980 936 981 - return best; 937 + return se; 982 938 } 983 939 984 940 #ifdef CONFIG_SCHED_DEBUG ··· 3657 3613 */ 3658 3614 deadline = div_s64(deadline * old_weight, weight); 3659 3615 se->deadline = se->vruntime + deadline; 3616 + min_deadline_cb_propagate(&se->run_node, NULL); 3660 3617 } 3661 3618 3662 3619 #ifdef CONFIG_SMP