@@ -269,17 +269,13 @@ static void calc_avgs(unsigned long avg[3], int missed_periods,
269
269
avg [2 ] = calc_load (avg [2 ], EXP_300s , pct );
270
270
}
271
271
272
- static bool update_stats (struct psi_group * group )
272
+ static bool collect_percpu_times (struct psi_group * group )
273
273
{
274
274
u64 deltas [NR_PSI_STATES - 1 ] = { 0 , };
275
- unsigned long missed_periods = 0 ;
276
275
unsigned long nonidle_total = 0 ;
277
- u64 now , expires , period ;
278
276
int cpu ;
279
277
int s ;
280
278
281
- mutex_lock (& group -> avgs_lock );
282
-
283
279
/*
284
280
* Collect the per-cpu time buckets and average them into a
285
281
* single time sample that is normalized to wallclock time.
@@ -317,11 +313,18 @@ static bool update_stats(struct psi_group *group)
317
313
for (s = 0 ; s < NR_PSI_STATES - 1 ; s ++ )
318
314
group -> total [s ] += div_u64 (deltas [s ], max (nonidle_total , 1UL ));
319
315
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
+
320
326
/* avgX= */
321
- now = sched_clock ();
322
327
expires = group -> avg_next_update ;
323
- if (now < expires )
324
- goto out ;
325
328
if (now - expires >= psi_period )
326
329
missed_periods = div_u64 (now - expires , psi_period );
327
330
@@ -332,7 +335,7 @@ static bool update_stats(struct psi_group *group)
332
335
* But the deltas we sample out of the per-cpu buckets above
333
336
* are based on the actual time elapsing between clock ticks.
334
337
*/
335
- group -> avg_next_update = expires + ((1 + missed_periods ) * psi_period );
338
+ avg_next_update = expires + ((1 + missed_periods ) * psi_period );
336
339
period = now - (group -> avg_last_update + (missed_periods * psi_period ));
337
340
group -> avg_last_update = now ;
338
341
@@ -362,40 +365,41 @@ static bool update_stats(struct psi_group *group)
362
365
group -> avg_total [s ] += sample ;
363
366
calc_avgs (group -> avg [s ], missed_periods , sample , period );
364
367
}
365
- out :
366
- mutex_unlock (& group -> avgs_lock );
367
- return nonidle_total ;
368
+
369
+ return avg_next_update ;
368
370
}
369
371
370
372
static void psi_avgs_work (struct work_struct * work )
371
373
{
372
374
struct delayed_work * dwork ;
373
375
struct psi_group * group ;
374
376
bool nonidle ;
377
+ u64 now ;
375
378
376
379
dwork = to_delayed_work (work );
377
380
group = container_of (dwork , struct psi_group , avgs_work );
378
381
382
+ mutex_lock (& group -> avgs_lock );
383
+
384
+ now = sched_clock ();
385
+
386
+ nonidle = collect_percpu_times (group );
379
387
/*
380
388
* If there is task activity, periodically fold the per-cpu
381
389
* times and feed samples into the running averages. If things
382
390
* are idle and there is no data to process, stop the clock.
383
391
* Once restarted, we'll catch up the running averages in one
384
392
* go - see calc_avgs() and missed_periods.
385
393
*/
386
-
387
- nonidle = update_stats (group );
394
+ if ( now >= group -> avg_next_update )
395
+ group -> avg_next_update = update_averages (group , now );
388
396
389
397
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 );
398
400
}
401
+
402
+ mutex_unlock (& group -> avgs_lock );
399
403
}
400
404
401
405
static 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)
707
711
int psi_show (struct seq_file * m , struct psi_group * group , enum psi_res res )
708
712
{
709
713
int full ;
714
+ u64 now ;
710
715
711
716
if (static_branch_likely (& psi_disabled ))
712
717
return - EOPNOTSUPP ;
713
718
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 );
715
726
716
727
for (full = 0 ; full < 2 - (res == PSI_CPU ); full ++ ) {
717
728
unsigned long avg [3 ];
0 commit comments