@@ -269,17 +269,13 @@ static void calc_avgs(unsigned long avg[3], int missed_periods,
269269 avg [2 ] = calc_load (avg [2 ], EXP_300s , pct );
270270}
271271
272- static bool update_stats (struct psi_group * group )
272+ static bool collect_percpu_times (struct psi_group * group )
273273{
274274 u64 deltas [NR_PSI_STATES - 1 ] = { 0 , };
275- unsigned long missed_periods = 0 ;
276275 unsigned long nonidle_total = 0 ;
277- u64 now , expires , period ;
278276 int cpu ;
279277 int s ;
280278
281- mutex_lock (& group -> avgs_lock );
282-
283279 /*
284280 * Collect the per-cpu time buckets and average them into a
285281 * single time sample that is normalized to wallclock time.
@@ -317,11 +313,18 @@ static bool update_stats(struct psi_group *group)
317313 for (s = 0 ; s < NR_PSI_STATES - 1 ; s ++ )
318314 group -> total [s ] += div_u64 (deltas [s ], max (nonidle_total , 1UL ));
319315
316+ return nonidle_total ;
317+ }
318+
319+ static u64 update_averages (struct psi_group * group , u64 now )
320+ {
321+ unsigned long missed_periods = 0 ;
322+ u64 expires , period ;
323+ u64 avg_next_update ;
324+ int s ;
325+
320326 /* avgX= */
321- now = sched_clock ();
322327 expires = group -> avg_next_update ;
323- if (now < expires )
324- goto out ;
325328 if (now - expires >= psi_period )
326329 missed_periods = div_u64 (now - expires , psi_period );
327330
@@ -332,7 +335,7 @@ static bool update_stats(struct psi_group *group)
332335 * But the deltas we sample out of the per-cpu buckets above
333336 * are based on the actual time elapsing between clock ticks.
334337 */
335- group -> avg_next_update = expires + ((1 + missed_periods ) * psi_period );
338+ avg_next_update = expires + ((1 + missed_periods ) * psi_period );
336339 period = now - (group -> avg_last_update + (missed_periods * psi_period ));
337340 group -> avg_last_update = now ;
338341
@@ -362,40 +365,41 @@ static bool update_stats(struct psi_group *group)
362365 group -> avg_total [s ] += sample ;
363366 calc_avgs (group -> avg [s ], missed_periods , sample , period );
364367 }
365- out :
366- mutex_unlock (& group -> avgs_lock );
367- return nonidle_total ;
368+
369+ return avg_next_update ;
368370}
369371
370372static void psi_avgs_work (struct work_struct * work )
371373{
372374 struct delayed_work * dwork ;
373375 struct psi_group * group ;
374376 bool nonidle ;
377+ u64 now ;
375378
376379 dwork = to_delayed_work (work );
377380 group = container_of (dwork , struct psi_group , avgs_work );
378381
382+ mutex_lock (& group -> avgs_lock );
383+
384+ now = sched_clock ();
385+
386+ nonidle = collect_percpu_times (group );
379387 /*
380388 * If there is task activity, periodically fold the per-cpu
381389 * times and feed samples into the running averages. If things
382390 * are idle and there is no data to process, stop the clock.
383391 * Once restarted, we'll catch up the running averages in one
384392 * go - see calc_avgs() and missed_periods.
385393 */
386-
387- nonidle = update_stats (group );
394+ if ( now >= group -> avg_next_update )
395+ group -> avg_next_update = update_averages (group , now );
388396
389397 if (nonidle ) {
390- unsigned long delay = 0 ;
391- u64 now ;
392-
393- now = sched_clock ();
394- if (group -> avg_next_update > now )
395- delay = nsecs_to_jiffies (
396- group -> avg_next_update - now ) + 1 ;
397- schedule_delayed_work (dwork , delay );
398+ schedule_delayed_work (dwork , nsecs_to_jiffies (
399+ group -> avg_next_update - now ) + 1 );
398400 }
401+
402+ mutex_unlock (& group -> avgs_lock );
399403}
400404
401405static void record_times (struct psi_group_cpu * groupc , int cpu ,
@@ -707,11 +711,18 @@ void cgroup_move_task(struct task_struct *task, struct css_set *to)
707711int psi_show (struct seq_file * m , struct psi_group * group , enum psi_res res )
708712{
709713 int full ;
714+ u64 now ;
710715
711716 if (static_branch_likely (& psi_disabled ))
712717 return - EOPNOTSUPP ;
713718
714- update_stats (group );
719+ /* Update averages before reporting them */
720+ mutex_lock (& group -> avgs_lock );
721+ now = sched_clock ();
722+ collect_percpu_times (group );
723+ if (now >= group -> avg_next_update )
724+ group -> avg_next_update = update_averages (group , now );
725+ mutex_unlock (& group -> avgs_lock );
715726
716727 for (full = 0 ; full < 2 - (res == PSI_CPU ); full ++ ) {
717728 unsigned long avg [3 ];
0 commit comments