On 2022/8/24 18:46, Johannes Weiner wrote: > On Wed, Aug 24, 2022 at 04:18:26PM +0800, Chengming Zhou wrote: >> @@ -903,6 +903,36 @@ void psi_task_switch(struct task_struct *prev, struct task_struct *next, >> } >> } >> >> +#ifdef CONFIG_IRQ_TIME_ACCOUNTING >> +void psi_account_irqtime(struct task_struct *task, u32 delta) >> +{ >> + int cpu = task_cpu(task); >> + void *iter = NULL; >> + struct psi_group *group; >> + struct psi_group_cpu *groupc; >> + u64 now; >> + >> + if (!task->pid) >> + return; >> + >> + now = cpu_clock(cpu); >> + >> + while ((group = iterate_groups(task, &iter))) { >> + groupc = per_cpu_ptr(group->pcpu, cpu); >> + >> + write_seqcount_begin(&groupc->seq); >> + >> + record_times(groupc, now); >> + groupc->times[PSI_IRQ_FULL] += delta; >> + >> + write_seqcount_end(&groupc->seq); >> + >> + if (group->poll_states & (1 << PSI_IRQ_FULL)) >> + psi_schedule_poll_work(group, 1); >> + } > > Shouldn't this kick avgs_work too? If the CPU is otherwise idle, > times[PSI_IRQ_FULL] would overflow after two missed averaging runs. If the CPU is idle, task->pid == 0, so no times[PSI_IRQ_FULL] would accumulate? I was thinking if task->pid != 0, avgs_work should be active. Not sure, maybe I missed something. > > avgs_work should probably also self-perpetuate when PSI_IRQ_FULL is in > changed_states. (Looking at that code, I think it can be simplified: > delete nonidle and do `if (changed_states) schedule_delayed_work()`.) ``` collect_percpu_times(group, PSI_AVGS, &changed_states); nonidle = changed_states & (1 << PSI_NONIDLE); if (nonidle) { schedule_delayed_work(dwork, nsecs_to_jiffies( group->avg_next_update - now) + 1); } ``` Yes, changed_states include PSI_IRQ_FULL, here we only check nonidle = changed_states & (1 << PSI_NONIDLE), so it will not restart if only PSI_IRQ_FULL? If use `if (changed_states) schedule_delayed_work()`, avgs_work will self-restart when only PSI_IRQ_FULL changes? Thanks!