hulk inclusion category: bugfix bugzilla: https://atomgit.com/openeuler/kernel/issues/8555 -------------------------------- Fix kabi breakage pf struct sched_domain for newidle_stats Signed-off-by: Chen Jinghuang <chenjinghuang2@huawei.com> --- include/linux/sched/topology.h | 15 ++++++++--- kernel/sched/fair.c | 48 +++++++++++++++++++++++++++++----- kernel/sched/topology.c | 11 +++++--- 3 files changed, 61 insertions(+), 13 deletions(-) diff --git a/include/linux/sched/topology.h b/include/linux/sched/topology.h index 95e5d7772800..20d3db415cd2 100644 --- a/include/linux/sched/topology.h +++ b/include/linux/sched/topology.h @@ -108,6 +108,17 @@ struct sched_domain_shared { #endif }; +#define NEWIDLE_CALL_BITS 12 +#define NEWIDLE_CALL_MASK ((1U << NEWIDLE_CALL_BITS) - 1) + +#define NEWIDLE_SUCCESS_BITS 10 +#define NEWIDLE_SUCCESS_SHIFT NEWIDLE_CALL_BITS +#define NEWIDLE_SUCCESS_MASK (((1U << NEWIDLE_SUCCESS_BITS) - 1) << NEWIDLE_SUCCESS_SHIFT) + +#define NEWIDLE_RATIO_BITS 10 +#define NEWIDLE_RATIO_SHIFT (NEWIDLE_CALL_BITS + NEWIDLE_SUCCESS_BITS) +#define NEWIDLE_RATIO_MASK (((1U << NEWIDLE_RATIO_BITS) - 1) << NEWIDLE_RATIO_SHIFT) + struct sched_domain { /* These fields must be setup */ struct sched_domain __rcu *parent; /* top domain must be null terminated */ @@ -130,9 +141,7 @@ struct sched_domain { unsigned int nr_balance_failed; /* initialise to 0 */ /* idle_balance() stats */ - unsigned int newidle_call; - unsigned int newidle_success; - unsigned int newidle_ratio; + u32 newidle_stats; u64 max_newidle_lb_cost; unsigned long last_decay_max_lb_cost; diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index d16c65d5fa34..c38fbe023e26 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -13651,16 +13651,50 @@ void update_max_interval(void) max_load_balance_interval = HZ*num_online_cpus()/10; } +#define get_newidle_call(stats) ((stats) & NEWIDLE_CALL_MASK) + +#define get_newidle_success(stats) \ + (((stats) >> NEWIDLE_SUCCESS_SHIFT) & ((1U << NEWIDLE_SUCCESS_BITS) - 1)) + +#define get_newidle_ratio(stats) \ + (((stats) >> NEWIDLE_RATIO_SHIFT) & ((1U << NEWIDLE_RATIO_BITS) - 1)) + +#define set_newidle_call(stats_ptr, val) \ + ({ \ + *(stats_ptr) = (*(stats_ptr) & ~NEWIDLE_CALL_MASK) | \ + ((val) & NEWIDLE_CALL_MASK); \ + }) + +#define set_newidle_success(stats_ptr, val) \ + ({ \ + *(stats_ptr) = (*(stats_ptr) & ~NEWIDLE_SUCCESS_MASK) | \ + (((val) & ((1U << NEWIDLE_SUCCESS_BITS) - 1)) \ + << NEWIDLE_SUCCESS_SHIFT); \ + }) + +#define set_newidle_ratio(stats_ptr, val) \ + ({ \ + *(stats_ptr) = (*(stats_ptr) & ~NEWIDLE_RATIO_MASK) | \ + (((val) & ((1U << NEWIDLE_RATIO_BITS) - 1)) \ + << NEWIDLE_RATIO_SHIFT); \ + }) + static inline void update_newidle_stats(struct sched_domain *sd, unsigned int success) { - sd->newidle_call++; - sd->newidle_success += success; + u32 call = get_newidle_call(sd->newidle_stats) + 1; + u32 succ = get_newidle_success(sd->newidle_stats) + success; + + if (call >= 1024) { + u32 ratio = min_t(u32, succ, (1U << NEWIDLE_RATIO_BITS) - 1); - if (sd->newidle_call >= 1024) { - sd->newidle_ratio = sd->newidle_success; - sd->newidle_call /= 2; - sd->newidle_success /= 2; + set_newidle_ratio(&sd->newidle_stats, ratio); + set_newidle_call(&sd->newidle_stats, call / 2); + set_newidle_success(&sd->newidle_stats, succ / 2); + return; } + + set_newidle_call(&sd->newidle_stats, call); + set_newidle_success(&sd->newidle_stats, succ); } static inline bool @@ -14361,7 +14395,7 @@ static int newidle_balance(struct rq *this_rq, struct rq_flags *rf) * rate. */ u32 d1k = sched_rng() % 1024; - weight = 1 + sd->newidle_ratio; + weight = 1 + get_newidle_ratio(sd->newidle_stats); if (d1k > weight) { update_newidle_stats(sd, 0); continue; diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c index cf847fdf1063..150e81ae476d 100644 --- a/kernel/sched/topology.c +++ b/kernel/sched/topology.c @@ -1573,6 +1573,13 @@ static int *sched_domains_numa_distance; static struct cpumask ***sched_domains_numa_masks; #endif +#define NEWIDLE_STATS_INIT(call, success, ratio) \ + (((call) & ((1U << NEWIDLE_CALL_BITS) - 1)) | \ + (((success) & ((1U << NEWIDLE_SUCCESS_BITS) - 1)) << \ + NEWIDLE_SUCCESS_SHIFT) | \ + (((ratio) & ((1U << NEWIDLE_RATIO_BITS) - 1)) << \ + NEWIDLE_RATIO_SHIFT)) + /* * SD_flags allowed in topology descriptions. * @@ -1646,9 +1653,7 @@ sd_init(struct sched_domain_topology_level *tl, .balance_interval = sd_weight, /* 50% success rate */ - .newidle_call = 512, - .newidle_success = 256, - .newidle_ratio = 512, + .newidle_stats = NEWIDLE_STATS_INIT(512, 256, 512), .max_newidle_lb_cost = 0, .last_decay_max_lb_cost = jiffies, -- 2.34.1