Re: [PATCH v7 linux 1/2] sched/cache: Reduce the overhead of task_cache_work by only scan the visisted cpus

From: Tim Chen

Date: Tue Jul 21 2026 - 11:05:20 EST


On Tue, 2026-07-21 at 10:53 +0800, Luo Gengkun wrote:
>
>
snip

> > > -static unsigned long fraction_mm_sched(struct rq *rq,
> > > - struct sched_cache_time *pcpu_sched)
> > > +static unsigned long fraction_mm_sched(int cpu,
> > > + struct mm_struct *mm)
> > > {
> > > + struct sched_cache_time *pcpu_sched =
> > > + per_cpu_ptr(mm->sc_stat.pcpu_sched, cpu);
> > > + struct rq *rq = cpu_rq(cpu);
> > > +
> > > guard(raw_spinlock_irqsave)(&rq->cpu_epoch_lock);
> > >
> > > __update_mm_sched(rq, pcpu_sched);
> > >
> > > + /* Skip the rq that has not been hit for a long time */
> > > + if ((rq->cpu_epoch - pcpu_sched->epoch_last_visit) > llc_epoch_affinity_timeout) {
> > > + cpumask_clear_cpu(cpu, mm->sc_stat.visited_cpus);
> > > + return 0;
> > > + }
> > > +
> > > /*
> > > * Runtime is a geometric series (r=0.5) and as such will sum to twice
> > > * the accumulation period, this means the multiplcation here should
> > > @@ -1711,6 +1722,9 @@ void account_mm_sched(struct rq *rq, struct task_struct *p, s64 delta_exec)
> > > pcpu_sched->runtime += delta_exec;
> > > rq->cpu_runtime += delta_exec;
> > > epoch = rq->cpu_epoch;
> > > + pcpu_sched->epoch_last_visit = epoch;
> >
> > We need to make sure that the epoch_last_visit update is seen by the cpu
> > running task_cache_work(), before it attempts to do the epoch comparison
> > and clear the cpu, and causing inconsistency in the visited_cpus.
> >
> > For example
> >
> > CPU A (e.g. doing LLC/affinity selection, reading remote pcpu_sched) CPU B (= `cpu`, running account_mm_sched() locally)
> > -------------------------------------------------------------------- -----------------------------------------------------
> > read pcpu_sched->epoch_last_visit (stale, old value)
> > -> looks like it timed out
> > pcpu_sched->epoch_last_visit = epoch (fresh visit!)
> > cpumask_set_cpu(cpu, visited_cpus) (correctly marks it visited)
> > cpumask_clear_cpu(cpu, visited_cpus) <-- wipes out the fresh set!
> >
> I don't think such a race condition will occur, because both the read and clear
> operations in fraction_mm_sched() are protected by rq->cpu_epoch_lock, just like
> account_mm_sched(). Please let me know if I'm missing something.
>

Yes, the epoch lock should prevent the above race from happening.
Missed that on my end.

>
Thanks.

Tim