@@ -12122,11 +12122,27 @@ void update_max_interval(void)
1212212122 max_load_balance_interval = HZ * num_online_cpus ()/10 ;
1212312123}
1212412124
12125- static inline bool update_newidle_cost (struct sched_domain * sd , u64 cost )
12125+ static inline void update_newidle_stats (struct sched_domain * sd , unsigned int success )
12126+ {
12127+ sd -> newidle_call ++ ;
12128+ sd -> newidle_success += success ;
12129+
12130+ if (sd -> newidle_call >= 1024 ) {
12131+ sd -> newidle_ratio = sd -> newidle_success ;
12132+ sd -> newidle_call /= 2 ;
12133+ sd -> newidle_success /= 2 ;
12134+ }
12135+ }
12136+
12137+ static inline bool
12138+ update_newidle_cost (struct sched_domain * sd , u64 cost , unsigned int success )
1212612139{
1212712140 unsigned long next_decay = sd -> last_decay_max_lb_cost + HZ ;
1212812141 unsigned long now = jiffies ;
1212912142
12143+ if (cost )
12144+ update_newidle_stats (sd , success );
12145+
1213012146 if (cost > sd -> max_newidle_lb_cost ) {
1213112147 /*
1213212148 * Track max cost of a domain to make sure to not delay the
@@ -12174,7 +12190,7 @@ static void sched_balance_domains(struct rq *rq, enum cpu_idle_type idle)
1217412190 * Decay the newidle max times here because this is a regular
1217512191 * visit to all the domains.
1217612192 */
12177- need_decay = update_newidle_cost (sd , 0 );
12193+ need_decay = update_newidle_cost (sd , 0 , 0 );
1217812194 max_cost += sd -> max_newidle_lb_cost ;
1217912195
1218012196 /*
@@ -12819,17 +12835,37 @@ static int sched_balance_newidle(struct rq *this_rq, struct rq_flags *rf)
1281912835 break ;
1282012836
1282112837 if (sd -> flags & SD_BALANCE_NEWIDLE ) {
12838+ unsigned int weight = 1 ;
12839+
12840+ if (sched_feat (NI_RANDOM )) {
12841+ /*
12842+ * Throw a 1k sided dice; and only run
12843+ * newidle_balance according to the success
12844+ * rate.
12845+ */
12846+ u32 d1k = sched_rng () % 1024 ;
12847+ weight = 1 + sd -> newidle_ratio ;
12848+ if (d1k > weight ) {
12849+ update_newidle_stats (sd , 0 );
12850+ continue ;
12851+ }
12852+ weight = (1024 + weight /2 ) / weight ;
12853+ }
1282212854
1282312855 pulled_task = sched_balance_rq (this_cpu , this_rq ,
1282412856 sd , CPU_NEWLY_IDLE ,
1282512857 & continue_balancing );
1282612858
1282712859 t1 = sched_clock_cpu (this_cpu );
1282812860 domain_cost = t1 - t0 ;
12829- update_newidle_cost (sd , domain_cost );
12830-
1283112861 curr_cost += domain_cost ;
1283212862 t0 = t1 ;
12863+
12864+ /*
12865+ * Track max cost of a domain to make sure to not delay the
12866+ * next wakeup on the CPU.
12867+ */
12868+ update_newidle_cost (sd , domain_cost , weight * !!pulled_task );
1283312869 }
1283412870
1283512871 /*
0 commit comments