@@ -689,21 +689,16 @@ u64 avg_vruntime(struct cfs_rq *cfs_rq)
689
689
*
690
690
* XXX could add max_slice to the augmented data to track this.
691
691
*/
692
- static s64 entity_lag ( u64 avruntime , struct sched_entity * se )
692
+ static void update_entity_lag ( struct cfs_rq * cfs_rq , struct sched_entity * se )
693
693
{
694
694
s64 vlag , limit ;
695
695
696
- vlag = avruntime - se -> vruntime ;
697
- limit = calc_delta_fair (max_t (u64 , 2 * se -> slice , TICK_NSEC ), se );
698
-
699
- return clamp (vlag , - limit , limit );
700
- }
701
-
702
- static void update_entity_lag (struct cfs_rq * cfs_rq , struct sched_entity * se )
703
- {
704
696
SCHED_WARN_ON (!se -> on_rq );
705
697
706
- se -> vlag = entity_lag (avg_vruntime (cfs_rq ), se );
698
+ vlag = avg_vruntime (cfs_rq ) - se -> vruntime ;
699
+ limit = calc_delta_fair (max_t (u64 , 2 * se -> slice , TICK_NSEC ), se );
700
+
701
+ se -> vlag = clamp (vlag , - limit , limit );
707
702
}
708
703
709
704
/*
@@ -3774,137 +3769,32 @@ static inline void
3774
3769
dequeue_load_avg (struct cfs_rq * cfs_rq , struct sched_entity * se ) { }
3775
3770
#endif
3776
3771
3777
- static void reweight_eevdf (struct sched_entity * se , u64 avruntime ,
3778
- unsigned long weight )
3779
- {
3780
- unsigned long old_weight = se -> load .weight ;
3781
- s64 vlag , vslice ;
3782
-
3783
- /*
3784
- * VRUNTIME
3785
- * --------
3786
- *
3787
- * COROLLARY #1: The virtual runtime of the entity needs to be
3788
- * adjusted if re-weight at !0-lag point.
3789
- *
3790
- * Proof: For contradiction assume this is not true, so we can
3791
- * re-weight without changing vruntime at !0-lag point.
3792
- *
3793
- * Weight VRuntime Avg-VRuntime
3794
- * before w v V
3795
- * after w' v' V'
3796
- *
3797
- * Since lag needs to be preserved through re-weight:
3798
- *
3799
- * lag = (V - v)*w = (V'- v')*w', where v = v'
3800
- * ==> V' = (V - v)*w/w' + v (1)
3801
- *
3802
- * Let W be the total weight of the entities before reweight,
3803
- * since V' is the new weighted average of entities:
3804
- *
3805
- * V' = (WV + w'v - wv) / (W + w' - w) (2)
3806
- *
3807
- * by using (1) & (2) we obtain:
3808
- *
3809
- * (WV + w'v - wv) / (W + w' - w) = (V - v)*w/w' + v
3810
- * ==> (WV-Wv+Wv+w'v-wv)/(W+w'-w) = (V - v)*w/w' + v
3811
- * ==> (WV - Wv)/(W + w' - w) + v = (V - v)*w/w' + v
3812
- * ==> (V - v)*W/(W + w' - w) = (V - v)*w/w' (3)
3813
- *
3814
- * Since we are doing at !0-lag point which means V != v, we
3815
- * can simplify (3):
3816
- *
3817
- * ==> W / (W + w' - w) = w / w'
3818
- * ==> Ww' = Ww + ww' - ww
3819
- * ==> W * (w' - w) = w * (w' - w)
3820
- * ==> W = w (re-weight indicates w' != w)
3821
- *
3822
- * So the cfs_rq contains only one entity, hence vruntime of
3823
- * the entity @v should always equal to the cfs_rq's weighted
3824
- * average vruntime @V, which means we will always re-weight
3825
- * at 0-lag point, thus breach assumption. Proof completed.
3826
- *
3827
- *
3828
- * COROLLARY #2: Re-weight does NOT affect weighted average
3829
- * vruntime of all the entities.
3830
- *
3831
- * Proof: According to corollary #1, Eq. (1) should be:
3832
- *
3833
- * (V - v)*w = (V' - v')*w'
3834
- * ==> v' = V' - (V - v)*w/w' (4)
3835
- *
3836
- * According to the weighted average formula, we have:
3837
- *
3838
- * V' = (WV - wv + w'v') / (W - w + w')
3839
- * = (WV - wv + w'(V' - (V - v)w/w')) / (W - w + w')
3840
- * = (WV - wv + w'V' - Vw + wv) / (W - w + w')
3841
- * = (WV + w'V' - Vw) / (W - w + w')
3842
- *
3843
- * ==> V'*(W - w + w') = WV + w'V' - Vw
3844
- * ==> V' * (W - w) = (W - w) * V (5)
3845
- *
3846
- * If the entity is the only one in the cfs_rq, then reweight
3847
- * always occurs at 0-lag point, so V won't change. Or else
3848
- * there are other entities, hence W != w, then Eq. (5) turns
3849
- * into V' = V. So V won't change in either case, proof done.
3850
- *
3851
- *
3852
- * So according to corollary #1 & #2, the effect of re-weight
3853
- * on vruntime should be:
3854
- *
3855
- * v' = V' - (V - v) * w / w' (4)
3856
- * = V - (V - v) * w / w'
3857
- * = V - vl * w / w'
3858
- * = V - vl'
3859
- */
3860
- if (avruntime != se -> vruntime ) {
3861
- vlag = entity_lag (avruntime , se );
3862
- vlag = div_s64 (vlag * old_weight , weight );
3863
- se -> vruntime = avruntime - vlag ;
3864
- }
3865
-
3866
- /*
3867
- * DEADLINE
3868
- * --------
3869
- *
3870
- * When the weight changes, the virtual time slope changes and
3871
- * we should adjust the relative virtual deadline accordingly.
3872
- *
3873
- * d' = v' + (d - v)*w/w'
3874
- * = V' - (V - v)*w/w' + (d - v)*w/w'
3875
- * = V - (V - v)*w/w' + (d - v)*w/w'
3876
- * = V + (d - V)*w/w'
3877
- */
3878
- vslice = (s64 )(se -> deadline - avruntime );
3879
- vslice = div_s64 (vslice * old_weight , weight );
3880
- se -> deadline = avruntime + vslice ;
3881
- }
3772
+ static void place_entity (struct cfs_rq * cfs_rq , struct sched_entity * se , int flags );
3882
3773
3883
3774
static void reweight_entity (struct cfs_rq * cfs_rq , struct sched_entity * se ,
3884
3775
unsigned long weight )
3885
3776
{
3886
3777
bool curr = cfs_rq -> curr == se ;
3887
- u64 avruntime ;
3888
3778
3889
3779
if (se -> on_rq ) {
3890
3780
/* commit outstanding execution time */
3891
3781
update_curr (cfs_rq );
3892
- avruntime = avg_vruntime (cfs_rq );
3782
+ update_entity_lag (cfs_rq , se );
3783
+ se -> deadline -= se -> vruntime ;
3784
+ se -> rel_deadline = 1 ;
3893
3785
if (!curr )
3894
3786
__dequeue_entity (cfs_rq , se );
3895
3787
update_load_sub (& cfs_rq -> load , se -> load .weight );
3896
3788
}
3897
3789
dequeue_load_avg (cfs_rq , se );
3898
3790
3899
- if (se -> on_rq ) {
3900
- reweight_eevdf (se , avruntime , weight );
3901
- } else {
3902
- /*
3903
- * Because we keep se->vlag = V - v_i, while: lag_i = w_i*(V - v_i),
3904
- * we need to scale se->vlag when w_i changes.
3905
- */
3906
- se -> vlag = div_s64 (se -> vlag * se -> load .weight , weight );
3907
- }
3791
+ /*
3792
+ * Because we keep se->vlag = V - v_i, while: lag_i = w_i*(V - v_i),
3793
+ * we need to scale se->vlag when w_i changes.
3794
+ */
3795
+ se -> vlag = div_s64 (se -> vlag * se -> load .weight , weight );
3796
+ if (se -> rel_deadline )
3797
+ se -> deadline = div_s64 (se -> deadline * se -> load .weight , weight );
3908
3798
3909
3799
update_load_set (& se -> load , weight );
3910
3800
@@ -3919,6 +3809,7 @@ static void reweight_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
3919
3809
enqueue_load_avg (cfs_rq , se );
3920
3810
if (se -> on_rq ) {
3921
3811
update_load_add (& cfs_rq -> load , se -> load .weight );
3812
+ place_entity (cfs_rq , se , 0 );
3922
3813
if (!curr )
3923
3814
__enqueue_entity (cfs_rq , se );
3924
3815
@@ -4065,7 +3956,11 @@ static void update_cfs_group(struct sched_entity *se)
4065
3956
struct cfs_rq * gcfs_rq = group_cfs_rq (se );
4066
3957
long shares ;
4067
3958
4068
- if (!gcfs_rq )
3959
+ /*
3960
+ * When a group becomes empty, preserve its weight. This matters for
3961
+ * DELAY_DEQUEUE.
3962
+ */
3963
+ if (!gcfs_rq || !gcfs_rq -> load .weight )
4069
3964
return ;
4070
3965
4071
3966
if (throttled_hierarchy (gcfs_rq ))
@@ -5359,7 +5254,7 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
5359
5254
5360
5255
se -> vruntime = vruntime - lag ;
5361
5256
5362
- if (sched_feat ( PLACE_REL_DEADLINE ) && se -> rel_deadline ) {
5257
+ if (se -> rel_deadline ) {
5363
5258
se -> deadline += se -> vruntime ;
5364
5259
se -> rel_deadline = 0 ;
5365
5260
return ;
0 commit comments