when a task dequeued, it will update it's util, and cfs_rq_util_change would check rq's util, if the cfs_rq->avg.util_est.enqueued is bigger than cfs_rq->avg.util_avg, but because the cfs_rq->avg.util_est.enqueued didn't be decreased, this would cause bigger cfs_rq_util by mistake, as a result, cfs_rq_util_change may change freq unreasonablely.
separate the util_est_dequeue() into util_est_dequeue() and util_est_update(), and dequeue the _task_util_est(p) before update util. Signed-off-by: Xuewen Yan <[email protected]> --- kernel/sched/fair.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index ae7ceba..20ecfd5 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3946,11 +3946,9 @@ static inline bool within_margin(int value, int margin) } static void -util_est_dequeue(struct cfs_rq *cfs_rq, struct task_struct *p, bool task_sleep) +util_est_dequeue(struct cfs_rq *cfs_rq, struct task_struct *p) { - long last_ewma_diff; struct util_est ue; - int cpu; if (!sched_feat(UTIL_EST)) return; @@ -3961,6 +3959,17 @@ static inline bool within_margin(int value, int margin) WRITE_ONCE(cfs_rq->avg.util_est.enqueued, ue.enqueued); trace_sched_util_est_cfs_tp(cfs_rq); +} + +static void +util_est_update(struct cfs_rq *cfs_rq, struct task_struct *p, bool task_sleep) +{ + long last_ewma_diff; + struct util_est ue; + int cpu; + + if (!sched_feat(UTIL_EST)) + return; /* * Skip update of task's estimated utilization when the task has not @@ -4085,7 +4094,10 @@ static inline int newidle_balance(struct rq *rq, struct rq_flags *rf) util_est_enqueue(struct cfs_rq *cfs_rq, struct task_struct *p) {} static inline void -util_est_dequeue(struct cfs_rq *cfs_rq, struct task_struct *p, +util_est_dequeue(struct cfs_rq *cfs_rq, struct task_struct *p) {} + +static inline void +util_est_update(struct cfs_rq *cfs_rq, struct task_struct *p, bool task_sleep) {} static inline void update_misfit_status(struct task_struct *p, struct rq *rq) {} @@ -5589,6 +5601,8 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags) int idle_h_nr_running = task_has_idle_policy(p); bool was_sched_idle = sched_idle_rq(rq); + util_est_dequeue(&rq->cfs, p); + for_each_sched_entity(se) { cfs_rq = cfs_rq_of(se); dequeue_entity(cfs_rq, se, flags); @@ -5639,7 +5653,7 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags) rq->next_balance = jiffies; dequeue_throttle: - util_est_dequeue(&rq->cfs, p, task_sleep); + util_est_update(&rq->cfs, p, task_sleep); hrtick_update(rq); } -- 1.9.1

